diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ba99ea..2f91cb2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,33 +30,21 @@ add_subdirectory(softfloat) FILE(GLOB RiscVSCHeaders ${CMAKE_CURRENT_SOURCE_DIR}/incl/sysc/*.h ${CMAKE_CURRENT_SOURCE_DIR}/incl/sysc/*/*.h) set(LIB_HEADERS ${RiscVSCHeaders} ) set(LIB_SOURCES - src/iss/rv32gc.cpp - src/iss/rv32imac.cpp - src/iss/rv64i.cpp - src/iss/rv64gc.cpp - src/iss/mnrv32.cpp + src/iss/tgf01.cpp + src/iss/tgf02.cpp src/vm/fp_functions.cpp - src/vm/tcc/vm_mnrv32.cpp - src/vm/tcc/vm_rv32gc.cpp - src/vm/tcc/vm_rv32imac.cpp - src/vm/tcc/vm_rv64i.cpp - src/vm/tcc/vm_rv64gc.cpp - src/vm/interp/vm_mnrv32.cpp - src/vm/interp/vm_rv32gc.cpp - src/vm/interp/vm_rv32imac.cpp - src/vm/interp/vm_rv64i.cpp - src/vm/interp/vm_rv64gc.cpp + src/vm/tcc/vm_tgf01.cpp + src/vm/tcc/vm_tgf02.cpp + src/vm/interp/vm_tgf01.cpp + src/vm/interp/vm_tgf02.cpp src/plugin/instruction_count.cpp src/plugin/cycle_estimate.cpp ) if(WITH_LLVM) set(LIB_SOURCES ${LIB_SOURCES} src/vm/llvm/fp_impl.cpp - src/vm/llvm/vm_mnrv32.cpp - src/vm/llvm/vm_rv32gc.cpp - src/vm/llvm/vm_rv32imac.cpp - src/vm/llvm/vm_rv64i.cpp - src/vm/llvm/vm_rv64gc.cpp + src/vm/llvm/vm_tgf01.cpp + src/vm/llvm/vm_tgf02.cpp ) endif() diff --git a/CMakeLists.txt.orig b/CMakeLists.txt.orig deleted file mode 100644 index 8b70e49..0000000 --- a/CMakeLists.txt.orig +++ /dev/null @@ -1,119 +0,0 @@ -cmake_minimum_required(VERSION 3.3) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_CURRENT_SOURCE_DIR}/sc-components/cmake) - -set(ENABLE_SCV TRUE CACHE BOOL "Enable use of SCV") -set(ENABLE_SHARED TRUE CACHE BOOL "Build shared libraries") - -include(GitFunctions) -get_branch_from_git() -# if we are not on master or develop set the submodules to develop -IF(NOT ${GIT_BRANCH} MATCHES "master") - IF(NOT ${GIT_BRANCH} MATCHES "develop") - message(STATUS "main branch is '${GIT_BRANCH}', setting submodules to 'develop'") - set(GIT_BRANCH develop) - endif() -endif() - -### set the directory names of the submodules -set(GIT_SUBMODULES elfio libGIS sc-components dbt-core) -set(GIT_SUBMODULE_DIR_sc-components .) -set(GIT_SUBMODULE_DIR_dbt-core .) -### set each submodules's commit or tag that is to be checked out -### (leave empty if you want master) -#set(GIT_SUBMODULE_VERSION_sc-comp 3af6b9836589b082c19d9131c5d0b7afa8ddd7cd) -set(GIT_SUBMODULE_BRANCH_sc-components ${GIT_BRANCH}) -set(GIT_SUBMODULE_BRANCH_dbt-core ${GIT_BRANCH}) - -include(GNUInstallDirs) -include(Submodules) -include(Conan) - -#enable_testing() - -set(CMAKE_CXX_STANDARD 14) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -include(CheckCXXCompilerFlag) -CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) -if(COMPILER_SUPPORTS_MARCH_NATIVE) -if("${CMAKE_BUILD_TYPE}" STREQUAL "") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") -elseif(NOT(${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") -endif() -endif() - -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - set(warnings "-Wall -Wextra -Werror") - #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_USE_CXX11_ABI=0") - set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") - set(CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG") -elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(warnings "/W4 /WX /EHsc") -endif() - -setup_conan() - -# This line finds the boost lib and headers. -set(Boost_NO_BOOST_CMAKE ON) # Don't do a find_package in config mode before searching for a regular boost install. -find_package(Boost COMPONENTS program_options system thread filesystem REQUIRED) - -if(DEFINED ENV{LLVM_HOME}) - find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm) -endif(DEFINED ENV{LLVM_HOME}) -find_package(LLVM REQUIRED CONFIG) -message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") -message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") -llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser) - -find_package(Threads) -find_package(Tcmalloc) -find_package(ZLIB) -find_package(SystemC) -if(SystemC_FOUND) - message(STATUS "SystemC headers at ${SystemC_INCLUDE_DIRS}") - message(STATUS "SystemC library at ${SystemC_LIBRARY_DIRS}") - if(SCV_FOUND) - message(STATUS "SCV headers at ${SCV_INCLUDE_DIRS}") - message(STATUS "SCV library at ${SCV_LIBRARY_DIRS}") - endif(SCV_FOUND) - if(CCI_FOUND) - message(STATUS "CCI headers at ${CCI_INCLUDE_DIRS}") - message(STATUS "CCI library at ${CCI_LIBRARY_DIRS}") - endif() -endif(SystemC_FOUND) - -set(PROJECT_3PARTY_DIRS external) -include(clang-format) - -set(ENABLE_CLANG_TIDY OFF CACHE BOOL "Add clang-tidy automatically to builds") -if (ENABLE_CLANG_TIDY) - find_program (CLANG_TIDY_EXE NAMES "clang-tidy" PATHS /usr/local/opt/llvm/bin ) - if (CLANG_TIDY_EXE) - message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") - set(CLANG_TIDY_CHECKS "-*,modernize-*") - set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE};-checks=${CLANG_TIDY_CHECKS};-header-filter='${CMAKE_SOURCE_DIR}/*';-fix" - CACHE STRING "" FORCE) - else() - message(AUTHOR_WARNING "clang-tidy not found!") - set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it - endif() -endif() - -# Set the version number of your project here (format is MAJOR.MINOR.PATCHLEVEL - e.g. 1.0.0) -set(VERSION_MAJOR "1") -set(VERSION_MINOR "0") -set(VERSION_PATCH "0") -set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) - -add_subdirectory(external) -add_subdirectory(dbt-core) -add_subdirectory(sc-components) -add_subdirectory(softfloat) -GET_DIRECTORY_PROPERTY(SOFTFLOAT_INCLUDE_DIRS DIRECTORY softfloat DEFINITION SOFTFLOAT_INCLUDE_DIRS) -add_subdirectory(riscv) -add_subdirectory(platform) - -message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") diff --git a/gen_input/TGFS.core_desc b/gen_input/TGFS.core_desc index c93377e..eb7e963 100644 --- a/gen_input/TGFS.core_desc +++ b/gen_input/TGFS.core_desc @@ -1,6 +1,6 @@ -import "RV32I.core_desc" -import "RVM.core_desc" -import "RVC.core_desc" +import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" +import "CoreDSL-Instruction-Set-Description/RVM.core_desc" +import "CoreDSL-Instruction-Set-Description/RVC.core_desc" Core TGF01 provides RV32I { constants { @@ -9,6 +9,8 @@ Core TGF01 provides RV32I { // definitions for the architecture wrapper // XL ZYXWVUTSRQPONMLKJIHGFEDCBA MISA_VAL:=0b01000000000000000000000100000000; + PGSIZE := 0x1000; //1 << 12; + PGMASK := 0xfff; //PGSIZE-1 } } @@ -20,5 +22,7 @@ Core TGF02 provides RV32I, RV32M, RV32IC { // definitions for the architecture wrapper // XL ZYXWVUTSRQPONMLKJIHGFEDCBA MISA_VAL:=0b01000000000000000001000100000100; + PGSIZE := 0x1000; //1 << 12; + PGMASK := 0xfff; //PGSIZE-1 } } \ No newline at end of file diff --git a/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl index 85dd233..17dd09d 100644 --- a/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl @@ -32,7 +32,7 @@ #include "../fp_functions.h" #include -#include +#include #include #include #include diff --git a/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl index 34b618d..881cb30 100644 --- a/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl @@ -31,7 +31,7 @@ *******************************************************************************/ #include -#include +#include #include #include #include diff --git a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl index d6b5214..23c5dd0 100644 --- a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl @@ -31,7 +31,7 @@ *******************************************************************************/ #include -#include +#include #include #include #include diff --git a/incl/iss/arch/mnrv32.h b/incl/iss/arch/mnrv32.h deleted file mode 100644 index 33f97ce..0000000 --- a/incl/iss/arch/mnrv32.h +++ /dev/null @@ -1,252 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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 _MNRV32_H_ -#define _MNRV32_H_ - -#include -#include -#include -#include - -namespace iss { -namespace arch { - -struct mnrv32; - -template <> struct traits { - - constexpr static char const* const core_type = "MNRV32"; - - 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"}}; - - static constexpr std::array reg_aliases{ - {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}}; - - enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000101000001000100000101, PGSIZE=0x1000, PGMASK=0xfff}; - - 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, - NUM_REGS, - NEXT_PC=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - LAST_BRANCH, - ICOUNT, - ZERO = X0, - RA = X1, - SP = X2, - GP = X3, - TP = X4, - T0 = X5, - T1 = X6, - T2 = X7, - S0 = X8, - S1 = X9, - A0 = X10, - A1 = X11, - A2 = X12, - A3 = X13, - A4 = X14, - A5 = X15, - A6 = X16, - A7 = X17, - S2 = X18, - S3 = X19, - S4 = X20, - S5 = X21, - S6 = X22, - S7 = X23, - S8 = X24, - S9 = X25, - S10 = X26, - S11 = X27, - T3 = X28, - T4 = X29, - T5 = X30, - T6 = X31 - }; - - 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,32,32,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,140,144,148,152,160}}; - - 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 }; -}; - -struct mnrv32: 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; - - mnrv32(); - ~mnrv32(); - - 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 MNRV32_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; - 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 /* _MNRV32_H_ */ diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/incl/iss/arch/riscv_hart_m_p.h similarity index 84% rename from incl/iss/arch/riscv_hart_msu_vp.h rename to incl/iss/arch/riscv_hart_m_p.h index 0d81aa0..5ee76f3 100644 --- a/incl/iss/arch/riscv_hart_msu_vp.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -268,10 +268,10 @@ public: }; } -template class riscv_hart_msu_vp : public BASE { +template class riscv_hart_m_p : public BASE { public: using super = BASE; - using this_class = riscv_hart_msu_vp; + using this_class = riscv_hart_m_p; using virt_addr_t = typename super::virt_addr_t; using phys_addr_t = typename super::phys_addr_t; using reg_t = typename super::reg_t; @@ -360,97 +360,6 @@ public: return {0, 0, 0, 0}; // dummy } }; - // specialization 64bit - template class hart_state::value>::type> { - public: - BEGIN_BF_DECL(mstatus_t, T); - // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) - BF_FIELD(SD, 63, 1); - // value of XLEN for S-mode - BF_FIELD(SXL, 34, 2); - // value of XLEN for U-mode - BF_FIELD(UXL, 32, 2); - // Trap SRET - BF_FIELD(TSR, 22, 1); - // Timeout Wait - BF_FIELD(TW, 21, 1); - // Trap Virtual Memory - BF_FIELD(TVM, 20, 1); - // Make eXecutable Readable - BF_FIELD(MXR, 19, 1); - // permit Supervisor User Memory access - BF_FIELD(SUM, 18, 1); - // Modify PRiVilege - BF_FIELD(MPRV, 17, 1); - // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty - BF_FIELD(XS, 15, 2); - // floating-point unit status Off/Initial/Clean/Dirty - BF_FIELD(FS, 13, 2); - // machine previous privilege - BF_FIELD(MPP, 11, 2); - // supervisor previous privilege - BF_FIELD(SPP, 8, 1); - // previous machine interrupt-enable - BF_FIELD(MPIE, 7, 1); - // previous supervisor interrupt-enable - BF_FIELD(SPIE, 5, 1); - // previous user interrupt-enable - BF_FIELD(UPIE, 4, 1); - // machine interrupt-enable - BF_FIELD(MIE, 3, 1); - // supervisor interrupt-enable - BF_FIELD(SIE, 1, 1); - // user interrupt-enable - BF_FIELD(UIE, 0, 1); - END_BF_DECL(); - - mstatus_t mstatus; - - static const reg_t mstatus_reset_val = 0xa00000000; - - void write_mstatus(T val, unsigned priv_lvl) { - T old_val = mstatus; - auto mask = get_mask(priv_lvl); - auto new_val = (old_val & ~mask) | (val & mask); - if ((new_val & mstatus.SXL.Mask) == 0) { - new_val |= old_val & mstatus.SXL.Mask; - } - if ((new_val & mstatus.UXL.Mask) == 0) { - new_val |= old_val & mstatus.UXL.Mask; - } - mstatus = new_val; - } - - T satp; - - static constexpr T get_misa() { return (2ULL << 62) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; } - - static constexpr T get_mask(unsigned priv_lvl) { - uint64_t ret; - switch (priv_lvl) { - case PRIV_U: ret = 0x8000000f00000011ULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 - case PRIV_S: ret = 0x8000000f000de133ULL;break; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011 - default: ret = 0x8000000f007ff9ddULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 - } - return ret; - } - - static inline vm_info decode_vm_info(uint32_t state, T sptbr) { - if (state == PRIV_M) return {0, 0, 0, 0}; - if (state <= PRIV_S) - switch (bit_sub<60, 4>(sptbr)) { - case 0: return {0, 0, 0, 0}; // off - case 8: return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV39 - case 9: return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV48 - case 10: return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV57 - case 11: return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV64 - default: abort(); - } - abort(); - return {0, 0, 0, 0}; // dummy - } - }; - const typename super::reg_t PGSIZE = 1 << PGSHIFT; const typename super::reg_t PGMASK = PGSIZE - 1; @@ -464,8 +373,8 @@ public: return m[mode]; } - riscv_hart_msu_vp(); - virtual ~riscv_hart_msu_vp() = default; + riscv_hart_m_p(); + virtual ~riscv_hart_m_p() = default; void reset(uint64_t address) override; @@ -478,7 +387,7 @@ public: iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, const uint8_t *const data) override; - virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data); } + virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data); } virtual uint64_t enter_trap(uint64_t flags, uint64_t addr) override; virtual uint64_t leave_trap(uint64_t flags) override; void wait_until(uint64_t flags) override; @@ -493,7 +402,7 @@ public: protected: struct riscv_instrumentation_if : public iss::instrumentation_if { - riscv_instrumentation_if(riscv_hart_msu_vp &arch) + riscv_instrumentation_if(riscv_hart_m_p &arch) : arch(arch) {} /** * get the name of this architecture @@ -508,7 +417,7 @@ protected: virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; - riscv_hart_msu_vp &arch; + riscv_hart_m_p &arch; }; friend struct riscv_instrumentation_if; @@ -561,7 +470,7 @@ protected: }; template -riscv_hart_msu_vp::riscv_hart_msu_vp() +riscv_hart_m_p::riscv_hart_m_p() : state() , cycle_offset(0) , instr_if(*this) { @@ -572,43 +481,43 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() for (unsigned addr = mcycle; addr <= hpmcounter31; ++addr) csr_wr_cb[addr] = nullptr; for (unsigned addr = mcycleh; addr <= hpmcounter31h; ++addr) csr_wr_cb[addr] = nullptr; // special handling - csr_rd_cb[time] = &riscv_hart_msu_vp::read_time; + csr_rd_cb[time] = &riscv_hart_m_p::read_time; csr_wr_cb[time] = nullptr; - csr_rd_cb[timeh] = &riscv_hart_msu_vp::read_time; + csr_rd_cb[timeh] = &riscv_hart_m_p::read_time; csr_wr_cb[timeh] = nullptr; - csr_rd_cb[mcycle] = &riscv_hart_msu_vp::read_cycle; - csr_rd_cb[mcycleh] = &riscv_hart_msu_vp::read_cycle; - csr_rd_cb[minstret] = &riscv_hart_msu_vp::read_cycle; - csr_rd_cb[minstreth] = &riscv_hart_msu_vp::read_cycle; - csr_rd_cb[mstatus] = &riscv_hart_msu_vp::read_status; - csr_wr_cb[mstatus] = &riscv_hart_msu_vp::write_status; - csr_rd_cb[sstatus] = &riscv_hart_msu_vp::read_status; - csr_wr_cb[sstatus] = &riscv_hart_msu_vp::write_status; - csr_rd_cb[ustatus] = &riscv_hart_msu_vp::read_status; - csr_wr_cb[ustatus] = &riscv_hart_msu_vp::write_status; - csr_rd_cb[mip] = &riscv_hart_msu_vp::read_ip; - csr_wr_cb[mip] = &riscv_hart_msu_vp::write_ip; - csr_rd_cb[sip] = &riscv_hart_msu_vp::read_ip; - csr_wr_cb[sip] = &riscv_hart_msu_vp::write_ip; - csr_rd_cb[uip] = &riscv_hart_msu_vp::read_ip; - csr_wr_cb[uip] = &riscv_hart_msu_vp::write_ip; - csr_rd_cb[mie] = &riscv_hart_msu_vp::read_ie; - csr_wr_cb[mie] = &riscv_hart_msu_vp::write_ie; - csr_rd_cb[sie] = &riscv_hart_msu_vp::read_ie; - csr_wr_cb[sie] = &riscv_hart_msu_vp::write_ie; - csr_rd_cb[uie] = &riscv_hart_msu_vp::read_ie; - csr_wr_cb[uie] = &riscv_hart_msu_vp::write_ie; - csr_rd_cb[satp] = &riscv_hart_msu_vp::read_satp; - csr_wr_cb[satp] = &riscv_hart_msu_vp::write_satp; - csr_rd_cb[fcsr] = &riscv_hart_msu_vp::read_fcsr; - csr_wr_cb[fcsr] = &riscv_hart_msu_vp::write_fcsr; - csr_rd_cb[fflags] = &riscv_hart_msu_vp::read_fcsr; - csr_wr_cb[fflags] = &riscv_hart_msu_vp::write_fcsr; - csr_rd_cb[frm] = &riscv_hart_msu_vp::read_fcsr; - csr_wr_cb[frm] = &riscv_hart_msu_vp::write_fcsr; + csr_rd_cb[mcycle] = &riscv_hart_m_p::read_cycle; + csr_rd_cb[mcycleh] = &riscv_hart_m_p::read_cycle; + csr_rd_cb[minstret] = &riscv_hart_m_p::read_cycle; + csr_rd_cb[minstreth] = &riscv_hart_m_p::read_cycle; + csr_rd_cb[mstatus] = &riscv_hart_m_p::read_status; + csr_wr_cb[mstatus] = &riscv_hart_m_p::write_status; + csr_rd_cb[sstatus] = &riscv_hart_m_p::read_status; + csr_wr_cb[sstatus] = &riscv_hart_m_p::write_status; + csr_rd_cb[ustatus] = &riscv_hart_m_p::read_status; + csr_wr_cb[ustatus] = &riscv_hart_m_p::write_status; + csr_rd_cb[mip] = &riscv_hart_m_p::read_ip; + csr_wr_cb[mip] = &riscv_hart_m_p::write_ip; + csr_rd_cb[sip] = &riscv_hart_m_p::read_ip; + csr_wr_cb[sip] = &riscv_hart_m_p::write_ip; + csr_rd_cb[uip] = &riscv_hart_m_p::read_ip; + csr_wr_cb[uip] = &riscv_hart_m_p::write_ip; + csr_rd_cb[mie] = &riscv_hart_m_p::read_ie; + csr_wr_cb[mie] = &riscv_hart_m_p::write_ie; + csr_rd_cb[sie] = &riscv_hart_m_p::read_ie; + csr_wr_cb[sie] = &riscv_hart_m_p::write_ie; + csr_rd_cb[uie] = &riscv_hart_m_p::read_ie; + csr_wr_cb[uie] = &riscv_hart_m_p::write_ie; + csr_rd_cb[satp] = &riscv_hart_m_p::read_satp; + csr_wr_cb[satp] = &riscv_hart_m_p::write_satp; + csr_rd_cb[fcsr] = &riscv_hart_m_p::read_fcsr; + csr_wr_cb[fcsr] = &riscv_hart_m_p::write_fcsr; + csr_rd_cb[fflags] = &riscv_hart_m_p::read_fcsr; + csr_wr_cb[fflags] = &riscv_hart_m_p::write_fcsr; + csr_rd_cb[frm] = &riscv_hart_m_p::read_fcsr; + csr_wr_cb[frm] = &riscv_hart_m_p::write_fcsr; } -template std::pair riscv_hart_msu_vp::load_file(std::string name, int type) { +template std::pair riscv_hart_m_p::load_file(std::string name, int type) { FILE *fp = fopen(name.c_str(), "r"); if (fp) { std::array buf; @@ -653,7 +562,7 @@ template std::pair riscv_hart_msu_vp::load } template -iss::status riscv_hart_msu_vp::read(const address_type type, const access_type access, const uint32_t space, +iss::status riscv_hart_m_p::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, uint8_t *const data) { #ifndef NDEBUG if (access && iss::access_type::DEBUG) { @@ -733,7 +642,7 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ } template -iss::status riscv_hart_msu_vp::write(const address_type type, const access_type access, const uint32_t space, +iss::status riscv_hart_m_p::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, const uint8_t *const data) { #ifndef NDEBUG const char *prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; @@ -855,7 +764,7 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access } } -template iss::status riscv_hart_msu_vp::read_csr(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_csr(unsigned addr, reg_t &val) { if (addr >= csr.size()) return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); @@ -869,7 +778,7 @@ template iss::status riscv_hart_msu_vp::read_csr(unsigned return (this->*f)(addr, val); } -template iss::status riscv_hart_msu_vp::write_csr(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_csr(unsigned addr, reg_t val) { if (addr >= csr.size()) return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; if (this->reg.machine_state < req_priv_lvl) @@ -886,7 +795,7 @@ template iss::status riscv_hart_msu_vp::write_csr(unsigned return (this->*f)(addr, val); } -template iss::status riscv_hart_msu_vp::read_cycle(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { auto cycle_val = this->reg.icount + cycle_offset; if (addr == mcycle) { val = static_cast(cycle_val); @@ -897,7 +806,7 @@ template iss::status riscv_hart_msu_vp::read_cycle(unsigne return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_time(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t &val) { uint64_t time_val = (this->reg.icount + cycle_offset) / (100000000 / 32768 - 1); //-> ~3052; if (addr == time) { val = static_cast(time_val); @@ -908,13 +817,13 @@ template iss::status riscv_hart_msu_vp::read_time(unsigned return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_status(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_status(unsigned addr, reg_t &val) { auto req_priv_lvl = (addr >> 8) & 0x3; val = state.mstatus & hart_state::get_mask(req_priv_lvl); return iss::Ok; } -template iss::status riscv_hart_msu_vp::write_status(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_status(unsigned addr, reg_t val) { auto req_priv_lvl = (addr >> 8) & 0x3; state.write_mstatus(val, req_priv_lvl); check_interrupt(); @@ -922,14 +831,14 @@ template iss::status riscv_hart_msu_vp::write_status(unsig return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_ie(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_ie(unsigned addr, reg_t &val) { val = csr[mie]; if (addr < mie) val &= csr[mideleg]; if (addr < sie) val &= csr[sideleg]; return iss::Ok; } -template iss::status riscv_hart_msu_vp::write_ie(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_ie(unsigned addr, reg_t val) { auto req_priv_lvl = (addr >> 8) & 0x3; auto mask = get_irq_mask(req_priv_lvl); csr[mie] = (csr[mie] & ~mask) | (val & mask); @@ -937,14 +846,14 @@ template iss::status riscv_hart_msu_vp::write_ie(unsigned return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_ip(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_ip(unsigned addr, reg_t &val) { val = csr[mip]; if (addr < mip) val &= csr[mideleg]; if (addr < sip) val &= csr[sideleg]; return iss::Ok; } -template iss::status riscv_hart_msu_vp::write_ip(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_ip(unsigned addr, reg_t val) { auto req_priv_lvl = (addr >> 8) & 0x3; auto mask = get_irq_mask(req_priv_lvl); mask &= ~(1 << 7); // MTIP is read only @@ -953,7 +862,7 @@ template iss::status riscv_hart_msu_vp::write_ip(unsigned return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_satp(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_satp(unsigned addr, reg_t &val) { reg_t tvm = state.mstatus.TVM; if (this->reg.machine_state == PRIV_S & tvm != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); @@ -964,7 +873,7 @@ template iss::status riscv_hart_msu_vp::read_satp(unsigned return iss::Ok; } -template iss::status riscv_hart_msu_vp::write_satp(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_satp(unsigned addr, reg_t val) { reg_t tvm = state.mstatus.TVM; if (this->reg.machine_state == PRIV_S & tvm != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); @@ -975,7 +884,7 @@ template iss::status riscv_hart_msu_vp::write_satp(unsigne update_vm_info(); return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_fcsr(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_fcsr(unsigned addr, reg_t &val) { switch (addr) { case 1: // fflags, 4:0 val = bit_sub<0, 5>(this->get_fcsr()); @@ -992,7 +901,7 @@ template iss::status riscv_hart_msu_vp::read_fcsr(unsigned return iss::Ok; } -template iss::status riscv_hart_msu_vp::write_fcsr(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_fcsr(unsigned addr, reg_t val) { switch (addr) { case 1: // fflags, 4:0 this->set_fcsr((this->get_fcsr() & 0xffffffe0) | (val & 0x1f)); @@ -1010,7 +919,7 @@ template iss::status riscv_hart_msu_vp::write_fcsr(unsigne } template -iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { +iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { if ((paddr.val + length) > mem.size()) return iss::Err; switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg @@ -1035,7 +944,7 @@ iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length } template -iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { +iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { if ((paddr.val + length) > mem.size()) return iss::Err; switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg @@ -1112,13 +1021,13 @@ iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned lengt return iss::Ok; } -template inline void riscv_hart_msu_vp::reset(uint64_t address) { +template inline void riscv_hart_m_p::reset(uint64_t address) { BASE::reset(address); state.mstatus = hart_state::mstatus_reset_val; update_vm_info(); } -template inline void riscv_hart_msu_vp::update_vm_info() { +template inline void riscv_hart_m_p::update_vm_info() { vm[1] = hart_state::decode_vm_info(this->reg.machine_state, state.satp); BASE::addr_mode[3]=BASE::addr_mode[2] = vm[1].is_active()? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL; if (state.mstatus.MPRV) @@ -1129,7 +1038,7 @@ template inline void riscv_hart_msu_vp::update_vm_info() { ptw.clear(); } -template void riscv_hart_msu_vp::check_interrupt() { +template void riscv_hart_m_p::check_interrupt() { auto status = state.mstatus; auto ip = csr[mip]; auto ie = csr[mie]; @@ -1157,7 +1066,7 @@ template void riscv_hart_msu_vp::check_interrupt() { } template -typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::virt2phys(const iss::addr_t &addr) { +typename riscv_hart_m_p::phys_addr_t riscv_hart_m_p::virt2phys(const iss::addr_t &addr) { const auto type = addr.access & iss::access_type::FUNC; auto it = ptw.find(addr.val >> PGSHIFT); if (it != ptw.end()) { @@ -1249,7 +1158,7 @@ typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::virt2phys } } -template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t flags, uint64_t addr) { +template uint64_t riscv_hart_m_p::enter_trap(uint64_t flags, uint64_t addr) { auto cur_priv = this->reg.machine_state; // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val @@ -1326,7 +1235,7 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f return this->reg.NEXT_PC; } -template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t flags) { +template uint64_t riscv_hart_m_p::leave_trap(uint64_t flags) { auto cur_priv = this->reg.machine_state; auto inst_priv = flags & 0x3; auto status = state.mstatus; @@ -1364,7 +1273,7 @@ template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t f return this->reg.NEXT_PC; } -template void riscv_hart_msu_vp::wait_until(uint64_t flags) { +template void riscv_hart_m_p::wait_until(uint64_t flags) { auto status = state.mstatus; auto tw = status.TW; if (this->reg.machine_state == PRIV_S && tw != 0) { diff --git a/incl/iss/arch/rv32gc.h b/incl/iss/arch/rv32gc.h deleted file mode 100644 index 48e7978..0000000 --- a/incl/iss/arch/rv32gc.h +++ /dev/null @@ -1,318 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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 _RV32GC_H_ -#define _RV32GC_H_ - -#include -#include -#include -#include - -namespace iss { -namespace arch { - -struct rv32gc; - -template <> struct traits { - - constexpr static char const* const core_type = "RV32GC"; - - 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", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}}; - - static constexpr std::array reg_aliases{ - {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}}; - - enum constants {XLEN=32, FLEN=64, PCLEN=32, MUL_LEN=64, MISA_VAL=0b1000000000101000001000100101101, PGSIZE=0x1000, PGMASK=0xfff}; - - constexpr static unsigned FP_REGS_SIZE = 64; - - 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, - F0, - F1, - F2, - F3, - F4, - F5, - F6, - F7, - F8, - F9, - F10, - F11, - F12, - F13, - F14, - F15, - F16, - F17, - F18, - F19, - F20, - F21, - F22, - F23, - F24, - F25, - F26, - F27, - F28, - F29, - F30, - F31, - FCSR, - NUM_REGS, - NEXT_PC=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - LAST_BRANCH, - ICOUNT, - ZERO = X0, - RA = X1, - SP = X2, - GP = X3, - TP = X4, - T0 = X5, - T1 = X6, - T2 = X7, - S0 = X8, - S1 = X9, - A0 = X10, - A1 = X11, - A2 = X12, - A3 = X13, - A4 = X14, - A5 = X15, - A6 = X16, - A7 = X17, - S2 = X18, - S3 = X19, - S4 = X20, - S5 = X21, - S6 = X22, - S7 = X23, - S8 = X24, - S9 = X25, - S10 = X26, - S11 = X27, - T3 = X28, - T4 = X29, - T5 = X30, - T6 = X31 - }; - - 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,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,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,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,412,416,424}}; - - 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 }; -}; - -struct rv32gc: 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; - - rv32gc(); - ~rv32gc(); - - 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 RV32GC_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; - uint64_t F0 = 0; - uint64_t F1 = 0; - uint64_t F2 = 0; - uint64_t F3 = 0; - uint64_t F4 = 0; - uint64_t F5 = 0; - uint64_t F6 = 0; - uint64_t F7 = 0; - uint64_t F8 = 0; - uint64_t F9 = 0; - uint64_t F10 = 0; - uint64_t F11 = 0; - uint64_t F12 = 0; - uint64_t F13 = 0; - uint64_t F14 = 0; - uint64_t F15 = 0; - uint64_t F16 = 0; - uint64_t F17 = 0; - uint64_t F18 = 0; - uint64_t F19 = 0; - uint64_t F20 = 0; - uint64_t F21 = 0; - uint64_t F22 = 0; - uint64_t F23 = 0; - uint64_t F24 = 0; - uint64_t F25 = 0; - uint64_t F26 = 0; - uint64_t F27 = 0; - uint64_t F28 = 0; - uint64_t F29 = 0; - uint64_t F30 = 0; - uint64_t F31 = 0; - uint32_t FCSR = 0; - uint32_t NEXT_PC = 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 reg.FCSR;} - void set_fcsr(uint32_t val){reg.FCSR = val;} - -}; - -} -} -#endif /* _RV32GC_H_ */ diff --git a/incl/iss/arch/rv32imac.h b/incl/iss/arch/rv32imac.h deleted file mode 100644 index ed3003c..0000000 --- a/incl/iss/arch/rv32imac.h +++ /dev/null @@ -1,252 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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 _RV32IMAC_H_ -#define _RV32IMAC_H_ - -#include -#include -#include -#include - -namespace iss { -namespace arch { - -struct rv32imac; - -template <> struct traits { - - constexpr static char const* const core_type = "RV32IMAC"; - - 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"}}; - - static constexpr std::array reg_aliases{ - {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}}; - - enum constants {XLEN=32, PCLEN=32, MUL_LEN=64, MISA_VAL=0b1000000000101000001000100000101, PGSIZE=0x1000, PGMASK=0xfff}; - - 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, - NUM_REGS, - NEXT_PC=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - LAST_BRANCH, - ICOUNT, - ZERO = X0, - RA = X1, - SP = X2, - GP = X3, - TP = X4, - T0 = X5, - T1 = X6, - T2 = X7, - S0 = X8, - S1 = X9, - A0 = X10, - A1 = X11, - A2 = X12, - A3 = X13, - A4 = X14, - A5 = X15, - A6 = X16, - A7 = X17, - S2 = X18, - S3 = X19, - S4 = X20, - S5 = X21, - S6 = X22, - S7 = X23, - S8 = X24, - S9 = X25, - S10 = X26, - S11 = X27, - T3 = X28, - T4 = X29, - T5 = X30, - T6 = X31 - }; - - 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,32,32,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,140,144,148,152,160}}; - - 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 }; -}; - -struct rv32imac: 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; - - rv32imac(); - ~rv32imac(); - - 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 RV32IMAC_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; - 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 /* _RV32IMAC_H_ */ diff --git a/incl/iss/arch/rv64gc.h b/incl/iss/arch/rv64gc.h deleted file mode 100644 index 26c6fc0..0000000 --- a/incl/iss/arch/rv64gc.h +++ /dev/null @@ -1,318 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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 _RV64GC_H_ -#define _RV64GC_H_ - -#include -#include -#include -#include - -namespace iss { -namespace arch { - -struct rv64gc; - -template <> struct traits { - - constexpr static char const* const core_type = "RV64GC"; - - 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", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}}; - - static constexpr std::array reg_aliases{ - {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}}; - - enum constants {XLEN=64, FLEN=64, PCLEN=64, MUL_LEN=128, MISA_VAL=0b1000000000101000001000100101101, PGSIZE=0x1000, PGMASK=0xfff}; - - constexpr static unsigned FP_REGS_SIZE = 64; - - 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, - F0, - F1, - F2, - F3, - F4, - F5, - F6, - F7, - F8, - F9, - F10, - F11, - F12, - F13, - F14, - F15, - F16, - F17, - F18, - F19, - F20, - F21, - F22, - F23, - F24, - F25, - F26, - F27, - F28, - F29, - F30, - F31, - FCSR, - NUM_REGS, - NEXT_PC=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - LAST_BRANCH, - ICOUNT, - ZERO = X0, - RA = X1, - SP = X2, - GP = X3, - TP = X4, - T0 = X5, - T1 = X6, - T2 = X7, - S0 = X8, - S1 = X9, - A0 = X10, - A1 = X11, - A2 = X12, - A3 = X13, - A4 = X14, - A5 = X15, - A6 = X16, - A7 = X17, - S2 = X18, - S3 = X19, - S4 = X20, - S5 = X21, - S6 = X22, - S7 = X23, - S8 = X24, - S9 = X25, - S10 = X26, - S11 = X27, - T3 = X28, - T4 = X29, - T5 = X30, - T6 = X31 - }; - - using reg_t = uint64_t; - - using addr_t = uint64_t; - - using code_word_t = uint64_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{ - {64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,64,32,32,32,32,64}}; - - static constexpr std::array reg_byte_offsets{ - {0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,400,408,416,424,432,440,448,456,464,472,480,488,496,504,512,520,528,536,540,544,548,552,560}}; - - 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 }; -}; - -struct rv64gc: 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; - - rv64gc(); - ~rv64gc(); - - 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 RV64GC_regs { - uint64_t X0 = 0; - uint64_t X1 = 0; - uint64_t X2 = 0; - uint64_t X3 = 0; - uint64_t X4 = 0; - uint64_t X5 = 0; - uint64_t X6 = 0; - uint64_t X7 = 0; - uint64_t X8 = 0; - uint64_t X9 = 0; - uint64_t X10 = 0; - uint64_t X11 = 0; - uint64_t X12 = 0; - uint64_t X13 = 0; - uint64_t X14 = 0; - uint64_t X15 = 0; - uint64_t X16 = 0; - uint64_t X17 = 0; - uint64_t X18 = 0; - uint64_t X19 = 0; - uint64_t X20 = 0; - uint64_t X21 = 0; - uint64_t X22 = 0; - uint64_t X23 = 0; - uint64_t X24 = 0; - uint64_t X25 = 0; - uint64_t X26 = 0; - uint64_t X27 = 0; - uint64_t X28 = 0; - uint64_t X29 = 0; - uint64_t X30 = 0; - uint64_t X31 = 0; - uint64_t PC = 0; - uint64_t F0 = 0; - uint64_t F1 = 0; - uint64_t F2 = 0; - uint64_t F3 = 0; - uint64_t F4 = 0; - uint64_t F5 = 0; - uint64_t F6 = 0; - uint64_t F7 = 0; - uint64_t F8 = 0; - uint64_t F9 = 0; - uint64_t F10 = 0; - uint64_t F11 = 0; - uint64_t F12 = 0; - uint64_t F13 = 0; - uint64_t F14 = 0; - uint64_t F15 = 0; - uint64_t F16 = 0; - uint64_t F17 = 0; - uint64_t F18 = 0; - uint64_t F19 = 0; - uint64_t F20 = 0; - uint64_t F21 = 0; - uint64_t F22 = 0; - uint64_t F23 = 0; - uint64_t F24 = 0; - uint64_t F25 = 0; - uint64_t F26 = 0; - uint64_t F27 = 0; - uint64_t F28 = 0; - uint64_t F29 = 0; - uint64_t F30 = 0; - uint64_t F31 = 0; - uint32_t FCSR = 0; - uint64_t NEXT_PC = 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 reg.FCSR;} - void set_fcsr(uint32_t val){reg.FCSR = val;} - -}; - -} -} -#endif /* _RV64GC_H_ */ diff --git a/incl/iss/arch/rv64i.h b/incl/iss/arch/rv64i.h deleted file mode 100644 index e13b0c4..0000000 --- a/incl/iss/arch/rv64i.h +++ /dev/null @@ -1,252 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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 _RV64I_H_ -#define _RV64I_H_ - -#include -#include -#include -#include - -namespace iss { -namespace arch { - -struct rv64i; - -template <> struct traits { - - constexpr static char const* const core_type = "RV64I"; - - 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"}}; - - static constexpr std::array reg_aliases{ - {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}}; - - enum constants {XLEN=64, PCLEN=64, MISA_VAL=0b10000000000001000000000100000000, PGSIZE=0x1000, PGMASK=0xfff}; - - 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, - NUM_REGS, - NEXT_PC=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - LAST_BRANCH, - ICOUNT, - ZERO = X0, - RA = X1, - SP = X2, - GP = X3, - TP = X4, - T0 = X5, - T1 = X6, - T2 = X7, - S0 = X8, - S1 = X9, - A0 = X10, - A1 = X11, - A2 = X12, - A3 = X13, - A4 = X14, - A5 = X15, - A6 = X16, - A7 = X17, - S2 = X18, - S3 = X19, - S4 = X20, - S5 = X21, - S6 = X22, - S7 = X23, - S8 = X24, - S9 = X25, - S10 = X26, - S11 = X27, - T3 = X28, - T4 = X29, - T5 = X30, - T6 = X31 - }; - - using reg_t = uint64_t; - - using addr_t = uint64_t; - - using code_word_t = uint64_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{ - {64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,64}}; - - static constexpr std::array reg_byte_offsets{ - {0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,276,280,284,288,296}}; - - 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 }; -}; - -struct rv64i: 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; - - rv64i(); - ~rv64i(); - - 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 RV64I_regs { - uint64_t X0 = 0; - uint64_t X1 = 0; - uint64_t X2 = 0; - uint64_t X3 = 0; - uint64_t X4 = 0; - uint64_t X5 = 0; - uint64_t X6 = 0; - uint64_t X7 = 0; - uint64_t X8 = 0; - uint64_t X9 = 0; - uint64_t X10 = 0; - uint64_t X11 = 0; - uint64_t X12 = 0; - uint64_t X13 = 0; - uint64_t X14 = 0; - uint64_t X15 = 0; - uint64_t X16 = 0; - uint64_t X17 = 0; - uint64_t X18 = 0; - uint64_t X19 = 0; - uint64_t X20 = 0; - uint64_t X21 = 0; - uint64_t X22 = 0; - uint64_t X23 = 0; - uint64_t X24 = 0; - uint64_t X25 = 0; - uint64_t X26 = 0; - uint64_t X27 = 0; - uint64_t X28 = 0; - uint64_t X29 = 0; - uint64_t X30 = 0; - uint64_t X31 = 0; - uint64_t PC = 0; - uint64_t NEXT_PC = 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 /* _RV64I_H_ */ diff --git a/incl/iss/arch/tgf01.h b/incl/iss/arch/tgf01.h index 9d4fcb4..7a7cb58 100644 --- a/incl/iss/arch/tgf01.h +++ b/incl/iss/arch/tgf01.h @@ -54,7 +54,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}}; - enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000000000000000100000000}; + enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000000000000000100000000, PGSIZE=0x1000, PGMASK=0xfff}; constexpr static unsigned FP_REGS_SIZE = 0; diff --git a/incl/iss/arch/tgf02.h b/incl/iss/arch/tgf02.h index 804971b..a2d1ca3 100644 --- a/incl/iss/arch/tgf02.h +++ b/incl/iss/arch/tgf02.h @@ -54,7 +54,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}}; - enum constants {XLEN=32, PCLEN=32, MUL_LEN=64, MISA_VAL=0b1000000000000000001000100000100}; + enum constants {XLEN=32, PCLEN=32, MUL_LEN=64, MISA_VAL=0b1000000000000000001000100000100, PGSIZE=0x1000, PGMASK=0xfff}; constexpr static unsigned FP_REGS_SIZE = 0; diff --git a/incl/sysc/core_complex.h b/incl/sysc/core_complex.h index 21bb219..fd53590 100644 --- a/incl/sysc/core_complex.h +++ b/incl/sysc/core_complex.h @@ -51,7 +51,7 @@ template class scv_tr_generator; namespace iss { class vm_if; namespace arch { -template class riscv_hart_msu_vp; +template class riscv_hart_m_p; } namespace debugger { class target_adapter_if; diff --git a/src/iss/mnrv32.cpp b/src/iss/mnrv32.cpp deleted file mode 100644 index 613bbf1..0000000 --- a/src/iss/mnrv32.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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; - -mnrv32::mnrv32() { - reg.icount = 0; -} - -mnrv32::~mnrv32() = default; - -void mnrv32::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 *mnrv32::get_regs_base_ptr() { - return reinterpret_cast(®); -} - -mnrv32::phys_addr_t mnrv32::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address -} - diff --git a/src/iss/rv32gc.cpp b/src/iss/rv32gc.cpp deleted file mode 100644 index c3756f9..0000000 --- a/src/iss/rv32gc.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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; - -rv32gc::rv32gc() { - reg.icount=0; -} - -rv32gc::~rv32gc(){ -} - -void rv32gc::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* rv32gc::get_regs_base_ptr(){ - return reinterpret_cast(®); -} - -rv32gc::phys_addr_t rv32gc::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address -} - diff --git a/src/iss/rv32imac.cpp b/src/iss/rv32imac.cpp deleted file mode 100644 index 2d8a56e..0000000 --- a/src/iss/rv32imac.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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; - -rv32imac::rv32imac() { - reg.icount = 0; - reg.machine_state = 0x3; -} - -rv32imac::~rv32imac() = default; - -void rv32imac::reset(uint64_t address) { - for (size_t i = 0; i < traits::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; -} - -uint8_t *rv32imac::get_regs_base_ptr() { return reinterpret_cast(®); } - -rv32imac::phys_addr_t rv32imac::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address -} diff --git a/src/iss/rv64gc.cpp b/src/iss/rv64gc.cpp deleted file mode 100644 index 17d8dc1..0000000 --- a/src/iss/rv64gc.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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; - -rv64gc::rv64gc() { - reg.icount = 0; -} - -rv64gc::~rv64gc() = default; - -void rv64gc::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 *rv64gc::get_regs_base_ptr() { - return reinterpret_cast(®); -} - -rv64gc::phys_addr_t rv64gc::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address -} - diff --git a/src/iss/rv64i.cpp b/src/iss/rv64i.cpp deleted file mode 100644 index 83070d5..0000000 --- a/src/iss/rv64i.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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; - -rv64i::rv64i() { - reg.icount = 0; -} - -rv64i::~rv64i() = default; - -void rv64i::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 *rv64i::get_regs_base_ptr() { - return reinterpret_cast(®); -} - -rv64i::phys_addr_t rv64i::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 7eb0737..2def365 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,12 +35,9 @@ #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include #ifdef WITH_LLVM #include #endif @@ -55,7 +52,7 @@ using vm_ptr= std::unique_ptr; template std::tuple create_cpu(std::string const& backend, unsigned gdb_port){ - CORE* lcpu = new iss::arch::riscv_hart_msu_vp(); + CORE* lcpu = new iss::arch::riscv_hart_m_p(); if(backend == "interp") return {cpu_ptr{lcpu}, vm_ptr{iss::interp::create(lcpu, gdb_port)}}; #ifdef WITH_LLVM @@ -132,16 +129,10 @@ int main(int argc, char *argv[]) { vm_ptr vm{nullptr}; cpu_ptr cpu{nullptr}; std::string isa_opt(clim["isa"].as()); - if (isa_opt=="mnrv32") { - std::tie(cpu, vm) = create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else if (isa_opt=="rv64i") { - std::tie(cpu, vm) = create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else if (isa_opt=="rv64gc") { - std::tie(cpu, vm) = create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else if (isa_opt=="rv32imac") { - std::tie(cpu, vm) = create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else if (isa_opt=="rv32gc") { - std::tie(cpu, vm) = create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + if (isa_opt=="tgf01") { + std::tie(cpu, vm) = create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else if (isa_opt=="tgf02") { + std::tie(cpu, vm) = create_cpu(clim["backend"].as(), clim["gdb-port"].as()); } else { LOG(ERROR) << "Illegal argument value for '--isa': " << clim["isa"].as() << std::endl; return 127; @@ -181,7 +172,7 @@ int main(int argc, char *argv[]) { } uint64_t start_address = 0; if (clim.count("mem")) - vm->get_arch()->load_file(clim["mem"].as(), iss::arch::traits::MEM); + vm->get_arch()->load_file(clim["mem"].as(), iss::arch::traits::MEM); if (clim.count("elf")) for (std::string input : clim["elf"].as>()) { auto start_addr = vm->get_arch()->load_file(input); diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 713f3cc..063085b 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -31,9 +31,8 @@ *******************************************************************************/ #include "sysc/core_complex.h" -#include "iss/arch/riscv_hart_msu_vp.h" -//#include "iss/arch/rv32imac.h" -#include "iss/arch/mnrv32.h" +#include "iss/arch/riscv_hart_m_p.h" +#include "iss/arch/tgf01.h" #include "iss/debugger/encoderdecoder.h" #include "iss/debugger/gdb_session.h" #include "iss/debugger/server.h" @@ -61,7 +60,7 @@ iss::debugger::encoder_decoder encdec; } //using core_type = iss::arch::rv32imac; -using core_type = iss::arch::mnrv32; +using core_type = iss::arch::tgf01; namespace { @@ -91,9 +90,9 @@ std::array irq_str = { { "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt" } }; } -class core_wrapper : public iss::arch::riscv_hart_msu_vp { +class core_wrapper : public iss::arch::riscv_hart_m_p { public: - using base_type = arch::riscv_hart_msu_vp; + using base_type = arch::riscv_hart_m_p; using phys_addr_t = typename arch::traits::phys_addr_t; core_wrapper(core_complex *owner) : owner(owner) @@ -287,7 +286,7 @@ vm_ptr create_cpu(core_wrapper* cpu, std::string const& backend, unsigned gdb_po } void core_complex::before_end_of_elaboration() { - SCCDEBUG(SCMOD)<<"instantiating iss::arch::mnrv32 with "<(this); vm = create_cpu(cpu.get(), backend.get_value(), gdb_server_port.get_value()); #ifdef WITH_SCV diff --git a/src/vm/interp/vm_rv32gc.cpp b/src/vm/interp/vm_rv32gc.cpp deleted file mode 100644 index 2131227..0000000 --- a/src/vm/interp/vm_rv32gc.cpp +++ /dev/null @@ -1,6839 +0,0 @@ -/******************************************************************************* - * Copyright (C) 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 "../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 rv32gc { -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::interp::vm_base { -public: - 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 iss::interp::vm_base::get_reg; - - 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_trap(uint16_t trap_id, uint16_t cause){ - auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; - this->template get_reg(arch::traits::TRAP_STATE) = trap_val; - this->template get_reg(arch::traits::NEXT_PC) = std::numeric_limits::max(); - } - - void leave_trap(unsigned lvl){ - this->core.leave_trap(lvl); - auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); - this->template get_reg(arch::traits::NEXT_PC) = pc_val; - this->template get_reg(arch::traits::LAST_BRANCH) = std::numeric_limits::max(); - } - - void wait(unsigned type){ - this->core.wait_until(type); - } - - -private: - /**************************************************************************** - * start opcode definitions - ****************************************************************************/ - 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, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &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, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &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 MUL */ - {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH */ - {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU */ - {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU */ - {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV */ - {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU */ - {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM */ - {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU */ - {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction LR.W */ - {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lr_w}, - /* instruction SC.W */ - {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__sc_w}, - /* instruction AMOSWAP.W */ - {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_w}, - /* instruction AMOADD.W */ - {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_w}, - /* instruction AMOXOR.W */ - {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_w}, - /* instruction AMOAND.W */ - {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_w}, - /* instruction AMOOR.W */ - {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_w}, - /* instruction AMOMIN.W */ - {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_w}, - /* instruction AMOMAX.W */ - {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_w}, - /* instruction AMOMINU.W */ - {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_w}, - /* instruction AMOMAXU.W */ - {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_w}, - /* instruction FLW */ - {32, 0b00000000000000000010000000000111, 0b00000000000000000111000001111111, &this_class::__flw}, - /* instruction FSW */ - {32, 0b00000000000000000010000000100111, 0b00000000000000000111000001111111, &this_class::__fsw}, - /* instruction FMADD.S */ - {32, 0b00000000000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_s}, - /* instruction FMSUB.S */ - {32, 0b00000000000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_s}, - /* instruction FNMADD.S */ - {32, 0b00000000000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_s}, - /* instruction FNMSUB.S */ - {32, 0b00000000000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_s}, - /* instruction FADD.S */ - {32, 0b00000000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_s}, - /* instruction FSUB.S */ - {32, 0b00001000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_s}, - /* instruction FMUL.S */ - {32, 0b00010000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_s}, - /* instruction FDIV.S */ - {32, 0b00011000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_s}, - /* instruction FSQRT.S */ - {32, 0b01011000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_s}, - /* instruction FSGNJ.S */ - {32, 0b00100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_s}, - /* instruction FSGNJN.S */ - {32, 0b00100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_s}, - /* instruction FSGNJX.S */ - {32, 0b00100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_s}, - /* instruction FMIN.S */ - {32, 0b00101000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_s}, - /* instruction FMAX.S */ - {32, 0b00101000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_s}, - /* instruction FCVT.W.S */ - {32, 0b11000000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_s}, - /* instruction FCVT.WU.S */ - {32, 0b11000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_s}, - /* instruction FEQ.S */ - {32, 0b10100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_s}, - /* instruction FLT.S */ - {32, 0b10100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_s}, - /* instruction FLE.S */ - {32, 0b10100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_s}, - /* instruction FCLASS.S */ - {32, 0b11100000000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_s}, - /* instruction FCVT.S.W */ - {32, 0b11010000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_w}, - /* instruction FCVT.S.WU */ - {32, 0b11010000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_wu}, - /* instruction FMV.X.W */ - {32, 0b11100000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_w}, - /* instruction FMV.W.X */ - {32, 0b11110000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_w_x}, - /* instruction FLD */ - {32, 0b00000000000000000011000000000111, 0b00000000000000000111000001111111, &this_class::__fld}, - /* instruction FSD */ - {32, 0b00000000000000000011000000100111, 0b00000000000000000111000001111111, &this_class::__fsd}, - /* instruction FMADD.D */ - {32, 0b00000010000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_d}, - /* instruction FMSUB.D */ - {32, 0b00000010000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_d}, - /* instruction FNMADD.D */ - {32, 0b00000010000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_d}, - /* instruction FNMSUB.D */ - {32, 0b00000010000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_d}, - /* instruction FADD.D */ - {32, 0b00000010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_d}, - /* instruction FSUB.D */ - {32, 0b00001010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_d}, - /* instruction FMUL.D */ - {32, 0b00010010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_d}, - /* instruction FDIV.D */ - {32, 0b00011010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_d}, - /* instruction FSQRT.D */ - {32, 0b01011010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_d}, - /* instruction FSGNJ.D */ - {32, 0b00100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_d}, - /* instruction FSGNJN.D */ - {32, 0b00100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_d}, - /* instruction FSGNJX.D */ - {32, 0b00100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_d}, - /* instruction FMIN.D */ - {32, 0b00101010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_d}, - /* instruction FMAX.D */ - {32, 0b00101010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_d}, - /* instruction FCVT.S.D */ - {32, 0b01000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_d}, - /* instruction FCVT.D.S */ - {32, 0b01000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_s}, - /* instruction FEQ.D */ - {32, 0b10100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_d}, - /* instruction FLT.D */ - {32, 0b10100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_d}, - /* instruction FLE.D */ - {32, 0b10100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_d}, - /* instruction FCLASS.D */ - {32, 0b11100010000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_d}, - /* instruction FCVT.W.D */ - {32, 0b11000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_d}, - /* instruction FCVT.WU.D */ - {32, 0b11000010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_d}, - /* instruction FCVT.D.W */ - {32, 0b11010010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_w}, - /* instruction FCVT.D.WU */ - {32, 0b11010010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_wu}, - /* instruction C.ADDI4SPN */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII */ - {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, - /* instruction C.FLW */ - {16, 0b0110000000000000, 0b1110000000000011, &this_class::__c_flw}, - /* instruction C.FSW */ - {16, 0b1110000000000000, 0b1110000000000011, &this_class::__c_fsw}, - /* instruction C.FLWSP */ - {16, 0b0110000000000010, 0b1110000000000011, &this_class::__c_flwsp}, - /* instruction C.FSWSP */ - {16, 0b1110000000000010, 0b1110000000000011, &this_class::__c_fswsp}, - /* instruction C.FLD */ - {16, 0b0010000000000000, 0b1110000000000011, &this_class::__c_fld}, - /* instruction C.FSD */ - {16, 0b1010000000000000, 0b1110000000000011, &this_class::__c_fsd}, - /* instruction C.FLDSP */ - {16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_fldsp}, - /* instruction C.FSDSP */ - {16, 0b1010000000000010, 0b1110000000000011, &this_class::__c_fsdsp}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 0); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (imm); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 0); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 1: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 1); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 1); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 2: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 2); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (cur_pc_val + 4); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto PC_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 2); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 3: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 3); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto new_pc_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = (cur_pc_val + 4); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto PC_val = (new_pc_val & ~(0x1)); - super::template get_reg(traits::NEXT_PC) = PC_val; - super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - this->do_sync(POST_SYNC, 3); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 4: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 4); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) == super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 4); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 5: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 5); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) != super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 5); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 6: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 6); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 6); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 7: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 7); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) >= static_cast(super::template get_reg(rs2 + traits::X0)))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 7); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 8: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 8); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) < super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 8); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 9: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 9); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) >= super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 9); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 10: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 10); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 10); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 11: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 11); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 11); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 12: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 12); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 12); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 13: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 13); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 13); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 14: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 14); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 14); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 15: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 15); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 15); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 16: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 16); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 16); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 17: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 17); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 17); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 18: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 18); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 18); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 19: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 19); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < (imm))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 19); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 20: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 20); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - int32_t full_imm_val = imm; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) < full_imm_val)? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 20); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 21: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 21); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) ^ (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 21); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 22: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 22); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) | (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 22); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 23: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 23); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) & (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 23); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 24: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 24); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - } - this->do_sync(POST_SYNC, 24); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 25: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 25); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - } - this->do_sync(POST_SYNC, 25); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 26: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 26); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - } - this->do_sync(POST_SYNC, 26); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 27: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 27); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) + super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 27); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 28: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 28); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) - super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 28); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 29: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 29); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 29); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 30: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 30); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 30); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 31: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 31); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) < super::template zext(super::template get_reg(rs2 + traits::X0)))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 31); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 32: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 32); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) ^ super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 32); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 33: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 33); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 33); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 34: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 34); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 34); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 35: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 35); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) | super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 35); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 36: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 36); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) & super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 36); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 37: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 37); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "fence"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (((pred) << 4) | (succ)); - super::write_mem(traits::FENCE, (0), static_cast(FENCEtmp0_val)); - this->do_sync(POST_SYNC, 37); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 38: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 38); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "fence_i"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (imm); - super::write_mem(traits::FENCE, (1), static_cast(FENCEtmp0_val)); - this->do_sync(POST_SYNC, 38); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 39: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 39); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ecall"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - raise_trap(0, 11); - this->do_sync(POST_SYNC, 39); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 40: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 40); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ebreak"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - raise_trap(0, 3); - this->do_sync(POST_SYNC, 40); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 41: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 41); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "uret"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(0); - this->do_sync(POST_SYNC, 41); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 42: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 42); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "sret"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(1); - this->do_sync(POST_SYNC, 42); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 43: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 43); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "mret"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(3); - this->do_sync(POST_SYNC, 43); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 44: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 44); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "wfi"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - wait(1); - this->do_sync(POST_SYNC, 44); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 45: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 45); - - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "sfence.vma"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (rs1); - super::write_mem(traits::FENCE, (2), static_cast(FENCEtmp0_val)); - auto FENCEtmp1_val = (rs2); - super::write_mem(traits::FENCE, (3), static_cast(FENCEtmp1_val)); - this->do_sync(POST_SYNC, 45); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 46: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 46); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto rs_val_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto csr_val_val = super::template read_mem(traits::CSR, (csr)); - auto CSRtmp0_val = rs_val_val; - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); - auto Xtmp1_val = csr_val_val; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } else { - auto CSRtmp2_val = rs_val_val; - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp2_val)); - } - this->do_sync(POST_SYNC, 46); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 47: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 47); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto xrd_val = super::template read_mem(traits::CSR, (csr)); - auto xrs1_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = xrd_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - if(rs1 != 0){ - auto CSRtmp1_val = (xrd_val | xrs1_val); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 47); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 48: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 48); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto xrd_val = super::template read_mem(traits::CSR, (csr)); - auto xrs1_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = xrd_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - if(rs1 != 0){ - auto CSRtmp1_val = (xrd_val & ~(xrs1_val)); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 48); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 49: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 49); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = super::template read_mem(traits::CSR, (csr)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto CSRtmp1_val = super::template zext((zimm)); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - this->do_sync(POST_SYNC, 49); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 50: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 50); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = super::template read_mem(traits::CSR, (csr)); - if(zimm != 0){ - auto CSRtmp0_val = (res_val | super::template zext((zimm))); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); - } - if(rd != 0){ - auto Xtmp1_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - this->do_sync(POST_SYNC, 50); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 51: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 51); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = super::template read_mem(traits::CSR, (csr)); - if(rd != 0){ - auto Xtmp0_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - if(zimm != 0){ - auto CSRtmp1_val = (res_val & ~(super::template zext((zimm)))); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 51); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 52: MUL */ - compile_ret_t __mul(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 52); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext(res_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 52); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 53: MULH */ - compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 53); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template sext(super::template get_reg(rs1 + traits::X0)) * super::template sext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext((res_val >> (32))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 53); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 54: MULHSU */ - compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 54); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template sext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext((res_val >> (32))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 54); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 55: MULHU */ - compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 55); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext((res_val >> (32))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 55); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 56: DIV */ - compile_ret_t __div(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 56); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - uint32_t M1_val = - 1; - uint8_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - { - if(((super::template get_reg(rs1 + traits::X0) == MMIN_val) && (super::template get_reg(rs2 + traits::X0) == M1_val))) { - auto Xtmp0_val = MMIN_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = (static_cast(super::template get_reg(rs1 + traits::X0)) / static_cast(super::template get_reg(rs2 + traits::X0))); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - else { - auto Xtmp2_val = -(1); - super::template get_reg(rd + traits::X0)=Xtmp2_val; - } - } - } - this->do_sync(POST_SYNC, 56); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 57: DIVU */ - compile_ret_t __divu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 57); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) / super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = -(1); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - this->do_sync(POST_SYNC, 57); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 58: REM */ - compile_ret_t __rem(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 58); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - uint32_t M1_val = - 1; - uint32_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - { - if(((super::template get_reg(rs1 + traits::X0) == MMIN_val) && (super::template get_reg(rs2 + traits::X0) == M1_val))) { - auto Xtmp0_val = 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = (static_cast(super::template get_reg(rs1 + traits::X0)) % static_cast(super::template get_reg(rs2 + traits::X0))); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - else { - auto Xtmp2_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(rd + traits::X0)=Xtmp2_val; - } - } - } - this->do_sync(POST_SYNC, 58); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 59: REMU */ - compile_ret_t __remu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 59); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) % super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - this->do_sync(POST_SYNC, 59); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 60: LR.W */ - compile_ret_t __lr_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 60); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto REStmp1_val = super::template sext(-(1)); - super::write_mem(traits::RES, offs_val, static_cast(REStmp1_val)); - } - this->do_sync(POST_SYNC, 60); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 61: SC.W */ - compile_ret_t __sc_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 61); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template read_mem(traits::RES, offs_val); - { - if((res1_val != 0)) { - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - } - } - if(rd != 0){ - auto Xtmp1_val = (res1_val != super::template zext(0))? - 0: - 1; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - this->do_sync(POST_SYNC, 61); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 62: AMOSWAP.W */ - compile_ret_t __amoswap_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 62); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto MEMtmp1_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 62); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 63: AMOADD.W */ - compile_ret_t __amoadd_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 63); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val + super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 63); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 64: AMOXOR.W */ - compile_ret_t __amoxor_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 64); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val ^ super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 64); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 65: AMOAND.W */ - compile_ret_t __amoand_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 65); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val & super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 65); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 66: AMOOR.W */ - compile_ret_t __amoor_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 66); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val | super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 66); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 67: AMOMIN.W */ - compile_ret_t __amomin_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 67); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (static_cast(res1_val) > static_cast(super::template get_reg(rs2 + traits::X0)))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 67); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 68: AMOMAX.W */ - compile_ret_t __amomax_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 68); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (static_cast(res1_val) < static_cast(super::template get_reg(rs2 + traits::X0)))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 68); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 69: AMOMINU.W */ - compile_ret_t __amominu_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 69); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val > super::template get_reg(rs2 + traits::X0))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 69); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 70: AMOMAXU.W */ - compile_ret_t __amomaxu_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 70); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val < super::template get_reg(rs2 + traits::X0))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 70); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 71: FLW */ - compile_ret_t __flw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 71); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}(x{rs1})", fmt::arg("mnemonic", "flw"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 32){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 71); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 72: FSW */ - compile_ret_t __fsw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 72); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}(x{rs1})", fmt::arg("mnemonic", "fsw"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 72); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 73: FMADD.S */ - compile_ret_t __fmadd_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 73); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fmadd_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template get_reg(rs3 + traits::F0), - super::template zext(0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto frs3_val = unbox_s( - super::template get_reg(rs3 + traits::F0) - ); - auto res_val = fmadd_s( - frs1_val, - frs2_val, - frs3_val, - super::template zext(0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 73); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 74: FMSUB.S */ - compile_ret_t __fmsub_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 74); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fmadd_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template get_reg(rs3 + traits::F0), - super::template zext(1), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto frs3_val = unbox_s( - super::template get_reg(rs3 + traits::F0) - ); - auto res_val = fmadd_s( - frs1_val, - frs2_val, - frs3_val, - super::template zext(1), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 74); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 75: FNMADD.S */ - compile_ret_t __fnmadd_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 75); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fmadd_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template get_reg(rs3 + traits::F0), - super::template zext(2), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto frs3_val = unbox_s( - super::template get_reg(rs3 + traits::F0) - ); - auto res_val = fmadd_s( - frs1_val, - frs2_val, - frs3_val, - super::template zext(2), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 75); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 76: FNMSUB.S */ - compile_ret_t __fnmsub_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 76); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fmadd_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template get_reg(rs3 + traits::F0), - super::template zext(3), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto frs3_val = unbox_s( - super::template get_reg(rs3 + traits::F0) - ); - auto res_val = fmadd_s( - frs1_val, - frs2_val, - frs3_val, - super::template zext(3), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 76); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 77: FADD.S */ - compile_ret_t __fadd_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 77); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fadd_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fadd_s( - frs1_val, - frs2_val, - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 77); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 78: FSUB.S */ - compile_ret_t __fsub_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 78); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fsub_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fsub_s( - frs1_val, - frs2_val, - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 78); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 79: FMUL.S */ - compile_ret_t __fmul_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 79); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fmul_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fmul_s( - frs1_val, - frs2_val, - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 79); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 80: FDIV.S */ - compile_ret_t __fdiv_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 80); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fdiv_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fdiv_s( - frs1_val, - frs2_val, - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 80); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 81: FSQRT.S */ - compile_ret_t __fsqrt_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 81); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fsqrt_s( - super::template get_reg(rs1 + traits::F0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto res_val = fsqrt_s( - frs1_val, - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 81); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 82: FSGNJ.S */ - compile_ret_t __fsgnj_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 82); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = ((super::template get_reg(rs1 + traits::F0) & 0x7fffffff) | (super::template get_reg(rs2 + traits::F0) & 0x80000000)); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = ((frs1_val & 0x7fffffff) | (frs2_val & 0x80000000)); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 82); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 83: FSGNJN.S */ - compile_ret_t __fsgnjn_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 83); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = ((super::template get_reg(rs1 + traits::F0) & 0x7fffffff) | (~(super::template get_reg(rs2 + traits::F0)) & 0x80000000)); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = ((frs1_val & 0x7fffffff) | (~(frs2_val) & 0x80000000)); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 83); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 84: FSGNJX.S */ - compile_ret_t __fsgnjx_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 84); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = (super::template get_reg(rs1 + traits::F0) ^ (super::template get_reg(rs2 + traits::F0) & 0x80000000)); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = (frs1_val ^ (frs2_val & 0x80000000)); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 84); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 85: FMIN.S */ - compile_ret_t __fmin_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 85); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fsel_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template zext(0) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fsel_s( - frs1_val, - frs2_val, - super::template zext(0) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 85); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 86: FMAX.S */ - compile_ret_t __fmax_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 86); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fsel_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template zext(1) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fsel_s( - frs1_val, - frs2_val, - super::template zext(1) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 86); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 87: FCVT.W.S */ - compile_ret_t __fcvt_w_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 87); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Xtmp0_val = super::template sext(fcvt_s( - super::template get_reg(rs1 + traits::F0), - super::template zext(0), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto Xtmp1_val = super::template sext(fcvt_s( - frs1_val, - super::template zext(0), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 87); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 88: FCVT.WU.S */ - compile_ret_t __fcvt_wu_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 88); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Xtmp0_val = super::template sext(fcvt_s( - super::template get_reg(rs1 + traits::F0), - super::template zext(1), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto Xtmp1_val = super::template sext(fcvt_s( - frs1_val, - super::template zext(1), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 88); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 89: FEQ.S */ - compile_ret_t __feq_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 89); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Xtmp0_val = super::template zext(fcmp_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template zext(0) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto Xtmp1_val = super::template zext(fcmp_s( - frs1_val, - frs2_val, - super::template zext(0) - )); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 89); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 90: FLT.S */ - compile_ret_t __flt_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 90); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Xtmp0_val = super::template zext(fcmp_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template zext(2) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto Xtmp1_val = super::template zext(fcmp_s( - frs1_val, - frs2_val, - super::template zext(2) - )); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - auto Xtmp2_val = fcmp_s( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(2) - ); - super::template get_reg(rd + traits::X0)=Xtmp2_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 90); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 91: FLE.S */ - compile_ret_t __fle_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 91); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Xtmp0_val = super::template zext(fcmp_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template zext(1) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto Xtmp1_val = super::template zext(fcmp_s( - frs1_val, - frs2_val, - super::template zext(1) - )); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 91); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 92: FCLASS.S */ - compile_ret_t __fclass_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 92); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = fclass_s( - unbox_s( - super::template get_reg(rs1 + traits::F0) - ) - ); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 92); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 93: FCVT.S.W */ - compile_ret_t __fcvt_s_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 93); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fcvt_s( - static_cast( - super::template get_reg(rs1 + traits::X0) - ), - super::template zext(2), - (rm) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto res_val = fcvt_s( - static_cast( - super::template get_reg(rs1 + traits::X0) - ), - super::template zext(2), - (rm) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 93); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 94: FCVT.S.WU */ - compile_ret_t __fcvt_s_wu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 94); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fcvt_s( - static_cast( - super::template get_reg(rs1 + traits::X0) - ), - super::template zext(3), - (rm) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto res_val = fcvt_s( - static_cast( - super::template get_reg(rs1 + traits::X0) - ), - super::template zext(3), - (rm) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 94); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 95: FMV.X.W */ - compile_ret_t __fmv_x_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 95); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fmv.x.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template sext(static_cast( - super::template get_reg(rs1 + traits::F0) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 95); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 96: FMV.W.X */ - compile_ret_t __fmv_w_x(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 96); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fmv.w.x"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = static_cast( - super::template get_reg(rs1 + traits::X0) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(static_cast( - super::template get_reg(rs1 + traits::X0) - ))); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 96); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 97: FLD */ - compile_ret_t __fld(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 97); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}({rs1})", fmt::arg("mnemonic", "fld"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 97); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 98: FSD */ - compile_ret_t __fsd(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 98); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}({rs1})", fmt::arg("mnemonic", "fsd"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 98); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 99: FMADD.D */ - compile_ret_t __fmadd_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 99); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fmadd_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - static_cast( - super::template get_reg(rs3 + traits::F0) - ), - super::template zext(0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 99); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 100: FMSUB.D */ - compile_ret_t __fmsub_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 100); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fmadd_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - static_cast( - super::template get_reg(rs3 + traits::F0) - ), - super::template zext(1), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 100); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 101: FNMADD.D */ - compile_ret_t __fnmadd_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 101); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fmadd_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - static_cast( - super::template get_reg(rs3 + traits::F0) - ), - super::template zext(2), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 101); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 102: FNMSUB.D */ - compile_ret_t __fnmsub_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 102); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fmadd_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - static_cast( - super::template get_reg(rs3 + traits::F0) - ), - super::template zext(3), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 102); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 103: FADD.D */ - compile_ret_t __fadd_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 103); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fadd_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 103); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 104: FSUB.D */ - compile_ret_t __fsub_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 104); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fsub_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 104); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 105: FMUL.D */ - compile_ret_t __fmul_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 105); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fmul_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 105); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 106: FDIV.D */ - compile_ret_t __fdiv_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 106); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fdiv_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 106); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 107: FSQRT.D */ - compile_ret_t __fsqrt_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 107); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fsqrt_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 107); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 108: FSGNJ.D */ - compile_ret_t __fsgnj_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 108); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - auto res_val = ((static_cast( - super::template get_reg(rs1 + traits::F0) - ) & MSK2_val) | (static_cast( - super::template get_reg(rs2 + traits::F0) - ) & MSK1_val)); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 108); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 109: FSGNJN.D */ - compile_ret_t __fsgnjn_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 109); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - auto res_val = ((static_cast( - super::template get_reg(rs1 + traits::F0) - ) & MSK2_val) | (~(static_cast( - super::template get_reg(rs2 + traits::F0) - )) & MSK1_val)); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 109); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 110: FSGNJX.D */ - compile_ret_t __fsgnjx_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 110); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - auto res_val = (static_cast( - super::template get_reg(rs1 + traits::F0) - ) ^ (static_cast( - super::template get_reg(rs2 + traits::F0) - ) & MSK1_val)); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 110); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 111: FMIN.D */ - compile_ret_t __fmin_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 111); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fsel_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(0) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 111); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 112: FMAX.D */ - compile_ret_t __fmax_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 112); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fsel_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(1) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 112); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 113: FCVT.S.D */ - compile_ret_t __fcvt_s_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 113); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.s.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fconv_d2f( - super::template get_reg(rs1 + traits::F0), - (rm) - ); - uint64_t upper_val = - 1; - auto Ftmp0_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - this->do_sync(POST_SYNC, 113); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 114: FCVT.D.S */ - compile_ret_t __fcvt_d_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 114); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.d.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fconv_f2d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - (rm) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 114); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 115: FEQ.D */ - compile_ret_t __feq_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 115); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template zext(fcmp_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(0) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 115); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 116: FLT.D */ - compile_ret_t __flt_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 116); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template zext(fcmp_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(2) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 116); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 117: FLE.D */ - compile_ret_t __fle_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 117); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template zext(fcmp_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(1) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 117); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 118: FCLASS.D */ - compile_ret_t __fclass_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 118); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = fclass_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ) - ); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 118); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 119: FCVT.W.D */ - compile_ret_t __fcvt_w_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 119); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template sext(fcvt_64_32( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - super::template zext(0), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 119); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 120: FCVT.WU.D */ - compile_ret_t __fcvt_wu_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 120); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template sext(fcvt_64_32( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - super::template zext(1), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 120); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 121: FCVT.D.W */ - compile_ret_t __fcvt_d_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 121); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fcvt_32_64( - super::template sext(static_cast( - super::template get_reg(rs1 + traits::X0) - )), - super::template zext(2), - (rm) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 121); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 122: FCVT.D.WU */ - compile_ret_t __fcvt_d_wu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 122); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fcvt_32_64( - super::template zext(static_cast( - super::template get_reg(rs1 + traits::X0) - )), - super::template zext(3), - (rm) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 122); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 123: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 123); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(imm == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (super::template get_reg(2 + traits::X0) + (imm)); - super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 123); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 124: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 124); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 124); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 125: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 125); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto MEMtmp0_val = super::template get_reg(rs2 + 8 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 125); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 126: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 126); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - super::template get_reg(rs1 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 126); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 127: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 127); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "c.nop"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - /* TODO: describe operations for C.NOP ! */ - this->do_sync(POST_SYNC, 127); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 128: C.JAL */ - compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 128); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (cur_pc_val + 2); - super::template get_reg(1 + traits::X0)=Xtmp0_val; - auto PC_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 128); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 129: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 129); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(rd == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (imm); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 129); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 130: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 130); - - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(rd == 0){ - raise_trap(0, 2); - } - if(imm == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (imm); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 130); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 131: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 131); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (static_cast(super::template get_reg(2 + traits::X0)) + (imm)); - super::template get_reg(2 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 131); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 132: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 132); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rs1_idx_val = rs1 + 8; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0))>>(shamt)); - super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 132); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 133: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 133); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rs1_idx_val = rs1 + 8; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0))>>(shamt)); - super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 133); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 134: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 134); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rs1_idx_val = rs1 + 8; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0)) & (imm)); - super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 134); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 135: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 135); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) - super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 135); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 136: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 136); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) ^ super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 136); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 137: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 137); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) | super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 137); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 138: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 138); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) & super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 138); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 139: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 139); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 139); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 140: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 140); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = (super::template get_reg(rs1 + 8 + traits::X0) == 0)? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 2); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 140); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 141: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 141); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = (super::template get_reg(rs1 + 8 + traits::X0) != 0)? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 2); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 141); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 142: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 142); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(rs1 == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); - super::template get_reg(rs1 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 142); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 143: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 143); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 143); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 144: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 144); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = super::template get_reg(rs2 + traits::X0); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 144); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 145: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 145); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(traits::NEXT_PC) = PC_val; - super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - this->do_sync(POST_SYNC, 145); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 146: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 146); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (super::template get_reg(rd + traits::X0) + super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 146); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 147: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 147); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (cur_pc_val + 2); - super::template get_reg(1 + traits::X0)=Xtmp0_val; - auto PC_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(traits::NEXT_PC) = PC_val; - super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - this->do_sync(POST_SYNC, 147); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 148: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 148); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "c.ebreak"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - raise_trap(0, 3); - this->do_sync(POST_SYNC, 148); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 149: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 149); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 149); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 150: DII */ - compile_ret_t __dii(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 150); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "dii"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - raise_trap(0, 2); - this->do_sync(POST_SYNC, 150); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 151: C.FLW */ - compile_ret_t __c_flw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 151); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rd}), {uimm}({rs1})", fmt::arg("mnemonic", "c.flw"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 32){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + 8 + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + 8 + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 151); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 152: C.FSW */ - compile_ret_t __c_fsw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 152); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rs2}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fsw"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + 8 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 152); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 153: C.FLWSP */ - compile_ret_t __c_flwsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 153); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {uimm}(x2)", fmt::arg("mnemonic", "c.flwsp"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 32){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 153); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 154: C.FSWSP */ - compile_ret_t __c_fswsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 154); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {uimm}(x2), ", fmt::arg("mnemonic", "c.fswsp"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 154); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 155: C.FLD */ - compile_ret_t __c_fld(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 155); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rd}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fld"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + 8 + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + 8 + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 155); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 156: C.FSD */ - compile_ret_t __c_fsd(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 156); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rs2}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fsd"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + 8 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 156); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 157: C.FLDSP */ - compile_ret_t __c_fldsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 157); - - uint16_t uimm = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {uimm}(x2)", fmt::arg("mnemonic", "c.fldsp"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 157); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 158: C.FSDSP */ - compile_ret_t __c_fsdsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 158); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint16_t uimm = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {uimm}(x2), ", fmt::arg("mnemonic", "c.fsdsp"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 158); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /**************************************************************************** - * 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){ - 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::rv32gc *core, unsigned short port, bool dump) { - auto ret = new rv32gc::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} // namespace interp -} // namespace iss diff --git a/src/vm/interp/vm_rv32imac.cpp b/src/vm/interp/vm_rv32imac.cpp deleted file mode 100644 index 5d4a379..0000000 --- a/src/vm/interp/vm_rv32imac.cpp +++ /dev/null @@ -1,3793 +0,0 @@ -/******************************************************************************* - * Copyright (C) 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 "../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 rv32imac { -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::interp::vm_base { -public: - 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 iss::interp::vm_base::get_reg; - - 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_trap(uint16_t trap_id, uint16_t cause){ - auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; - this->template get_reg(arch::traits::TRAP_STATE) = trap_val; - this->template get_reg(arch::traits::NEXT_PC) = std::numeric_limits::max(); - } - - void leave_trap(unsigned lvl){ - this->core.leave_trap(lvl); - auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); - this->template get_reg(arch::traits::NEXT_PC) = pc_val; - this->template get_reg(arch::traits::LAST_BRANCH) = std::numeric_limits::max(); - } - - void wait(unsigned type){ - this->core.wait_until(type); - } - - -private: - /**************************************************************************** - * start opcode definitions - ****************************************************************************/ - 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, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &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, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &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 MUL */ - {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH */ - {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU */ - {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU */ - {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV */ - {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU */ - {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM */ - {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU */ - {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction LR.W */ - {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lr_w}, - /* instruction SC.W */ - {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__sc_w}, - /* instruction AMOSWAP.W */ - {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_w}, - /* instruction AMOADD.W */ - {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_w}, - /* instruction AMOXOR.W */ - {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_w}, - /* instruction AMOAND.W */ - {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_w}, - /* instruction AMOOR.W */ - {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_w}, - /* instruction AMOMIN.W */ - {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_w}, - /* instruction AMOMAX.W */ - {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_w}, - /* instruction AMOMINU.W */ - {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_w}, - /* instruction AMOMAXU.W */ - {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_w}, - /* instruction C.ADDI4SPN */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII */ - {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 0); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (imm); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 0); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 1: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 1); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 1); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 2: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 2); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (cur_pc_val + 4); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto PC_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 2); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 3: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 3); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto new_pc_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = (cur_pc_val + 4); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto PC_val = (new_pc_val & ~(0x1)); - super::template get_reg(traits::NEXT_PC) = PC_val; - super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - this->do_sync(POST_SYNC, 3); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 4: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 4); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) == super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 4); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 5: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 5); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) != super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 5); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 6: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 6); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 6); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 7: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 7); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) >= static_cast(super::template get_reg(rs2 + traits::X0)))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 7); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 8: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 8); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) < super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 8); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 9: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 9); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) >= super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 9); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 10: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 10); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 10); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 11: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 11); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 11); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 12: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 12); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 12); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 13: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 13); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 13); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 14: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 14); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 14); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 15: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 15); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 15); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 16: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 16); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 16); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 17: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 17); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 17); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 18: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 18); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 18); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 19: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 19); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < (imm))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 19); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 20: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 20); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - int32_t full_imm_val = imm; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) < full_imm_val)? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 20); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 21: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 21); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) ^ (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 21); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 22: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 22); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) | (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 22); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 23: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 23); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) & (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 23); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 24: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 24); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - } - this->do_sync(POST_SYNC, 24); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 25: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 25); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - } - this->do_sync(POST_SYNC, 25); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 26: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 26); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - } - this->do_sync(POST_SYNC, 26); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 27: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 27); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) + super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 27); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 28: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 28); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) - super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 28); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 29: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 29); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 29); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 30: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 30); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 30); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 31: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 31); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) < super::template zext(super::template get_reg(rs2 + traits::X0)))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 31); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 32: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 32); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) ^ super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 32); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 33: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 33); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 33); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 34: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 34); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 34); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 35: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 35); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) | super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 35); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 36: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 36); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) & super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 36); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 37: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 37); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "fence"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (((pred) << 4) | (succ)); - super::write_mem(traits::FENCE, (0), static_cast(FENCEtmp0_val)); - this->do_sync(POST_SYNC, 37); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 38: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 38); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "fence_i"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (imm); - super::write_mem(traits::FENCE, (1), static_cast(FENCEtmp0_val)); - this->do_sync(POST_SYNC, 38); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 39: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 39); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ecall"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - raise_trap(0, 11); - this->do_sync(POST_SYNC, 39); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 40: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 40); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ebreak"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - raise_trap(0, 3); - this->do_sync(POST_SYNC, 40); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 41: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 41); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "uret"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(0); - this->do_sync(POST_SYNC, 41); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 42: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 42); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "sret"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(1); - this->do_sync(POST_SYNC, 42); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 43: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 43); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "mret"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(3); - this->do_sync(POST_SYNC, 43); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 44: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 44); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "wfi"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - wait(1); - this->do_sync(POST_SYNC, 44); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 45: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 45); - - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "sfence.vma"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (rs1); - super::write_mem(traits::FENCE, (2), static_cast(FENCEtmp0_val)); - auto FENCEtmp1_val = (rs2); - super::write_mem(traits::FENCE, (3), static_cast(FENCEtmp1_val)); - this->do_sync(POST_SYNC, 45); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 46: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 46); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto rs_val_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto csr_val_val = super::template read_mem(traits::CSR, (csr)); - auto CSRtmp0_val = rs_val_val; - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); - auto Xtmp1_val = csr_val_val; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } else { - auto CSRtmp2_val = rs_val_val; - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp2_val)); - } - this->do_sync(POST_SYNC, 46); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 47: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 47); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto xrd_val = super::template read_mem(traits::CSR, (csr)); - auto xrs1_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = xrd_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - if(rs1 != 0){ - auto CSRtmp1_val = (xrd_val | xrs1_val); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 47); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 48: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 48); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto xrd_val = super::template read_mem(traits::CSR, (csr)); - auto xrs1_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = xrd_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - if(rs1 != 0){ - auto CSRtmp1_val = (xrd_val & ~(xrs1_val)); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 48); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 49: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 49); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = super::template read_mem(traits::CSR, (csr)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto CSRtmp1_val = super::template zext((zimm)); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - this->do_sync(POST_SYNC, 49); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 50: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 50); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = super::template read_mem(traits::CSR, (csr)); - if(zimm != 0){ - auto CSRtmp0_val = (res_val | super::template zext((zimm))); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); - } - if(rd != 0){ - auto Xtmp1_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - this->do_sync(POST_SYNC, 50); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 51: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 51); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = super::template read_mem(traits::CSR, (csr)); - if(rd != 0){ - auto Xtmp0_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - if(zimm != 0){ - auto CSRtmp1_val = (res_val & ~(super::template zext((zimm)))); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 51); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 52: MUL */ - compile_ret_t __mul(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 52); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext(res_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 52); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 53: MULH */ - compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 53); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template sext(super::template get_reg(rs1 + traits::X0)) * super::template sext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext((res_val >> (32))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 53); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 54: MULHSU */ - compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 54); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template sext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext((res_val >> (32))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 54); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 55: MULHU */ - compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 55); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext((res_val >> (32))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 55); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 56: DIV */ - compile_ret_t __div(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 56); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - uint32_t M1_val = - 1; - uint8_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - { - if(((super::template get_reg(rs1 + traits::X0) == MMIN_val) && (super::template get_reg(rs2 + traits::X0) == M1_val))) { - auto Xtmp0_val = MMIN_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = (static_cast(super::template get_reg(rs1 + traits::X0)) / static_cast(super::template get_reg(rs2 + traits::X0))); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - else { - auto Xtmp2_val = -(1); - super::template get_reg(rd + traits::X0)=Xtmp2_val; - } - } - } - this->do_sync(POST_SYNC, 56); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 57: DIVU */ - compile_ret_t __divu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 57); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) / super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = -(1); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - this->do_sync(POST_SYNC, 57); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 58: REM */ - compile_ret_t __rem(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 58); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - uint32_t M1_val = - 1; - uint32_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - { - if(((super::template get_reg(rs1 + traits::X0) == MMIN_val) && (super::template get_reg(rs2 + traits::X0) == M1_val))) { - auto Xtmp0_val = 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = (static_cast(super::template get_reg(rs1 + traits::X0)) % static_cast(super::template get_reg(rs2 + traits::X0))); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - else { - auto Xtmp2_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(rd + traits::X0)=Xtmp2_val; - } - } - } - this->do_sync(POST_SYNC, 58); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 59: REMU */ - compile_ret_t __remu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 59); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) % super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - this->do_sync(POST_SYNC, 59); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 60: LR.W */ - compile_ret_t __lr_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 60); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto REStmp1_val = super::template sext(-(1)); - super::write_mem(traits::RES, offs_val, static_cast(REStmp1_val)); - } - this->do_sync(POST_SYNC, 60); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 61: SC.W */ - compile_ret_t __sc_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 61); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template read_mem(traits::RES, offs_val); - { - if((res1_val != 0)) { - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - } - } - if(rd != 0){ - auto Xtmp1_val = (res1_val != super::template zext(0))? - 0: - 1; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - this->do_sync(POST_SYNC, 61); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 62: AMOSWAP.W */ - compile_ret_t __amoswap_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 62); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto MEMtmp1_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 62); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 63: AMOADD.W */ - compile_ret_t __amoadd_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 63); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val + super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 63); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 64: AMOXOR.W */ - compile_ret_t __amoxor_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 64); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val ^ super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 64); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 65: AMOAND.W */ - compile_ret_t __amoand_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 65); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val & super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 65); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 66: AMOOR.W */ - compile_ret_t __amoor_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 66); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val | super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 66); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 67: AMOMIN.W */ - compile_ret_t __amomin_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 67); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (static_cast(res1_val) > static_cast(super::template get_reg(rs2 + traits::X0)))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 67); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 68: AMOMAX.W */ - compile_ret_t __amomax_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 68); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (static_cast(res1_val) < static_cast(super::template get_reg(rs2 + traits::X0)))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 68); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 69: AMOMINU.W */ - compile_ret_t __amominu_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 69); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val > super::template get_reg(rs2 + traits::X0))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 69); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 70: AMOMAXU.W */ - compile_ret_t __amomaxu_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 70); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val < super::template get_reg(rs2 + traits::X0))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 70); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 71: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 71); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(imm == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (super::template get_reg(2 + traits::X0) + (imm)); - super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 71); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 72: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 72); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 72); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 73: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 73); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto MEMtmp0_val = super::template get_reg(rs2 + 8 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 73); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 74: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 74); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - super::template get_reg(rs1 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 74); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 75: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 75); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "c.nop"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - /* TODO: describe operations for C.NOP ! */ - this->do_sync(POST_SYNC, 75); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 76: C.JAL */ - compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 76); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (cur_pc_val + 2); - super::template get_reg(1 + traits::X0)=Xtmp0_val; - auto PC_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 76); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 77: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 77); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(rd == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (imm); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 77); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 78: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 78); - - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(rd == 0){ - raise_trap(0, 2); - } - if(imm == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (imm); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 78); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 79: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 79); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (static_cast(super::template get_reg(2 + traits::X0)) + (imm)); - super::template get_reg(2 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 79); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 80: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 80); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rs1_idx_val = rs1 + 8; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0))>>(shamt)); - super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 80); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 81: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 81); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rs1_idx_val = rs1 + 8; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0))>>(shamt)); - super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 81); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 82: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 82); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rs1_idx_val = rs1 + 8; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0)) & (imm)); - super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 82); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 83: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 83); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) - super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 83); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 84: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 84); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) ^ super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 84); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 85: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 85); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) | super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 85); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 86: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 86); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) & super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 86); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 87: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 87); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 87); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 88: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 88); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = (super::template get_reg(rs1 + 8 + traits::X0) == 0)? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 2); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 88); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 89: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 89); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = (super::template get_reg(rs1 + 8 + traits::X0) != 0)? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 2); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 89); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 90: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 90); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(rs1 == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); - super::template get_reg(rs1 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 90); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 91: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 91); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 91); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 92: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 92); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = super::template get_reg(rs2 + traits::X0); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 92); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 93: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 93); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(traits::NEXT_PC) = PC_val; - super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - this->do_sync(POST_SYNC, 93); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 94: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 94); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (super::template get_reg(rd + traits::X0) + super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 94); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 95: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 95); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (cur_pc_val + 2); - super::template get_reg(1 + traits::X0)=Xtmp0_val; - auto PC_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(traits::NEXT_PC) = PC_val; - super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - this->do_sync(POST_SYNC, 95); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 96: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 96); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "c.ebreak"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - raise_trap(0, 3); - this->do_sync(POST_SYNC, 96); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 97: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 97); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 97); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 98: DII */ - compile_ret_t __dii(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 98); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "dii"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - raise_trap(0, 2); - this->do_sync(POST_SYNC, 98); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /**************************************************************************** - * 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){ - 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::rv32imac *core, unsigned short port, bool dump) { - auto ret = new rv32imac::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} // namespace interp -} // namespace iss diff --git a/src/vm/interp/vm_rv64gc.cpp b/src/vm/interp/vm_rv64gc.cpp deleted file mode 100644 index 4e404f8..0000000 --- a/src/vm/interp/vm_rv64gc.cpp +++ /dev/null @@ -1,8694 +0,0 @@ -/******************************************************************************* - * Copyright (C) 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 "../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 rv64gc { -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::interp::vm_base { -public: - 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 iss::interp::vm_base::get_reg; - - 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_trap(uint16_t trap_id, uint16_t cause){ - auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; - this->template get_reg(arch::traits::TRAP_STATE) = trap_val; - this->template get_reg(arch::traits::NEXT_PC) = std::numeric_limits::max(); - } - - void leave_trap(unsigned lvl){ - this->core.leave_trap(lvl); - auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); - this->template get_reg(arch::traits::NEXT_PC) = pc_val; - this->template get_reg(arch::traits::LAST_BRANCH) = std::numeric_limits::max(); - } - - void wait(unsigned type){ - this->core.wait_until(type); - } - - -private: - /**************************************************************************** - * start opcode definitions - ****************************************************************************/ - 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, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &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, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &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 LWU */ - {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, - /* instruction LD */ - {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, &this_class::__ld}, - /* instruction SD */ - {32, 0b00000000000000000011000000100011, 0b00000000000000000111000001111111, &this_class::__sd}, - /* instruction ADDIW */ - {32, 0b00000000000000000000000000011011, 0b00000000000000000111000001111111, &this_class::__addiw}, - /* instruction SLLIW */ - {32, 0b00000000000000000001000000011011, 0b11111110000000000111000001111111, &this_class::__slliw}, - /* instruction SRLIW */ - {32, 0b00000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__srliw}, - /* instruction SRAIW */ - {32, 0b01000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__sraiw}, - /* instruction ADDW */ - {32, 0b00000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__addw}, - /* instruction SUBW */ - {32, 0b01000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__subw}, - /* instruction SLLW */ - {32, 0b00000000000000000001000000111011, 0b11111110000000000111000001111111, &this_class::__sllw}, - /* instruction SRLW */ - {32, 0b00000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__srlw}, - /* instruction SRAW */ - {32, 0b01000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__sraw}, - /* instruction MUL */ - {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH */ - {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU */ - {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU */ - {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV */ - {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU */ - {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM */ - {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU */ - {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction MULW */ - {32, 0b00000010000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__mulw}, - /* instruction DIVW */ - {32, 0b00000010000000000100000000111011, 0b11111110000000000111000001111111, &this_class::__divw}, - /* instruction DIVUW */ - {32, 0b00000010000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__divuw}, - /* instruction REMW */ - {32, 0b00000010000000000110000000111011, 0b11111110000000000111000001111111, &this_class::__remw}, - /* instruction REMUW */ - {32, 0b00000010000000000111000000111011, 0b11111110000000000111000001111111, &this_class::__remuw}, - /* instruction LR.W */ - {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lr_w}, - /* instruction SC.W */ - {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__sc_w}, - /* instruction AMOSWAP.W */ - {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_w}, - /* instruction AMOADD.W */ - {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_w}, - /* instruction AMOXOR.W */ - {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_w}, - /* instruction AMOAND.W */ - {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_w}, - /* instruction AMOOR.W */ - {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_w}, - /* instruction AMOMIN.W */ - {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_w}, - /* instruction AMOMAX.W */ - {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_w}, - /* instruction AMOMINU.W */ - {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_w}, - /* instruction AMOMAXU.W */ - {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_w}, - /* instruction LR.D */ - {32, 0b00010000000000000011000000101111, 0b11111001111100000111000001111111, &this_class::__lr_d}, - /* instruction SC.D */ - {32, 0b00011000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__sc_d}, - /* instruction AMOSWAP.D */ - {32, 0b00001000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_d}, - /* instruction AMOADD.D */ - {32, 0b00000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_d}, - /* instruction AMOXOR.D */ - {32, 0b00100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_d}, - /* instruction AMOAND.D */ - {32, 0b01100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_d}, - /* instruction AMOOR.D */ - {32, 0b01000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_d}, - /* instruction AMOMIN.D */ - {32, 0b10000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_d}, - /* instruction AMOMAX.D */ - {32, 0b10100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_d}, - /* instruction AMOMINU.D */ - {32, 0b11000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_d}, - /* instruction AMOMAXU.D */ - {32, 0b11100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_d}, - /* instruction FLW */ - {32, 0b00000000000000000010000000000111, 0b00000000000000000111000001111111, &this_class::__flw}, - /* instruction FSW */ - {32, 0b00000000000000000010000000100111, 0b00000000000000000111000001111111, &this_class::__fsw}, - /* instruction FMADD.S */ - {32, 0b00000000000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_s}, - /* instruction FMSUB.S */ - {32, 0b00000000000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_s}, - /* instruction FNMADD.S */ - {32, 0b00000000000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_s}, - /* instruction FNMSUB.S */ - {32, 0b00000000000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_s}, - /* instruction FADD.S */ - {32, 0b00000000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_s}, - /* instruction FSUB.S */ - {32, 0b00001000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_s}, - /* instruction FMUL.S */ - {32, 0b00010000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_s}, - /* instruction FDIV.S */ - {32, 0b00011000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_s}, - /* instruction FSQRT.S */ - {32, 0b01011000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_s}, - /* instruction FSGNJ.S */ - {32, 0b00100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_s}, - /* instruction FSGNJN.S */ - {32, 0b00100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_s}, - /* instruction FSGNJX.S */ - {32, 0b00100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_s}, - /* instruction FMIN.S */ - {32, 0b00101000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_s}, - /* instruction FMAX.S */ - {32, 0b00101000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_s}, - /* instruction FCVT.W.S */ - {32, 0b11000000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_s}, - /* instruction FCVT.WU.S */ - {32, 0b11000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_s}, - /* instruction FEQ.S */ - {32, 0b10100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_s}, - /* instruction FLT.S */ - {32, 0b10100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_s}, - /* instruction FLE.S */ - {32, 0b10100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_s}, - /* instruction FCLASS.S */ - {32, 0b11100000000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_s}, - /* instruction FCVT.S.W */ - {32, 0b11010000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_w}, - /* instruction FCVT.S.WU */ - {32, 0b11010000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_wu}, - /* instruction FMV.X.W */ - {32, 0b11100000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_w}, - /* instruction FMV.W.X */ - {32, 0b11110000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_w_x}, - /* instruction FCVT.L.S */ - {32, 0b11000000001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_l_s}, - /* instruction FCVT.LU.S */ - {32, 0b11000000001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_lu_s}, - /* instruction FCVT.S.L */ - {32, 0b11010000001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_l}, - /* instruction FCVT.S.LU */ - {32, 0b11010000001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_lu}, - /* instruction FLD */ - {32, 0b00000000000000000011000000000111, 0b00000000000000000111000001111111, &this_class::__fld}, - /* instruction FSD */ - {32, 0b00000000000000000011000000100111, 0b00000000000000000111000001111111, &this_class::__fsd}, - /* instruction FMADD.D */ - {32, 0b00000010000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_d}, - /* instruction FMSUB.D */ - {32, 0b00000010000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_d}, - /* instruction FNMADD.D */ - {32, 0b00000010000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_d}, - /* instruction FNMSUB.D */ - {32, 0b00000010000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_d}, - /* instruction FADD.D */ - {32, 0b00000010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_d}, - /* instruction FSUB.D */ - {32, 0b00001010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_d}, - /* instruction FMUL.D */ - {32, 0b00010010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_d}, - /* instruction FDIV.D */ - {32, 0b00011010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_d}, - /* instruction FSQRT.D */ - {32, 0b01011010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_d}, - /* instruction FSGNJ.D */ - {32, 0b00100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_d}, - /* instruction FSGNJN.D */ - {32, 0b00100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_d}, - /* instruction FSGNJX.D */ - {32, 0b00100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_d}, - /* instruction FMIN.D */ - {32, 0b00101010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_d}, - /* instruction FMAX.D */ - {32, 0b00101010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_d}, - /* instruction FCVT.S.D */ - {32, 0b01000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_d}, - /* instruction FCVT.D.S */ - {32, 0b01000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_s}, - /* instruction FEQ.D */ - {32, 0b10100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_d}, - /* instruction FLT.D */ - {32, 0b10100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_d}, - /* instruction FLE.D */ - {32, 0b10100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_d}, - /* instruction FCLASS.D */ - {32, 0b11100010000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_d}, - /* instruction FCVT.W.D */ - {32, 0b11000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_d}, - /* instruction FCVT.WU.D */ - {32, 0b11000010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_d}, - /* instruction FCVT.D.W */ - {32, 0b11010010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_w}, - /* instruction FCVT.D.WU */ - {32, 0b11010010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_wu}, - /* instruction FCVT.L.D */ - {32, 0b11000010001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_l_d}, - /* instruction FCVT.LU.D */ - {32, 0b11000010001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_lu_d}, - /* instruction FCVT.D.L */ - {32, 0b11010010001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_l}, - /* instruction FCVT.D.LU */ - {32, 0b11010010001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_lu}, - /* instruction FMV.X.D */ - {32, 0b11100010000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_d}, - /* instruction FMV.D.X */ - {32, 0b11110010000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_d_x}, - /* instruction C.ADDI4SPN */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII */ - {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, - /* instruction C.LD */ - {16, 0b0110000000000000, 0b1110000000000011, &this_class::__c_ld}, - /* instruction C.SD */ - {16, 0b1110000000000000, 0b1110000000000011, &this_class::__c_sd}, - /* instruction C.SUBW */ - {16, 0b1001110000000001, 0b1111110001100011, &this_class::__c_subw}, - /* instruction C.ADDW */ - {16, 0b1001110000100001, 0b1111110001100011, &this_class::__c_addw}, - /* instruction C.ADDIW */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_addiw}, - /* instruction C.LDSP */ - {16, 0b0110000000000010, 0b1110000000000011, &this_class::__c_ldsp}, - /* instruction C.SDSP */ - {16, 0b1110000000000010, 0b1110000000000011, &this_class::__c_sdsp}, - /* instruction C.FLW */ - {16, 0b0110000000000000, 0b1110000000000011, &this_class::__c_flw}, - /* instruction C.FSW */ - {16, 0b1110000000000000, 0b1110000000000011, &this_class::__c_fsw}, - /* instruction C.FLWSP */ - {16, 0b0110000000000010, 0b1110000000000011, &this_class::__c_flwsp}, - /* instruction C.FSWSP */ - {16, 0b1110000000000010, 0b1110000000000011, &this_class::__c_fswsp}, - /* instruction C.FLD */ - {16, 0b0010000000000000, 0b1110000000000011, &this_class::__c_fld}, - /* instruction C.FSD */ - {16, 0b1010000000000000, 0b1110000000000011, &this_class::__c_fsd}, - /* instruction C.FLDSP */ - {16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_fldsp}, - /* instruction C.FSDSP */ - {16, 0b1010000000000010, 0b1110000000000011, &this_class::__c_fsdsp}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 0); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (imm); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 0); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 1: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 1); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 1); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 2: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 2); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (cur_pc_val + 4); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto PC_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 2); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 3: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 3); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto new_pc_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = (cur_pc_val + 4); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto PC_val = (new_pc_val & ~(0x1)); - super::template get_reg(traits::NEXT_PC) = PC_val; - super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - this->do_sync(POST_SYNC, 3); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 4: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 4); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) == super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 4); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 5: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 5); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) != super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 5); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 6: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 6); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 6); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 7: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 7); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) >= static_cast(super::template get_reg(rs2 + traits::X0)))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 7); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 8: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 8); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) < super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 8); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 9: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 9); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (super::template get_reg(rs1 + traits::X0) >= super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 4); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 9); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 10: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 10); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 10); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 11: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 11); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 11); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 12: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 12); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 12); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 13: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 13); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 13); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 14: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 14); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 14); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 15: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 15); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 15); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 16: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 16); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 16); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 17: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 17); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 17); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 18: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 18); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 18); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 19: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 19); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < (imm))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 19); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 20: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 20); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - int64_t full_imm_val = imm; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) < full_imm_val)? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 20); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 21: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 21); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) ^ (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 21); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 22: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 22); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) | (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 22); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 23: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 23); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) & (imm)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 23); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 24: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 24); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - } - this->do_sync(POST_SYNC, 24); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 25: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 25); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - } - this->do_sync(POST_SYNC, 25); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 26: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 26); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(shamt > 31){ - raise_trap(0, 0); - } else { - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - } - this->do_sync(POST_SYNC, 26); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 27: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 27); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) + super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 27); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 28: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 28); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) - super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 28); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 29: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 29); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(super::template get_reg(rs2 + traits::X0) & ((64) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 29); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 30: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 30); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 30); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 31: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 31); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) < super::template zext(super::template get_reg(rs2 + traits::X0)))? - 1: - 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 31); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 32: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 32); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) ^ super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 32); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 33: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 33); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((64) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 33); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 34: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 34); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((64) - 1))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 34); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 35: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 35); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) | super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 35); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 36: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 36); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) & super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 36); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 37: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 37); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "fence"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (((pred) << 4) | (succ)); - super::write_mem(traits::FENCE, (0), static_cast(FENCEtmp0_val)); - this->do_sync(POST_SYNC, 37); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 38: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 38); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "fence_i"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (imm); - super::write_mem(traits::FENCE, (1), static_cast(FENCEtmp0_val)); - this->do_sync(POST_SYNC, 38); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 39: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 39); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ecall"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - raise_trap(0, 11); - this->do_sync(POST_SYNC, 39); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 40: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 40); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ebreak"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - raise_trap(0, 3); - this->do_sync(POST_SYNC, 40); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 41: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 41); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "uret"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(0); - this->do_sync(POST_SYNC, 41); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 42: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 42); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "sret"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(1); - this->do_sync(POST_SYNC, 42); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 43: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 43); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "mret"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - leave_trap(3); - this->do_sync(POST_SYNC, 43); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 44: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 44); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "wfi"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - wait(1); - this->do_sync(POST_SYNC, 44); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 45: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 45); - - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "sfence.vma"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto FENCEtmp0_val = (rs1); - super::write_mem(traits::FENCE, (2), static_cast(FENCEtmp0_val)); - auto FENCEtmp1_val = (rs2); - super::write_mem(traits::FENCE, (3), static_cast(FENCEtmp1_val)); - this->do_sync(POST_SYNC, 45); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 46: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 46); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto rs_val_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto csr_val_val = super::template read_mem(traits::CSR, (csr)); - auto CSRtmp0_val = rs_val_val; - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); - auto Xtmp1_val = csr_val_val; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } else { - auto CSRtmp2_val = rs_val_val; - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp2_val)); - } - this->do_sync(POST_SYNC, 46); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 47: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 47); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto xrd_val = super::template read_mem(traits::CSR, (csr)); - auto xrs1_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = xrd_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - if(rs1 != 0){ - auto CSRtmp1_val = (xrd_val | xrs1_val); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 47); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 48: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 48); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto xrd_val = super::template read_mem(traits::CSR, (csr)); - auto xrs1_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = xrd_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - if(rs1 != 0){ - auto CSRtmp1_val = (xrd_val & ~(xrs1_val)); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 48); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 49: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 49); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = super::template read_mem(traits::CSR, (csr)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto CSRtmp1_val = super::template zext((zimm)); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - this->do_sync(POST_SYNC, 49); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 50: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 50); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = super::template read_mem(traits::CSR, (csr)); - if(zimm != 0){ - auto CSRtmp0_val = (res_val | super::template zext((zimm))); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); - } - if(rd != 0){ - auto Xtmp1_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - this->do_sync(POST_SYNC, 50); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 51: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 51); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = super::template read_mem(traits::CSR, (csr)); - if(rd != 0){ - auto Xtmp0_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - if(zimm != 0){ - auto CSRtmp1_val = (res_val & ~(super::template zext((zimm)))); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); - } - this->do_sync(POST_SYNC, 51); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 52: LWU */ - compile_ret_t __lwu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 52); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lwu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 52); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 53: LD */ - compile_ret_t __ld(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 53); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "ld"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 53); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 54: SD */ - compile_ret_t __sd(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 54); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sd"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 54); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 55: ADDIW */ - compile_ret_t __addiw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 55); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - )) + (imm)); - auto Xtmp0_val = super::template sext(res_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 55); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 56: SLLIW */ - compile_ret_t __slliw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 56); - - 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", "slliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto sh_val_val = (static_cast( - super::template get_reg(rs1 + traits::X0) - )<<(shamt)); - auto Xtmp0_val = super::template sext(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 56); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 57: SRLIW */ - compile_ret_t __srliw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 57); - - 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", "srliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto sh_val_val = (static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - ))>>(shamt)); - auto Xtmp0_val = super::template sext(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 57); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 58: SRAIW */ - compile_ret_t __sraiw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 58); - - 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", "sraiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto sh_val_val = (static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - ))>>(shamt)); - auto Xtmp0_val = super::template sext(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 58); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 59: ADDW */ - compile_ret_t __addw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 59); - - 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 */ - this->core.disass_output(pc.val, "addw"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (static_cast( - super::template get_reg(rs1 + traits::X0) - ) + static_cast( - super::template get_reg(rs2 + traits::X0) - )); - auto Xtmp0_val = super::template sext(res_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 59); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 60: SUBW */ - compile_ret_t __subw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 60); - - 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 */ - this->core.disass_output(pc.val, "subw"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (static_cast( - super::template get_reg(rs1 + traits::X0) - ) - static_cast( - super::template get_reg(rs2 + traits::X0) - )); - auto Xtmp0_val = super::template sext(res_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 60); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 61: SLLW */ - compile_ret_t __sllw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 61); - - 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", "sllw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = (static_cast( - super::template get_reg(rs2 + traits::X0) - ) & mask_val); - auto sh_val_val = (static_cast( - super::template get_reg(rs1 + traits::X0) - )<(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 61); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 62: SRLW */ - compile_ret_t __srlw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 62); - - 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", "srlw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = (static_cast( - super::template get_reg(rs2 + traits::X0) - ) & mask_val); - auto sh_val_val = (static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - ))>>count_val); - auto Xtmp0_val = super::template sext(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 62); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 63: SRAW */ - compile_ret_t __sraw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 63); - - 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", "sraw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = (static_cast( - super::template get_reg(rs2 + traits::X0) - ) & mask_val); - auto sh_val_val = (static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - ))>>count_val); - auto Xtmp0_val = super::template sext(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 63); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 64: MUL */ - compile_ret_t __mul(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 64); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext(res_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 64); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 65: MULH */ - compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 65); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template sext(super::template get_reg(rs1 + traits::X0)) * super::template sext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext((res_val >> (64))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 65); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 66: MULHSU */ - compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 66); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template sext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext((res_val >> (64))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 66); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 67: MULHU */ - compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 67); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); - auto Xtmp0_val = super::template zext((res_val >> (64))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 67); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 68: DIV */ - compile_ret_t __div(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 68); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - uint64_t M1_val = - 1; - uint8_t XLM1_val = 64 - 1; - uint64_t ONE_val = 1; - uint64_t MMIN_val = ONE_val << XLM1_val; - { - if(((super::template get_reg(rs1 + traits::X0) == MMIN_val) && (super::template get_reg(rs2 + traits::X0) == M1_val))) { - auto Xtmp0_val = MMIN_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = (static_cast(super::template get_reg(rs1 + traits::X0)) / static_cast(super::template get_reg(rs2 + traits::X0))); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - else { - auto Xtmp2_val = -(1); - super::template get_reg(rd + traits::X0)=Xtmp2_val; - } - } - } - this->do_sync(POST_SYNC, 68); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 69: DIVU */ - compile_ret_t __divu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 69); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) / super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = -(1); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - this->do_sync(POST_SYNC, 69); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 70: REM */ - compile_ret_t __rem(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 70); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - uint64_t M1_val = - 1; - uint32_t XLM1_val = 64 - 1; - uint64_t ONE_val = 1; - uint64_t MMIN_val = ONE_val << XLM1_val; - { - if(((super::template get_reg(rs1 + traits::X0) == MMIN_val) && (super::template get_reg(rs2 + traits::X0) == M1_val))) { - auto Xtmp0_val = 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = (static_cast(super::template get_reg(rs1 + traits::X0)) % static_cast(super::template get_reg(rs2 + traits::X0))); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - else { - auto Xtmp2_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(rd + traits::X0)=Xtmp2_val; - } - } - } - this->do_sync(POST_SYNC, 70); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 71: REMU */ - compile_ret_t __remu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 71); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) % super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - this->do_sync(POST_SYNC, 71); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 72: MULW */ - compile_ret_t __mulw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 72); - - 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", "mulw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = super::template sext((static_cast( - super::template get_reg(rs1 + traits::X0) - ) * static_cast( - super::template get_reg(rs2 + traits::X0) - ))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 72); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 73: DIVW */ - compile_ret_t __divw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 73); - - 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", "divw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - uint32_t M1_val = - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << 31; - { - if(((static_cast( - super::template get_reg(rs1 + traits::X0) - ) == MMIN_val) && (static_cast( - super::template get_reg(rs2 + traits::X0) - ) == M1_val))) { - auto Xtmp0_val = (-(1) << 31); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = super::template sext((static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - )) / static_cast(static_cast( - super::template get_reg(rs2 + traits::X0) - )))); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - else { - auto Xtmp2_val = -(1); - super::template get_reg(rd + traits::X0)=Xtmp2_val; - } - } - } - this->do_sync(POST_SYNC, 73); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 74: DIVUW */ - compile_ret_t __divuw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 74); - - 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", "divuw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((static_cast( - super::template get_reg(rs2 + traits::X0) - ) != 0)) { - auto Xtmp0_val = super::template sext((static_cast( - super::template get_reg(rs1 + traits::X0) - ) / static_cast( - super::template get_reg(rs2 + traits::X0) - ))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = -(1); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - this->do_sync(POST_SYNC, 74); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 75: REMW */ - compile_ret_t __remw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 75); - - 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", "remw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((super::template get_reg(rs2 + traits::X0) != 0)) { - uint32_t M1_val = - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << 31; - { - if(((static_cast( - super::template get_reg(rs1 + traits::X0) - ) == MMIN_val) && (super::template get_reg(rs2 + traits::X0) == M1_val))) { - auto Xtmp0_val = 0; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = super::template sext((static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - )) % static_cast(static_cast( - super::template get_reg(rs2 + traits::X0) - )))); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - else { - auto Xtmp2_val = super::template sext(static_cast( - super::template get_reg(rs1 + traits::X0) - )); - super::template get_reg(rd + traits::X0)=Xtmp2_val; - } - } - } - this->do_sync(POST_SYNC, 75); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 76: REMUW */ - compile_ret_t __remuw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 76); - - 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", "remuw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - { - if((static_cast( - super::template get_reg(rs2 + traits::X0) - ) != 0)) { - auto Xtmp0_val = super::template sext((static_cast( - super::template get_reg(rs1 + traits::X0) - ) % static_cast( - super::template get_reg(rs2 + traits::X0) - ))); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - else { - auto Xtmp1_val = super::template sext(static_cast( - super::template get_reg(rs1 + traits::X0) - )); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - } - this->do_sync(POST_SYNC, 76); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 77: LR.W */ - compile_ret_t __lr_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 77); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto REStmp1_val = super::template sext(-(1)); - super::write_mem(traits::RES, offs_val, static_cast(REStmp1_val)); - } - this->do_sync(POST_SYNC, 77); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 78: SC.W */ - compile_ret_t __sc_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 78); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template read_mem(traits::RES, offs_val); - { - if((res1_val != 0)) { - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - } - } - if(rd != 0){ - auto Xtmp1_val = (res1_val != super::template zext(0))? - 0: - 1; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - this->do_sync(POST_SYNC, 78); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 79: AMOSWAP.W */ - compile_ret_t __amoswap_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 79); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto MEMtmp1_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 79); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 80: AMOADD.W */ - compile_ret_t __amoadd_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 80); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val + super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 80); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 81: AMOXOR.W */ - compile_ret_t __amoxor_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 81); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val ^ super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 81); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 82: AMOAND.W */ - compile_ret_t __amoand_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 82); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val & super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 82); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 83: AMOOR.W */ - compile_ret_t __amoor_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 83); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val | super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 83); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 84: AMOMIN.W */ - compile_ret_t __amomin_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 84); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (static_cast(res1_val) > static_cast(super::template get_reg(rs2 + traits::X0)))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 84); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 85: AMOMAX.W */ - compile_ret_t __amomax_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 85); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (static_cast(res1_val) < static_cast(super::template get_reg(rs2 + traits::X0)))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 85); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 86: AMOMINU.W */ - compile_ret_t __amominu_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 86); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val > super::template get_reg(rs2 + traits::X0))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 86); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 87: AMOMAXU.W */ - compile_ret_t __amomaxu_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 87); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val < super::template get_reg(rs2 + traits::X0))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 87); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 88: LR.D */ - compile_ret_t __lr_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 88); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto REStmp1_val = super::template sext(-(1)); - super::write_mem(traits::RES, offs_val, static_cast(REStmp1_val)); - } - this->do_sync(POST_SYNC, 88); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 89: SC.D */ - compile_ret_t __sc_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 89); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res_val = super::template read_mem(traits::RES, offs_val); - { - if((res_val != 0)) { - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val));if(rd != 0){ - auto Xtmp1_val = 0; - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - } - else { - if(rd != 0){ - auto Xtmp2_val = 1; - super::template get_reg(rd + traits::X0)=Xtmp2_val; - } - } - } - this->do_sync(POST_SYNC, 89); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 90: AMOSWAP.D */ - compile_ret_t __amoswap_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 90); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto MEMtmp1_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 90); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 91: AMOADD.D */ - compile_ret_t __amoadd_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 91); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res_val + super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 91); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 92: AMOXOR.D */ - compile_ret_t __amoxor_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 92); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res_val ^ super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 92); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 93: AMOAND.D */ - compile_ret_t __amoand_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 93); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res_val & super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 93); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 94: AMOOR.D */ - compile_ret_t __amoor_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 94); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res_val | super::template get_reg(rs2 + traits::X0)); - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 94); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 95: AMOMIN.D */ - compile_ret_t __amomin_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 95); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (static_cast(res1_val) > static_cast(super::template get_reg(rs2 + traits::X0)))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 95); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 96: AMOMAX.D */ - compile_ret_t __amomax_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 96); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (static_cast(res_val) < static_cast(super::template get_reg(rs2 + traits::X0)))? - super::template get_reg(rs2 + traits::X0): - res_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 96); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 97: AMOMINU.D */ - compile_ret_t __amominu_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 97); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res_val > super::template get_reg(rs2 + traits::X0))? - super::template get_reg(rs2 + traits::X0): - res_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 97); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 98: AMOMAXU.D */ - compile_ret_t __amomaxu_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 98); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = super::template get_reg(rs1 + traits::X0); - auto res1_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - if(rd != 0){ - auto Xtmp0_val = res1_val; - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - auto res2_val = (res1_val < super::template get_reg(rs2 + traits::X0))? - super::template get_reg(rs2 + traits::X0): - res1_val; - auto MEMtmp1_val = res2_val; - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp1_val)); - this->do_sync(POST_SYNC, 98); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 99: FLW */ - compile_ret_t __flw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 99); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}(x{rs1})", fmt::arg("mnemonic", "flw"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 32){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 99); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 100: FSW */ - compile_ret_t __fsw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 100); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}(x{rs1})", fmt::arg("mnemonic", "fsw"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 100); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 101: FMADD.S */ - compile_ret_t __fmadd_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 101); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fmadd_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template get_reg(rs3 + traits::F0), - super::template zext(0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto frs3_val = unbox_s( - super::template get_reg(rs3 + traits::F0) - ); - auto res_val = fmadd_s( - frs1_val, - frs2_val, - frs3_val, - super::template zext(0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 101); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 102: FMSUB.S */ - compile_ret_t __fmsub_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 102); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fmadd_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template get_reg(rs3 + traits::F0), - super::template zext(1), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto frs3_val = unbox_s( - super::template get_reg(rs3 + traits::F0) - ); - auto res_val = fmadd_s( - frs1_val, - frs2_val, - frs3_val, - super::template zext(1), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 102); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 103: FNMADD.S */ - compile_ret_t __fnmadd_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 103); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fmadd_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template get_reg(rs3 + traits::F0), - super::template zext(2), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto frs3_val = unbox_s( - super::template get_reg(rs3 + traits::F0) - ); - auto res_val = fmadd_s( - frs1_val, - frs2_val, - frs3_val, - super::template zext(2), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 103); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 104: FNMSUB.S */ - compile_ret_t __fnmsub_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 104); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fmadd_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template get_reg(rs3 + traits::F0), - super::template zext(3), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto frs3_val = unbox_s( - super::template get_reg(rs3 + traits::F0) - ); - auto res_val = fmadd_s( - frs1_val, - frs2_val, - frs3_val, - super::template zext(3), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 104); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 105: FADD.S */ - compile_ret_t __fadd_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 105); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fadd_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fadd_s( - frs1_val, - frs2_val, - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 105); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 106: FSUB.S */ - compile_ret_t __fsub_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 106); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fsub_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fsub_s( - frs1_val, - frs2_val, - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 106); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 107: FMUL.S */ - compile_ret_t __fmul_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 107); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fmul_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fmul_s( - frs1_val, - frs2_val, - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 107); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 108: FDIV.S */ - compile_ret_t __fdiv_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 108); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fdiv_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fdiv_s( - frs1_val, - frs2_val, - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 108); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 109: FSQRT.S */ - compile_ret_t __fsqrt_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 109); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fsqrt_s( - super::template get_reg(rs1 + traits::F0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto res_val = fsqrt_s( - frs1_val, - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 109); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 110: FSGNJ.S */ - compile_ret_t __fsgnj_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 110); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = ((super::template get_reg(rs1 + traits::F0) & 0x7fffffff) | (super::template get_reg(rs2 + traits::F0) & 0x80000000)); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = ((frs1_val & 0x7fffffff) | (frs2_val & 0x80000000)); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 110); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 111: FSGNJN.S */ - compile_ret_t __fsgnjn_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 111); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = ((super::template get_reg(rs1 + traits::F0) & 0x7fffffff) | (~(super::template get_reg(rs2 + traits::F0)) & 0x80000000)); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = ((frs1_val & 0x7fffffff) | (~(frs2_val) & 0x80000000)); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 111); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 112: FSGNJX.S */ - compile_ret_t __fsgnjx_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 112); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = (super::template get_reg(rs1 + traits::F0) ^ (super::template get_reg(rs2 + traits::F0) & 0x80000000)); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = (frs1_val ^ (frs2_val & 0x80000000)); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 112); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 113: FMIN.S */ - compile_ret_t __fmin_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 113); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fsel_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template zext(0) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fsel_s( - frs1_val, - frs2_val, - super::template zext(0) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 113); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 114: FMAX.S */ - compile_ret_t __fmax_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 114); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fsel_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template zext(1) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto res_val = fsel_s( - frs1_val, - frs2_val, - super::template zext(1) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 114); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 115: FCVT.W.S */ - compile_ret_t __fcvt_w_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 115); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Xtmp0_val = super::template sext(fcvt_s( - super::template get_reg(rs1 + traits::F0), - super::template zext(0), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto Xtmp1_val = super::template sext(fcvt_s( - frs1_val, - super::template zext(0), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 115); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 116: FCVT.WU.S */ - compile_ret_t __fcvt_wu_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 116); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Xtmp0_val = super::template sext(fcvt_s( - super::template get_reg(rs1 + traits::F0), - super::template zext(1), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto Xtmp1_val = super::template sext(fcvt_s( - frs1_val, - super::template zext(1), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 116); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 117: FEQ.S */ - compile_ret_t __feq_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 117); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Xtmp0_val = super::template zext(fcmp_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template zext(0) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto Xtmp1_val = super::template zext(fcmp_s( - frs1_val, - frs2_val, - super::template zext(0) - )); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 117); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 118: FLT.S */ - compile_ret_t __flt_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 118); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Xtmp0_val = super::template zext(fcmp_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template zext(2) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto Xtmp1_val = super::template zext(fcmp_s( - frs1_val, - frs2_val, - super::template zext(2) - )); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - auto Xtmp2_val = fcmp_s( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(2) - ); - super::template get_reg(rd + traits::X0)=Xtmp2_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 118); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 119: FLE.S */ - compile_ret_t __fle_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 119); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Xtmp0_val = super::template zext(fcmp_s( - super::template get_reg(rs1 + traits::F0), - super::template get_reg(rs2 + traits::F0), - super::template zext(1) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } else { - auto frs1_val = unbox_s( - super::template get_reg(rs1 + traits::F0) - ); - auto frs2_val = unbox_s( - super::template get_reg(rs2 + traits::F0) - ); - auto Xtmp1_val = super::template zext(fcmp_s( - frs1_val, - frs2_val, - super::template zext(1) - )); - super::template get_reg(rd + traits::X0)=Xtmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 119); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 120: FCLASS.S */ - compile_ret_t __fclass_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 120); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = fclass_s( - unbox_s( - super::template get_reg(rs1 + traits::F0) - ) - ); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 120); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 121: FCVT.S.W */ - compile_ret_t __fcvt_s_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 121); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fcvt_s( - static_cast( - super::template get_reg(rs1 + traits::X0) - ), - super::template zext(2), - (rm) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto res_val = fcvt_s( - static_cast( - super::template get_reg(rs1 + traits::X0) - ), - super::template zext(2), - (rm) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 121); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 122: FCVT.S.WU */ - compile_ret_t __fcvt_s_wu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 122); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = fcvt_s( - static_cast( - super::template get_reg(rs1 + traits::X0) - ), - super::template zext(3), - (rm) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - auto res_val = fcvt_s( - static_cast( - super::template get_reg(rs1 + traits::X0) - ), - super::template zext(3), - (rm) - ); - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 122); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 123: FMV.X.W */ - compile_ret_t __fmv_x_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 123); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fmv.x.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template sext(static_cast( - super::template get_reg(rs1 + traits::F0) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 123); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 124: FMV.W.X */ - compile_ret_t __fmv_w_x(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 124); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fmv.w.x"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(64 == 32){ - auto Ftmp0_val = static_cast( - super::template get_reg(rs1 + traits::X0) - ); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(static_cast( - super::template get_reg(rs1 + traits::X0) - ))); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 124); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 125: FCVT.L.S */ - compile_ret_t __fcvt_l_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 125); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.l.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fcvt_32_64( - unbox_s( - super::template get_reg(rs1 + traits::F0) - ), - super::template zext(0), - (rm) - ); - auto Xtmp0_val = super::template sext(res_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 125); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 126: FCVT.LU.S */ - compile_ret_t __fcvt_lu_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 126); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.lu.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fcvt_32_64( - unbox_s( - super::template get_reg(rs1 + traits::F0) - ), - super::template zext(1), - (rm) - ); - auto Xtmp0_val = super::template zext(res_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 126); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 127: FCVT.S.L */ - compile_ret_t __fcvt_s_l(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 127); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, x{rs1}", fmt::arg("mnemonic", "fcvt.s.l"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fcvt_64_32( - super::template get_reg(rs1 + traits::X0), - super::template zext(2), - (rm) - ); - if(64 == 32){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 127); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 128: FCVT.S.LU */ - compile_ret_t __fcvt_s_lu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 128); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, x{rs1}", fmt::arg("mnemonic", "fcvt.s.lu"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fcvt_64_32( - super::template get_reg(rs1 + traits::X0), - super::template zext(3), - (rm) - ); - if(64 == 32){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 128); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 129: FLD */ - compile_ret_t __fld(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 129); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}({rs1})", fmt::arg("mnemonic", "fld"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 129); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 130: FSD */ - compile_ret_t __fsd(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 130); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}({rs1})", fmt::arg("mnemonic", "fsd"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 130); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 131: FMADD.D */ - compile_ret_t __fmadd_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 131); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fmadd_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - static_cast( - super::template get_reg(rs3 + traits::F0) - ), - super::template zext(0), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 131); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 132: FMSUB.D */ - compile_ret_t __fmsub_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 132); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fmadd_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - static_cast( - super::template get_reg(rs3 + traits::F0) - ), - super::template zext(1), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 132); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 133: FNMADD.D */ - compile_ret_t __fnmadd_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 133); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fmadd_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - static_cast( - super::template get_reg(rs3 + traits::F0) - ), - super::template zext(2), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 133); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 134: FNMSUB.D */ - compile_ret_t __fnmsub_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 134); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fmadd_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - static_cast( - super::template get_reg(rs3 + traits::F0) - ), - super::template zext(3), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 134); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 135: FADD.D */ - compile_ret_t __fadd_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 135); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fadd_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 135); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 136: FSUB.D */ - compile_ret_t __fsub_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 136); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fsub_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 136); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 137: FMUL.D */ - compile_ret_t __fmul_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 137); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fmul_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 137); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 138: FDIV.D */ - compile_ret_t __fdiv_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 138); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fdiv_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 138); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 139: FSQRT.D */ - compile_ret_t __fsqrt_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 139); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fsqrt_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - ((rm) < 7)? - (rm): - static_cast( - super::template get_reg(traits::FCSR) - ) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 139); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 140: FSGNJ.D */ - compile_ret_t __fsgnj_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 140); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - auto res_val = ((static_cast( - super::template get_reg(rs1 + traits::F0) - ) & MSK2_val) | (static_cast( - super::template get_reg(rs2 + traits::F0) - ) & MSK1_val)); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 140); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 141: FSGNJN.D */ - compile_ret_t __fsgnjn_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 141); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - auto res_val = ((static_cast( - super::template get_reg(rs1 + traits::F0) - ) & MSK2_val) | (~(static_cast( - super::template get_reg(rs2 + traits::F0) - )) & MSK1_val)); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 141); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 142: FSGNJX.D */ - compile_ret_t __fsgnjx_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 142); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - auto res_val = (static_cast( - super::template get_reg(rs1 + traits::F0) - ) ^ (static_cast( - super::template get_reg(rs2 + traits::F0) - ) & MSK1_val)); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 142); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 143: FMIN.D */ - compile_ret_t __fmin_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 143); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fsel_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(0) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 143); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 144: FMAX.D */ - compile_ret_t __fmax_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 144); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fsel_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(1) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 144); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 145: FCVT.S.D */ - compile_ret_t __fcvt_s_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 145); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.s.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fconv_d2f( - super::template get_reg(rs1 + traits::F0), - (rm) - ); - uint64_t upper_val = - 1; - auto Ftmp0_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - this->do_sync(POST_SYNC, 145); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 146: FCVT.D.S */ - compile_ret_t __fcvt_d_s(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 146); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.d.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fconv_f2d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - (rm) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 146); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 147: FEQ.D */ - compile_ret_t __feq_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 147); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template zext(fcmp_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(0) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 147); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 148: FLT.D */ - compile_ret_t __flt_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 148); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template zext(fcmp_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(2) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 148); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 149: FLE.D */ - compile_ret_t __fle_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 149); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template zext(fcmp_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - static_cast( - super::template get_reg(rs2 + traits::F0) - ), - super::template zext(1) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 149); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 150: FCLASS.D */ - compile_ret_t __fclass_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 150); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = fclass_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ) - ); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 150); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 151: FCVT.W.D */ - compile_ret_t __fcvt_w_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 151); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template sext(fcvt_64_32( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - super::template zext(0), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 151); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 152: FCVT.WU.D */ - compile_ret_t __fcvt_wu_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 152); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template sext(fcvt_64_32( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - super::template zext(1), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 152); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 153: FCVT.D.W */ - compile_ret_t __fcvt_d_w(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 153); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fcvt_32_64( - super::template sext(static_cast( - super::template get_reg(rs1 + traits::X0) - )), - super::template zext(2), - (rm) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 153); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 154: FCVT.D.WU */ - compile_ret_t __fcvt_d_wu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 154); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fcvt_32_64( - super::template zext(static_cast( - super::template get_reg(rs1 + traits::X0) - )), - super::template zext(3), - (rm) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 154); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 155: FCVT.L.D */ - compile_ret_t __fcvt_l_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 155); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.l.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template sext(fcvt_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - super::template zext(0), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 155); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 156: FCVT.LU.D */ - compile_ret_t __fcvt_lu_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 156); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.lu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template sext(fcvt_d( - static_cast( - super::template get_reg(rs1 + traits::F0) - ), - super::template zext(1), - (rm) - )); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - auto flags_val = fget_flags( - ); - auto FCSR_val = ((super::template get_reg(traits::FCSR) & ~((0x1f))) + flags_val); - super::template get_reg(traits::FCSR) = FCSR_val; - this->do_sync(POST_SYNC, 156); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 157: FCVT.D.L */ - compile_ret_t __fcvt_d_l(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 157); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.l"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fcvt_d( - super::template sext(super::template get_reg(rs1 + traits::X0)), - super::template zext(2), - (rm) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 157); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 158: FCVT.D.LU */ - compile_ret_t __fcvt_d_lu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 158); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.lu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = fcvt_d( - super::template zext(super::template get_reg(rs1 + traits::X0)), - super::template zext(3), - (rm) - ); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 158); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 159: FMV.X.D */ - compile_ret_t __fmv_x_d(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 159); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fmv.x.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Xtmp0_val = super::template sext(super::template get_reg(rs1 + traits::F0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 159); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 160: FMV.D.X */ - compile_ret_t __fmv_d_x(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 160); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fmv.d.x"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto Ftmp0_val = super::template zext(super::template get_reg(rs1 + traits::X0)); - super::template get_reg(rd + traits::F0)=Ftmp0_val; - this->do_sync(POST_SYNC, 160); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 161: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 161); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(imm == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (super::template get_reg(2 + traits::X0) + (imm)); - super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 161); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 162: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 162); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 162); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 163: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 163); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto MEMtmp0_val = super::template get_reg(rs2 + 8 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 163); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 164: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 164); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - super::template get_reg(rs1 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 164); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 165: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 165); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "c.nop"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - /* TODO: describe operations for C.NOP ! */ - this->do_sync(POST_SYNC, 165); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 166: C.JAL */ - compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 166); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (cur_pc_val + 2); - super::template get_reg(1 + traits::X0)=Xtmp0_val; - auto PC_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 166); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 167: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 167); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(rd == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (imm); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 167); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 168: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 168); - - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(rd == 0){ - raise_trap(0, 2); - } - if(imm == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (imm); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 168); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 169: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 169); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (static_cast(super::template get_reg(2 + traits::X0)) + (imm)); - super::template get_reg(2 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 169); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 170: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 170); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rs1_idx_val = rs1 + 8; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0))>>(shamt)); - super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 170); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 171: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 171); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rs1_idx_val = rs1 + 8; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0))>>(shamt)); - super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 171); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 172: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 172); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rs1_idx_val = rs1 + 8; - auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0)) & (imm)); - super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 172); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 173: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 173); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) - super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 173); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 174: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 174); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) ^ super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 174); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 175: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 175); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) | super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 175); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 176: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 176); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - uint8_t rd_idx_val = rd + 8; - auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) & super::template get_reg(rs2 + 8 + traits::X0)); - super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 176); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 177: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 177); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = (static_cast(cur_pc_val) + (imm)); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 177); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 178: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 178); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = (super::template get_reg(rs1 + 8 + traits::X0) == 0)? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 2); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 178); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 179: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 179); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = (super::template get_reg(rs1 + 8 + traits::X0) != 0)? - (static_cast(cur_pc_val) + (imm)): - (cur_pc_val + 2); - super::template get_reg(traits::NEXT_PC) = PC_val; - auto is_cont_v = PC_val !=pc.val; - super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 179); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 180: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 180); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(rs1 == 0){ - raise_trap(0, 2); - } - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); - super::template get_reg(rs1 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 180); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 181: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 181); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 181); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 182: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 182); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = super::template get_reg(rs2 + traits::X0); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 182); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 183: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 183); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto PC_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(traits::NEXT_PC) = PC_val; - super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - this->do_sync(POST_SYNC, 183); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 184: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 184); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (super::template get_reg(rd + traits::X0) + super::template get_reg(rs2 + traits::X0)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 184); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 185: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 185); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto Xtmp0_val = (cur_pc_val + 2); - super::template get_reg(1 + traits::X0)=Xtmp0_val; - auto PC_val = super::template get_reg(rs1 + traits::X0); - super::template get_reg(traits::NEXT_PC) = PC_val; - super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - this->do_sync(POST_SYNC, 185); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 186: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 186); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "c.ebreak"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - raise_trap(0, 3); - this->do_sync(POST_SYNC, 186); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 187: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 187); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 187); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 188: DII */ - compile_ret_t __dii(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 188); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "dii"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - raise_trap(0, 2); - this->do_sync(POST_SYNC, 188); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 189: C.LD */ - compile_ret_t __c_ld(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 189); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm},({rs1})", fmt::arg("mnemonic", "c.ld"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 189); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 190: C.SD */ - compile_ret_t __c_sd(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 190); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm},({rs1})", fmt::arg("mnemonic", "c.sd"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto MEMtmp0_val = super::template get_reg(rs2 + 8 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 190); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 191: C.SUBW */ - compile_ret_t __c_subw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 191); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto res_val = (static_cast( - super::template get_reg(rd + 8 + traits::X0) - ) - static_cast( - super::template get_reg(rs2 + 8 + traits::X0) - )); - auto Xtmp0_val = super::template sext(res_val); - super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 191); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 192: C.ADDW */ - compile_ret_t __c_addw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 192); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto res_val = (static_cast( - super::template get_reg(rd + 8 + traits::X0) - ) + static_cast( - super::template get_reg(rs2 + 8 + traits::X0) - )); - auto Xtmp0_val = super::template sext(res_val); - super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 192); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 193: C.ADDIW */ - compile_ret_t __c_addiw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 193); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addiw"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - if(rs1 != 0){ - auto res_val = (static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - )) + (imm)); - auto Xtmp0_val = super::template sext(res_val); - super::template get_reg(rs1 + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 193); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 194: C.LDSP */ - compile_ret_t __c_ldsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 194); - - uint16_t uimm = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm}(sp)", fmt::arg("mnemonic", "c.ldsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 194); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 195: C.SDSP */ - compile_ret_t __c_sdsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 195); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint16_t uimm = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm}(sp)", fmt::arg("mnemonic", "c.sdsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 195); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 196: C.FLW */ - compile_ret_t __c_flw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 196); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rd}), {uimm}({rs1})", fmt::arg("mnemonic", "c.flw"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 32){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + 8 + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + 8 + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 196); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 197: C.FSW */ - compile_ret_t __c_fsw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 197); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rs2}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fsw"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + 8 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 197); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 198: C.FLWSP */ - compile_ret_t __c_flwsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 198); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {uimm}(x2)", fmt::arg("mnemonic", "c.flwsp"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 32){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 32) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 198); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 199: C.FSWSP */ - compile_ret_t __c_fswsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 199); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {uimm}(x2), ", fmt::arg("mnemonic", "c.fswsp"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 199); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 200: C.FLD */ - compile_ret_t __c_fld(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 200); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rd}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fld"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + 8 + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | res_val); - super::template get_reg(rd + 8 + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 200); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 201: C.FSD */ - compile_ret_t __c_fsd(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 201); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rs2}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fsd"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + 8 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 201); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 202: C.FLDSP */ - compile_ret_t __c_fldsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 202); - - uint16_t uimm = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {uimm}(x2)", fmt::arg("mnemonic", "c.fldsp"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto res_val = super::template read_mem(traits::MEM, offs_val); - if(64 == 64){ - auto Ftmp0_val = res_val; - super::template get_reg(rd + traits::F0)=Ftmp0_val; - } else { - uint64_t upper_val = - 1; - auto Ftmp1_val = ((upper_val << 64) | super::template zext(res_val)); - super::template get_reg(rd + traits::F0)=Ftmp1_val; - } - this->do_sync(POST_SYNC, 202); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 203: C.FSDSP */ - compile_ret_t __c_fsdsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 203); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint16_t uimm = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {uimm}(x2), ", fmt::arg("mnemonic", "c.fsdsp"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; - auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); - auto MEMtmp0_val = static_cast( - super::template get_reg(rs2 + traits::F0) - ); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 203); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /**************************************************************************** - * 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){ - 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::rv64gc *core, unsigned short port, bool dump) { - auto ret = new rv64gc::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} // namespace interp -} // namespace iss diff --git a/src/vm/interp/vm_rv64i.cpp b/src/vm/interp/vm_tgf01.cpp similarity index 78% rename from src/vm/interp/vm_rv64i.cpp rename to src/vm/interp/vm_tgf01.cpp index 3a65771..9e13b96 100644 --- a/src/vm/interp/vm_rv64i.cpp +++ b/src/vm/interp/vm_tgf01.cpp @@ -31,8 +31,8 @@ *******************************************************************************/ #include "../fp_functions.h" -#include -#include +#include +#include #include #include #include @@ -50,7 +50,7 @@ namespace iss { namespace interp { -namespace rv64i { +namespace tgf01 { using namespace iss::arch; using namespace iss::debugger; @@ -167,7 +167,7 @@ private: compile_func op; }; - const std::array instr_descr = {{ + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, @@ -218,11 +218,11 @@ private: /* instruction ANDI */ {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, /* instruction SLLI */ - {32, 0b00000000000000000001000000010011, 0b11111100000000000111000001111111, &this_class::__slli}, + {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srli}, + {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srai}, + {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, /* instruction ADD */ {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, /* instruction SUB */ @@ -273,30 +273,6 @@ private: {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, /* instruction CSRRCI */ {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction LWU */ - {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, - /* instruction LD */ - {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, &this_class::__ld}, - /* instruction SD */ - {32, 0b00000000000000000011000000100011, 0b00000000000000000111000001111111, &this_class::__sd}, - /* instruction ADDIW */ - {32, 0b00000000000000000000000000011011, 0b00000000000000000111000001111111, &this_class::__addiw}, - /* instruction SLLIW */ - {32, 0b00000000000000000001000000011011, 0b11111110000000000111000001111111, &this_class::__slliw}, - /* instruction SRLIW */ - {32, 0b00000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__srliw}, - /* instruction SRAIW */ - {32, 0b01000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__sraiw}, - /* instruction ADDW */ - {32, 0b00000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__addw}, - /* instruction SUBW */ - {32, 0b01000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__subw}, - /* instruction SLLW */ - {32, 0b00000000000000000001000000111011, 0b11111110000000000111000001111111, &this_class::__sllw}, - /* instruction SRLW */ - {32, 0b00000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__srlw}, - /* instruction SRAW */ - {32, 0b01000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__sraw}, }}; /* instruction definitions */ @@ -349,7 +325,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = (static_cast(cur_pc_val) + (imm)); + auto Xtmp0_val = (static_cast(cur_pc_val) + (imm)); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 1); @@ -384,7 +360,7 @@ private: auto Xtmp0_val = (cur_pc_val + 4); super::template get_reg(rd + traits::X0)=Xtmp0_val; } - auto PC_val = (static_cast(cur_pc_val) + (imm)); + auto PC_val = (static_cast(cur_pc_val) + (imm)); super::template get_reg(traits::NEXT_PC) = PC_val; auto is_cont_v = PC_val !=pc.val; super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; @@ -417,7 +393,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto new_pc_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto new_pc_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); auto align_val = (new_pc_val & 0x2); { if((align_val != 0)) { @@ -463,7 +439,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; auto PC_val = (super::template get_reg(rs1 + traits::X0) == super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): + (static_cast(cur_pc_val) + (imm)): (cur_pc_val + 4); super::template get_reg(traits::NEXT_PC) = PC_val; auto is_cont_v = PC_val !=pc.val; @@ -498,7 +474,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; auto PC_val = (super::template get_reg(rs1 + traits::X0) != super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): + (static_cast(cur_pc_val) + (imm)): (cur_pc_val + 4); super::template get_reg(traits::NEXT_PC) = PC_val; auto is_cont_v = PC_val !=pc.val; @@ -532,8 +508,8 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? - (static_cast(cur_pc_val) + (imm)): + auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? + (static_cast(cur_pc_val) + (imm)): (cur_pc_val + 4); super::template get_reg(traits::NEXT_PC) = PC_val; auto is_cont_v = PC_val !=pc.val; @@ -567,8 +543,8 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) >= static_cast(super::template get_reg(rs2 + traits::X0)))? - (static_cast(cur_pc_val) + (imm)): + auto PC_val = (static_cast(super::template get_reg(rs1 + traits::X0)) >= static_cast(super::template get_reg(rs2 + traits::X0)))? + (static_cast(cur_pc_val) + (imm)): (cur_pc_val + 4); super::template get_reg(traits::NEXT_PC) = PC_val; auto is_cont_v = PC_val !=pc.val; @@ -603,7 +579,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; auto PC_val = (super::template get_reg(rs1 + traits::X0) < super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): + (static_cast(cur_pc_val) + (imm)): (cur_pc_val + 4); super::template get_reg(traits::NEXT_PC) = PC_val; auto is_cont_v = PC_val !=pc.val; @@ -638,7 +614,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; auto PC_val = (super::template get_reg(rs1 + traits::X0) >= super::template get_reg(rs2 + traits::X0))? - (static_cast(cur_pc_val) + (imm)): + (static_cast(cur_pc_val) + (imm)): (cur_pc_val + 4); super::template get_reg(traits::NEXT_PC) = PC_val; auto is_cont_v = PC_val !=pc.val; @@ -672,9 +648,9 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); + auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 10); @@ -706,9 +682,9 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); + auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 11); @@ -740,9 +716,9 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); + auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 12); @@ -774,9 +750,9 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); + auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 13); @@ -808,9 +784,9 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); + auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 14); @@ -842,7 +818,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); this->do_sync(POST_SYNC, 15); @@ -874,7 +850,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); this->do_sync(POST_SYNC, 16); @@ -906,7 +882,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); this->do_sync(POST_SYNC, 17); @@ -939,7 +915,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 18); @@ -972,7 +948,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < (imm))? + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < (imm))? 1: 0; super::template get_reg(rd + traits::X0)=Xtmp0_val; @@ -1006,7 +982,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - int64_t full_imm_val = imm; + int32_t full_imm_val = imm; if(rd != 0){ auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) < full_imm_val)? 1: @@ -1043,7 +1019,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) ^ (imm)); + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) ^ (imm)); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 21); @@ -1076,7 +1052,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) | (imm)); + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) | (imm)); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 22); @@ -1109,7 +1085,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) & (imm)); + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) & (imm)); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 23); @@ -1130,7 +1106,7 @@ private: uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,6>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( @@ -1141,9 +1117,13 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; + if(shamt > 31){ + raise_trap(0, 0); + } else { + if(rd != 0){ + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } } this->do_sync(POST_SYNC, 24); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); @@ -1163,7 +1143,7 @@ private: uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,6>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( @@ -1174,9 +1154,13 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; + if(shamt > 31){ + raise_trap(0, 0); + } else { + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } } this->do_sync(POST_SYNC, 25); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); @@ -1196,7 +1180,7 @@ private: uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,6>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( @@ -1207,9 +1191,13 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; + if(shamt > 31){ + raise_trap(0, 0); + } else { + if(rd != 0){ + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(shamt)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } } this->do_sync(POST_SYNC, 26); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); @@ -1307,7 +1295,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(super::template get_reg(rs2 + traits::X0) & ((64) - 1))); + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 29); @@ -1340,7 +1328,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) < static_cast(super::template get_reg(rs2 + traits::X0)))? 1: 0; super::template get_reg(rd + traits::X0)=Xtmp0_val; @@ -1375,7 +1363,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) < super::template zext(super::template get_reg(rs2 + traits::X0)))? + auto Xtmp0_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) < super::template zext(super::template get_reg(rs2 + traits::X0)))? 1: 0; super::template get_reg(rd + traits::X0)=Xtmp0_val; @@ -1443,7 +1431,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((64) - 1))); + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 33); @@ -1476,7 +1464,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((64) - 1))); + auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0))>>(super::template get_reg(rs2 + traits::X0) & ((32) - 1))); super::template get_reg(rd + traits::X0)=Xtmp0_val; } this->do_sync(POST_SYNC, 34); @@ -1573,7 +1561,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; auto FENCEtmp0_val = (((pred) << 4) | (succ)); - super::write_mem(traits::FENCE, (0), static_cast(FENCEtmp0_val)); + super::write_mem(traits::FENCE, (0), static_cast(FENCEtmp0_val)); this->do_sync(POST_SYNC, 37); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check @@ -1601,7 +1589,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; auto FENCEtmp0_val = (imm); - super::write_mem(traits::FENCE, (1), static_cast(FENCEtmp0_val)); + super::write_mem(traits::FENCE, (1), static_cast(FENCEtmp0_val)); this->do_sync(POST_SYNC, 38); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check @@ -1772,9 +1760,9 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; auto FENCEtmp0_val = (rs1); - super::write_mem(traits::FENCE, (2), static_cast(FENCEtmp0_val)); + super::write_mem(traits::FENCE, (2), static_cast(FENCEtmp0_val)); auto FENCEtmp1_val = (rs2); - super::write_mem(traits::FENCE, (3), static_cast(FENCEtmp1_val)); + super::write_mem(traits::FENCE, (3), static_cast(FENCEtmp1_val)); this->do_sync(POST_SYNC, 45); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check @@ -1806,14 +1794,14 @@ private: super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; auto rs_val_val = super::template get_reg(rs1 + traits::X0); if(rd != 0){ - auto csr_val_val = super::template read_mem(traits::CSR, (csr)); + auto csr_val_val = super::template read_mem(traits::CSR, (csr)); auto CSRtmp0_val = rs_val_val; - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); auto Xtmp1_val = csr_val_val; super::template get_reg(rd + traits::X0)=Xtmp1_val; } else { auto CSRtmp2_val = rs_val_val; - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp2_val)); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp2_val)); } this->do_sync(POST_SYNC, 46); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); @@ -1844,7 +1832,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto xrd_val = super::template read_mem(traits::CSR, (csr)); + auto xrd_val = super::template read_mem(traits::CSR, (csr)); auto xrs1_val = super::template get_reg(rs1 + traits::X0); if(rd != 0){ auto Xtmp0_val = xrd_val; @@ -1852,7 +1840,7 @@ private: } if(rs1 != 0){ auto CSRtmp1_val = (xrd_val | xrs1_val); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); } this->do_sync(POST_SYNC, 47); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); @@ -1883,7 +1871,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto xrd_val = super::template read_mem(traits::CSR, (csr)); + auto xrd_val = super::template read_mem(traits::CSR, (csr)); auto xrs1_val = super::template get_reg(rs1 + traits::X0); if(rd != 0){ auto Xtmp0_val = xrd_val; @@ -1891,7 +1879,7 @@ private: } if(rs1 != 0){ auto CSRtmp1_val = (xrd_val & ~(xrs1_val)); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); } this->do_sync(POST_SYNC, 48); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); @@ -1923,11 +1911,11 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; if(rd != 0){ - auto Xtmp0_val = super::template read_mem(traits::CSR, (csr)); + auto Xtmp0_val = super::template read_mem(traits::CSR, (csr)); super::template get_reg(rd + traits::X0)=Xtmp0_val; } - auto CSRtmp1_val = super::template zext((zimm)); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); + auto CSRtmp1_val = super::template zext((zimm)); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); this->do_sync(POST_SYNC, 49); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check @@ -1957,10 +1945,10 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = super::template read_mem(traits::CSR, (csr)); + auto res_val = super::template read_mem(traits::CSR, (csr)); if(zimm != 0){ - auto CSRtmp0_val = (res_val | super::template zext((zimm))); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); + auto CSRtmp0_val = (res_val | super::template zext((zimm))); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp0_val)); } if(rd != 0){ auto Xtmp1_val = res_val; @@ -1995,14 +1983,14 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto res_val = super::template read_mem(traits::CSR, (csr)); + auto res_val = super::template read_mem(traits::CSR, (csr)); if(rd != 0){ auto Xtmp0_val = res_val; super::template get_reg(rd + traits::X0)=Xtmp0_val; } if(zimm != 0){ - auto CSRtmp1_val = (res_val & ~(super::template zext((zimm)))); - super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); + auto CSRtmp1_val = (res_val & ~(super::template zext((zimm)))); + super::write_mem(traits::CSR, (csr), static_cast(CSRtmp1_val)); } this->do_sync(POST_SYNC, 51); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); @@ -2016,440 +2004,6 @@ private: return pc; } - /* instruction 52: LWU */ - compile_ret_t __lwu(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 52); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lwu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template zext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 52); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 53: LD */ - compile_ret_t __ld(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 53); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "ld"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - if(rd != 0){ - auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 53); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 54: SD */ - compile_ret_t __sd(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 54); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sd"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - auto offs_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); - auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); - super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 54); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 55: ADDIW */ - compile_ret_t __addiw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 55); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - )) + (imm)); - auto Xtmp0_val = super::template sext(res_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 55); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 56: SLLIW */ - compile_ret_t __slliw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 56); - - 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", "slliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto sh_val_val = (static_cast( - super::template get_reg(rs1 + traits::X0) - )<<(shamt)); - auto Xtmp0_val = super::template sext(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 56); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 57: SRLIW */ - compile_ret_t __srliw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 57); - - 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", "srliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto sh_val_val = (static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - ))>>(shamt)); - auto Xtmp0_val = super::template sext(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 57); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 58: SRAIW */ - compile_ret_t __sraiw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 58); - - 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", "sraiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto sh_val_val = (static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - ))>>(shamt)); - auto Xtmp0_val = super::template sext(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 58); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 59: ADDW */ - compile_ret_t __addw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 59); - - 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 */ - this->core.disass_output(pc.val, "addw"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (static_cast( - super::template get_reg(rs1 + traits::X0) - ) + static_cast( - super::template get_reg(rs2 + traits::X0) - )); - auto Xtmp0_val = super::template sext(res_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 59); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 60: SUBW */ - compile_ret_t __subw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 60); - - 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 */ - this->core.disass_output(pc.val, "subw"); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - auto res_val = (static_cast( - super::template get_reg(rs1 + traits::X0) - ) - static_cast( - super::template get_reg(rs2 + traits::X0) - )); - auto Xtmp0_val = super::template sext(res_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 60); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 61: SLLW */ - compile_ret_t __sllw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 61); - - 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", "sllw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = (static_cast( - super::template get_reg(rs2 + traits::X0) - ) & mask_val); - auto sh_val_val = (static_cast( - super::template get_reg(rs1 + traits::X0) - )<(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 61); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 62: SRLW */ - compile_ret_t __srlw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 62); - - 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", "srlw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = (static_cast( - super::template get_reg(rs2 + traits::X0) - ) & mask_val); - auto sh_val_val = (static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - ))>>count_val); - auto Xtmp0_val = super::template sext(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 62); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - - /* instruction 63: SRAW */ - compile_ret_t __sraw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 63); - - 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", "sraw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - - auto cur_pc_val = pc.val; - super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = (static_cast( - super::template get_reg(rs2 + traits::X0) - ) & mask_val); - auto sh_val_val = (static_cast(static_cast( - super::template get_reg(rs1 + traits::X0) - ))>>count_val); - auto Xtmp0_val = super::template sext(sh_val_val); - super::template get_reg(rd + traits::X0)=Xtmp0_val; - } - this->do_sync(POST_SYNC, 63); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); - last_br = std::numeric_limits::max(); - super::core.enter_trap(trap_state, cur_pc_val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - /**************************************************************************** * end opcode definitions ****************************************************************************/ @@ -2509,8 +2063,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t star } // namespace mnrv32 template <> -std::unique_ptr create(arch::rv64i *core, unsigned short port, bool dump) { - auto ret = new rv64i::vm_impl(*core, dump); +std::unique_ptr create(arch::tgf01 *core, unsigned short port, bool dump) { + auto ret = new tgf01::vm_impl(*core, dump); if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } diff --git a/src/vm/interp/vm_mnrv32.cpp b/src/vm/interp/vm_tgf02.cpp similarity index 88% rename from src/vm/interp/vm_mnrv32.cpp rename to src/vm/interp/vm_tgf02.cpp index f37e6eb..208a1be 100644 --- a/src/vm/interp/vm_mnrv32.cpp +++ b/src/vm/interp/vm_tgf02.cpp @@ -31,8 +31,8 @@ *******************************************************************************/ #include "../fp_functions.h" -#include -#include +#include +#include #include #include #include @@ -50,7 +50,7 @@ namespace iss { namespace interp { -namespace mnrv32 { +namespace tgf02 { using namespace iss::arch; using namespace iss::debugger; @@ -167,7 +167,7 @@ private: compile_func op; }; - const std::array instr_descr = {{ + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, @@ -273,6 +273,22 @@ private: {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, /* instruction CSRRCI */ {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, + /* instruction MUL */ + {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, + /* instruction MULH */ + {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, + /* instruction MULHSU */ + {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, + /* instruction MULHU */ + {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, + /* instruction DIV */ + {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, + /* instruction DIVU */ + {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, + /* instruction REM */ + {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, + /* instruction REMU */ + {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, /* instruction C.ADDI4SPN */ {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, /* instruction C.LW */ @@ -2052,10 +2068,334 @@ private: return pc; } - /* instruction 52: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr){ + /* instruction 52: MUL */ + compile_ret_t __mul(virt_addr_t& pc, code_word_t instr){ this->do_sync(PRE_SYNC, 52); + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto res_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); + auto Xtmp0_val = super::template zext(res_val); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 52); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 53: MULH */ + compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 53); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto res_val = (super::template sext(super::template get_reg(rs1 + traits::X0)) * super::template sext(super::template get_reg(rs2 + traits::X0))); + auto Xtmp0_val = super::template zext((res_val >> (32))); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 53); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 54: MULHSU */ + compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 54); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto res_val = (super::template sext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); + auto Xtmp0_val = super::template zext((res_val >> (32))); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 54); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 55: MULHU */ + compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 55); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + auto res_val = (super::template zext(super::template get_reg(rs1 + traits::X0)) * super::template zext(super::template get_reg(rs2 + traits::X0))); + auto Xtmp0_val = super::template zext((res_val >> (32))); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + this->do_sync(POST_SYNC, 55); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 56: DIV */ + compile_ret_t __div(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 56); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + { + if((super::template get_reg(rs2 + traits::X0) != 0)) { + uint32_t M1_val = - 1; + uint8_t XLM1_val = 32 - 1; + uint32_t ONE_val = 1; + uint32_t MMIN_val = ONE_val << XLM1_val; + { + if(((super::template get_reg(rs1 + traits::X0) == MMIN_val) && (super::template get_reg(rs2 + traits::X0) == M1_val))) { + auto Xtmp0_val = MMIN_val; + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + else { + auto Xtmp1_val = (static_cast(super::template get_reg(rs1 + traits::X0)) / static_cast(super::template get_reg(rs2 + traits::X0))); + super::template get_reg(rd + traits::X0)=Xtmp1_val; + } + } + } + else { + auto Xtmp2_val = -(1); + super::template get_reg(rd + traits::X0)=Xtmp2_val; + } + } + } + this->do_sync(POST_SYNC, 56); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 57: DIVU */ + compile_ret_t __divu(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 57); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + { + if((super::template get_reg(rs2 + traits::X0) != 0)) { + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) / super::template get_reg(rs2 + traits::X0)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + else { + auto Xtmp1_val = -(1); + super::template get_reg(rd + traits::X0)=Xtmp1_val; + } + } + } + this->do_sync(POST_SYNC, 57); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 58: REM */ + compile_ret_t __rem(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 58); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + { + if((super::template get_reg(rs2 + traits::X0) != 0)) { + uint32_t M1_val = - 1; + uint32_t XLM1_val = 32 - 1; + uint32_t ONE_val = 1; + uint32_t MMIN_val = ONE_val << XLM1_val; + { + if(((super::template get_reg(rs1 + traits::X0) == MMIN_val) && (super::template get_reg(rs2 + traits::X0) == M1_val))) { + auto Xtmp0_val = 0; + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + else { + auto Xtmp1_val = (static_cast(super::template get_reg(rs1 + traits::X0)) % static_cast(super::template get_reg(rs2 + traits::X0))); + super::template get_reg(rd + traits::X0)=Xtmp1_val; + } + } + } + else { + auto Xtmp2_val = super::template get_reg(rs1 + traits::X0); + super::template get_reg(rd + traits::X0)=Xtmp2_val; + } + } + } + this->do_sync(POST_SYNC, 58); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 59: REMU */ + compile_ret_t __remu(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 59); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + + auto cur_pc_val = pc.val; + super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 4; + if(rd != 0){ + { + if((super::template get_reg(rs2 + traits::X0) != 0)) { + auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0) % super::template get_reg(rs2 + traits::X0)); + super::template get_reg(rd + traits::X0)=Xtmp0_val; + } + else { + auto Xtmp1_val = super::template get_reg(rs1 + traits::X0); + super::template get_reg(rd + traits::X0)=Xtmp1_val; + } + } + } + this->do_sync(POST_SYNC, 59); + auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + // trap check + if(trap_state!=0){ + auto& last_br = super::template get_reg(arch::traits::LAST_BRANCH); + last_br = std::numeric_limits::max(); + super::core.enter_trap(trap_state, cur_pc_val); + } + pc.val=super::template get_reg(arch::traits::NEXT_PC); + return pc; + } + + /* instruction 60: C.ADDI4SPN */ + compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr){ + this->do_sync(PRE_SYNC, 60); + uint8_t rd = ((bit_sub<2,3>(instr))); uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); if(this->disass_enabled){ @@ -2073,7 +2413,7 @@ private: } auto Xtmp0_val = (super::template get_reg(2 + traits::X0) + (imm)); super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 52); + this->do_sync(POST_SYNC, 60); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2085,9 +2425,9 @@ private: return pc; } - /* instruction 53: C.LW */ + /* instruction 61: C.LW */ compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 53); + this->do_sync(PRE_SYNC, 61); uint8_t rd = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); @@ -2105,7 +2445,7 @@ private: auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); super::template get_reg(rd + 8 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 53); + this->do_sync(POST_SYNC, 61); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2117,9 +2457,9 @@ private: return pc; } - /* instruction 54: C.SW */ + /* instruction 62: C.SW */ compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 54); + this->do_sync(PRE_SYNC, 62); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); @@ -2137,7 +2477,7 @@ private: auto offs_val = (super::template get_reg(rs1 + 8 + traits::X0) + (uimm)); auto MEMtmp0_val = super::template get_reg(rs2 + 8 + traits::X0); super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 54); + this->do_sync(POST_SYNC, 62); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2149,9 +2489,9 @@ private: return pc; } - /* instruction 55: C.ADDI */ + /* instruction 63: C.ADDI */ compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 55); + this->do_sync(PRE_SYNC, 63); int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,5>(instr))); @@ -2167,7 +2507,7 @@ private: super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; auto Xtmp0_val = (static_cast(super::template get_reg(rs1 + traits::X0)) + (imm)); super::template get_reg(rs1 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 55); + this->do_sync(POST_SYNC, 63); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2179,9 +2519,9 @@ private: return pc; } - /* instruction 56: C.NOP */ + /* instruction 64: C.NOP */ compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 56); + this->do_sync(PRE_SYNC, 64); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2191,7 +2531,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; /* TODO: describe operations for C.NOP ! */ - this->do_sync(POST_SYNC, 56); + this->do_sync(POST_SYNC, 64); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2203,9 +2543,9 @@ private: return pc; } - /* instruction 57: C.JAL */ + /* instruction 65: C.JAL */ compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 57); + this->do_sync(PRE_SYNC, 65); int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ @@ -2224,7 +2564,7 @@ private: super::template get_reg(traits::NEXT_PC) = PC_val; auto is_cont_v = PC_val !=pc.val; super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 57); + this->do_sync(POST_SYNC, 65); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2236,9 +2576,9 @@ private: return pc; } - /* instruction 58: C.LI */ + /* instruction 66: C.LI */ compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 58); + this->do_sync(PRE_SYNC, 66); int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -2257,7 +2597,7 @@ private: } auto Xtmp0_val = (imm); super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 58); + this->do_sync(POST_SYNC, 66); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2269,9 +2609,9 @@ private: return pc; } - /* instruction 59: C.LUI */ + /* instruction 67: C.LUI */ compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 59); + this->do_sync(PRE_SYNC, 67); int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -2293,7 +2633,7 @@ private: } auto Xtmp0_val = (imm); super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 59); + this->do_sync(POST_SYNC, 67); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2305,9 +2645,9 @@ private: return pc; } - /* instruction 60: C.ADDI16SP */ + /* instruction 68: C.ADDI16SP */ compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 60); + this->do_sync(PRE_SYNC, 68); int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ @@ -2322,7 +2662,7 @@ private: super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; auto Xtmp0_val = (static_cast(super::template get_reg(2 + traits::X0)) + (imm)); super::template get_reg(2 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 60); + this->do_sync(POST_SYNC, 68); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2334,9 +2674,9 @@ private: return pc; } - /* instruction 61: C.SRLI */ + /* instruction 69: C.SRLI */ compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 61); + this->do_sync(PRE_SYNC, 69); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -2353,7 +2693,7 @@ private: uint8_t rs1_idx_val = rs1 + 8; auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0))>>(shamt)); super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 61); + this->do_sync(POST_SYNC, 69); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2365,9 +2705,9 @@ private: return pc; } - /* instruction 62: C.SRAI */ + /* instruction 70: C.SRAI */ compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 62); + this->do_sync(PRE_SYNC, 70); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -2384,7 +2724,7 @@ private: uint8_t rs1_idx_val = rs1 + 8; auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0))>>(shamt)); super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 62); + this->do_sync(POST_SYNC, 70); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2396,9 +2736,9 @@ private: return pc; } - /* instruction 63: C.ANDI */ + /* instruction 71: C.ANDI */ compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 63); + this->do_sync(PRE_SYNC, 71); int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -2415,7 +2755,7 @@ private: uint8_t rs1_idx_val = rs1 + 8; auto Xtmp0_val = (static_cast(super::template get_reg(rs1_idx_val + traits::X0)) & (imm)); super::template get_reg(rs1_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 63); + this->do_sync(POST_SYNC, 71); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2427,9 +2767,9 @@ private: return pc; } - /* instruction 64: C.SUB */ + /* instruction 72: C.SUB */ compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 64); + this->do_sync(PRE_SYNC, 72); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -2446,7 +2786,7 @@ private: uint8_t rd_idx_val = rd + 8; auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) - super::template get_reg(rs2 + 8 + traits::X0)); super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 64); + this->do_sync(POST_SYNC, 72); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2458,9 +2798,9 @@ private: return pc; } - /* instruction 65: C.XOR */ + /* instruction 73: C.XOR */ compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 65); + this->do_sync(PRE_SYNC, 73); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -2477,7 +2817,7 @@ private: uint8_t rd_idx_val = rd + 8; auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) ^ super::template get_reg(rs2 + 8 + traits::X0)); super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 65); + this->do_sync(POST_SYNC, 73); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2489,9 +2829,9 @@ private: return pc; } - /* instruction 66: C.OR */ + /* instruction 74: C.OR */ compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 66); + this->do_sync(PRE_SYNC, 74); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -2508,7 +2848,7 @@ private: uint8_t rd_idx_val = rd + 8; auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) | super::template get_reg(rs2 + 8 + traits::X0)); super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 66); + this->do_sync(POST_SYNC, 74); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2520,9 +2860,9 @@ private: return pc; } - /* instruction 67: C.AND */ + /* instruction 75: C.AND */ compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 67); + this->do_sync(PRE_SYNC, 75); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -2539,7 +2879,7 @@ private: uint8_t rd_idx_val = rd + 8; auto Xtmp0_val = (super::template get_reg(rd_idx_val + traits::X0) & super::template get_reg(rs2 + 8 + traits::X0)); super::template get_reg(rd_idx_val + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 67); + this->do_sync(POST_SYNC, 75); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2551,9 +2891,9 @@ private: return pc; } - /* instruction 68: C.J */ + /* instruction 76: C.J */ compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 68); + this->do_sync(PRE_SYNC, 76); int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ @@ -2570,7 +2910,7 @@ private: super::template get_reg(traits::NEXT_PC) = PC_val; auto is_cont_v = PC_val !=pc.val; super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 68); + this->do_sync(POST_SYNC, 76); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2582,9 +2922,9 @@ private: return pc; } - /* instruction 69: C.BEQZ */ + /* instruction 77: C.BEQZ */ compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 69); + this->do_sync(PRE_SYNC, 77); int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -2604,7 +2944,7 @@ private: super::template get_reg(traits::NEXT_PC) = PC_val; auto is_cont_v = PC_val !=pc.val; super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 69); + this->do_sync(POST_SYNC, 77); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2616,9 +2956,9 @@ private: return pc; } - /* instruction 70: C.BNEZ */ + /* instruction 78: C.BNEZ */ compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 70); + this->do_sync(PRE_SYNC, 78); int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -2638,7 +2978,7 @@ private: super::template get_reg(traits::NEXT_PC) = PC_val; auto is_cont_v = PC_val !=pc.val; super::template get_reg(traits::LAST_BRANCH) = is_cont_v?1:0; - this->do_sync(POST_SYNC, 70); + this->do_sync(POST_SYNC, 78); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2650,9 +2990,9 @@ private: return pc; } - /* instruction 71: C.SLLI */ + /* instruction 79: C.SLLI */ compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 71); + this->do_sync(PRE_SYNC, 79); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,5>(instr))); @@ -2671,7 +3011,7 @@ private: } auto Xtmp0_val = (super::template get_reg(rs1 + traits::X0)<<(shamt)); super::template get_reg(rs1 + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 71); + this->do_sync(POST_SYNC, 79); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2683,9 +3023,9 @@ private: return pc; } - /* instruction 72: C.LWSP */ + /* instruction 80: C.LWSP */ compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 72); + this->do_sync(PRE_SYNC, 80); uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -2702,7 +3042,7 @@ private: auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); auto Xtmp0_val = super::template sext(super::template read_mem(traits::MEM, offs_val)); super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 72); + this->do_sync(POST_SYNC, 80); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2714,9 +3054,9 @@ private: return pc; } - /* instruction 73: C.MV */ + /* instruction 81: C.MV */ compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 73); + this->do_sync(PRE_SYNC, 81); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -2732,7 +3072,7 @@ private: super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; auto Xtmp0_val = super::template get_reg(rs2 + traits::X0); super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 73); + this->do_sync(POST_SYNC, 81); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2744,9 +3084,9 @@ private: return pc; } - /* instruction 74: C.JR */ + /* instruction 82: C.JR */ compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 74); + this->do_sync(PRE_SYNC, 82); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2762,7 +3102,7 @@ private: auto PC_val = super::template get_reg(rs1 + traits::X0); super::template get_reg(traits::NEXT_PC) = PC_val; super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - this->do_sync(POST_SYNC, 74); + this->do_sync(POST_SYNC, 82); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2774,9 +3114,9 @@ private: return pc; } - /* instruction 75: C.ADD */ + /* instruction 83: C.ADD */ compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 75); + this->do_sync(PRE_SYNC, 83); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -2792,7 +3132,7 @@ private: super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; auto Xtmp0_val = (super::template get_reg(rd + traits::X0) + super::template get_reg(rs2 + traits::X0)); super::template get_reg(rd + traits::X0)=Xtmp0_val; - this->do_sync(POST_SYNC, 75); + this->do_sync(POST_SYNC, 83); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2804,9 +3144,9 @@ private: return pc; } - /* instruction 76: C.JALR */ + /* instruction 84: C.JALR */ compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 76); + this->do_sync(PRE_SYNC, 84); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2824,7 +3164,7 @@ private: auto PC_val = super::template get_reg(rs1 + traits::X0); super::template get_reg(traits::NEXT_PC) = PC_val; super::template get_reg(traits::LAST_BRANCH) = std::numeric_limits::max(); - this->do_sync(POST_SYNC, 76); + this->do_sync(POST_SYNC, 84); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2836,9 +3176,9 @@ private: return pc; } - /* instruction 77: C.EBREAK */ + /* instruction 85: C.EBREAK */ compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 77); + this->do_sync(PRE_SYNC, 85); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2848,7 +3188,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; raise_trap(0, 3); - this->do_sync(POST_SYNC, 77); + this->do_sync(POST_SYNC, 85); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2860,9 +3200,9 @@ private: return pc; } - /* instruction 78: C.SWSP */ + /* instruction 86: C.SWSP */ compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 78); + this->do_sync(PRE_SYNC, 86); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); @@ -2879,7 +3219,7 @@ private: auto offs_val = (super::template get_reg(2 + traits::X0) + (uimm)); auto MEMtmp0_val = super::template get_reg(rs2 + traits::X0); super::write_mem(traits::MEM, offs_val, static_cast(MEMtmp0_val)); - this->do_sync(POST_SYNC, 78); + this->do_sync(POST_SYNC, 86); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2891,9 +3231,9 @@ private: return pc; } - /* instruction 79: DII */ + /* instruction 87: DII */ compile_ret_t __dii(virt_addr_t& pc, code_word_t instr){ - this->do_sync(PRE_SYNC, 79); + this->do_sync(PRE_SYNC, 87); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2903,7 +3243,7 @@ private: auto cur_pc_val = pc.val; super::template get_reg(arch::traits::NEXT_PC) = cur_pc_val + 2; raise_trap(0, 2); - this->do_sync(POST_SYNC, 79); + this->do_sync(POST_SYNC, 87); auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); // trap check if(trap_state!=0){ @@ -2974,8 +3314,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t star } // namespace mnrv32 template <> -std::unique_ptr create(arch::mnrv32 *core, unsigned short port, bool dump) { - auto ret = new mnrv32::vm_impl(*core, dump); +std::unique_ptr create(arch::tgf02 *core, unsigned short port, bool dump) { + auto ret = new tgf02::vm_impl(*core, dump); if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } diff --git a/src/vm/llvm/vm_mnrv32.cpp b/src/vm/llvm/vm_mnrv32.cpp deleted file mode 100644 index 3d23272..0000000 --- a/src/vm/llvm/vm_mnrv32.cpp +++ /dev/null @@ -1,3627 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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 -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace llvm { -namespace fp_impl { -void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); -} - -namespace mnrv32 { -using namespace ::llvm; -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::llvm::vm_base { -public: - using super = typename iss::llvm::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; - - 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 (vm_base::tgt_adapter == nullptr) - vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm_base::tgt_adapter; - } - -protected: - using vm_base::get_reg_ptr; - - inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - template inline ConstantInt *size(T type) { - return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); - } - - void setup_module(Module* m) override { - super::setup_module(m); - iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); - } - - inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { - return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); - } - - std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override; - - void gen_leave_behavior(BasicBlock *leave_blk) override; - - void gen_raise_trap(uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(unsigned lvl); - - void gen_wait(unsigned type); - - void gen_trap_behavior(BasicBlock *) override; - - void gen_trap_check(BasicBlock *bb); - - inline Value *gen_reg_load(unsigned i, unsigned level = 0) { - return this->builder.CreateLoad(get_reg_ptr(i), false); - } - - inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { - Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); - this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); - } - - // 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) }; - - using this_class = vm_impl; - using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, - code_word_t instr, - BasicBlock *bb); - 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; - } - -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, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &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, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &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 C.ADDI4SPN */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII */ - {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LUI"); - - this->gen_sync(PRE_SYNC, 0); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 0); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 1: AUIPC */ - std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AUIPC"); - - this->gen_sync(PRE_SYNC, 1); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 1); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 2: JAL */ - std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JAL"); - - this->gen_sync(PRE_SYNC, 2); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 2); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 3: JALR */ - std::tuple __jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JALR"); - - this->gen_sync(PRE_SYNC, 3); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* new_pc_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAnd( - new_pc_val, - this->builder.CreateNot(this->gen_const(32U, 0x1))); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 3); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 4: BEQ */ - std::tuple __beq(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BEQ"); - - this->gen_sync(PRE_SYNC, 4); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 4); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 5: BNE */ - std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BNE"); - - this->gen_sync(PRE_SYNC, 5); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 5); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 6: BLT */ - std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLT"); - - this->gen_sync(PRE_SYNC, 6); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 6); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 7: BGE */ - std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGE"); - - this->gen_sync(PRE_SYNC, 7); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGE, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 7); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 8: BLTU */ - std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLTU"); - - this->gen_sync(PRE_SYNC, 8); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 8); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 9: BGEU */ - std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGEU"); - - this->gen_sync(PRE_SYNC, 9); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 9); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 10: LB */ - std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LB"); - - this->gen_sync(PRE_SYNC, 10); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 10); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 11: LH */ - std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LH"); - - this->gen_sync(PRE_SYNC, 11); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 11); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 12: LW */ - std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LW"); - - this->gen_sync(PRE_SYNC, 12); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 12); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 13: LBU */ - std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LBU"); - - this->gen_sync(PRE_SYNC, 13); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 13); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 14: LHU */ - std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LHU"); - - this->gen_sync(PRE_SYNC, 14); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 14); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 15: SB */ - std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SB"); - - this->gen_sync(PRE_SYNC, 15); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 15); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 16: SH */ - std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SH"); - - this->gen_sync(PRE_SYNC, 16); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(16))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 16); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 17: SW */ - std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SW"); - - this->gen_sync(PRE_SYNC, 17); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 17); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 18: ADDI */ - std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDI"); - - this->gen_sync(PRE_SYNC, 18); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 18); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 19: SLTI */ - std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTI"); - - this->gen_sync(PRE_SYNC, 19); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 19); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 20: SLTIU */ - std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTIU"); - - this->gen_sync(PRE_SYNC, 20); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - int32_t full_imm_val = imm; - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, full_imm_val)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 20); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 21: XORI */ - std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XORI"); - - this->gen_sync(PRE_SYNC, 21); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 21); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 22: ORI */ - std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ORI"); - - this->gen_sync(PRE_SYNC, 22); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 22); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 23: ANDI */ - std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ANDI"); - - this->gen_sync(PRE_SYNC, 23); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 23); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 24: SLLI */ - std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 24); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 25: SRLI */ - std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 25); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 26: SRAI */ - std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 26); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 27: ADD */ - std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADD"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 27); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 28: SUB */ - std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SUB"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 28); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 29: SLL */ - std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLL"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 29); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 30: SLT */ - std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLT"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 30); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 31: SLTU */ - std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTU"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, - false)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 31); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 32: XOR */ - std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XOR"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 32); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 33: SRL */ - std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRL"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 33); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 34: SRA */ - std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRA"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 34); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 35: OR */ - std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("OR"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 35); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 36: AND */ - std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AND"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 36); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 37: FENCE */ - std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE"); - - this->gen_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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(32U, pred), - this->gen_const(32U, 4)), - this->gen_const(32U, succ)); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 0), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 37); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 38: FENCE_I */ - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE_I"); - - this->gen_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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence_i"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, imm); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 1), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 38); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(FLUSH, nullptr); - } - - /* instruction 39: ECALL */ - std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ECALL"); - - this->gen_sync(PRE_SYNC, 39); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ecall"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 11); - this->gen_sync(POST_SYNC, 39); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 40: EBREAK */ - std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("EBREAK"); - - this->gen_sync(PRE_SYNC, 40); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ebreak"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 40); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 41: URET */ - std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("URET"); - - this->gen_sync(PRE_SYNC, 41); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("uret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(0); - this->gen_sync(POST_SYNC, 41); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 42: SRET */ - std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRET"); - - this->gen_sync(PRE_SYNC, 42); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(1); - this->gen_sync(POST_SYNC, 42); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 43: MRET */ - std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MRET"); - - this->gen_sync(PRE_SYNC, 43); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("mret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(3); - this->gen_sync(POST_SYNC, 43); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 44: WFI */ - std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("WFI"); - - this->gen_sync(PRE_SYNC, 44); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("wfi"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_wait(1); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 44); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 45: SFENCE.VMA */ - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SFENCE.VMA"); - - this->gen_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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sfence.vma"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, rs1); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 2), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - Value* FENCEtmp1_val = this->gen_const(32U, rs2); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 3), - this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 45); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 46: CSRRW */ - std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRW"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* CSRtmp0_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - Value* Xtmp1_val = csr_val_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* CSRtmp2_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 46); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 47: CSRRS */ - std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRS"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateOr( - xrd_val, - xrs1_val); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 47); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 48: CSRRC */ - std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRC"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - xrd_val, - this->builder.CreateNot(xrs1_val)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 48); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 49: CSRRWI */ - std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRWI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* CSRtmp1_val = this->gen_ext( - this->gen_const(32U, zimm), - 32, - false); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 49); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 50: CSRRSI */ - std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRSI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - if(zimm != 0){ - Value* CSRtmp0_val = this->builder.CreateOr( - res_val, - this->gen_ext( - this->gen_const(32U, zimm), - 32, - false)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - } - if(rd != 0){ - Value* Xtmp1_val = res_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 50); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 51: CSRRCI */ - std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRCI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(zimm != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - res_val, - this->builder.CreateNot(this->gen_ext( - this->gen_const(32U, zimm), - 32, - false))); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 51); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 52: C.ADDI4SPN */ - std::tuple __c_addi4spn(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI4SPN"); - - this->gen_sync(PRE_SYNC, 52); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(imm == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 52); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 53: C.LW */ - std::tuple __c_lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LW"); - - this->gen_sync(PRE_SYNC, 53); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 53); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 54: C.SW */ - std::tuple __c_sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SW"); - - this->gen_sync(PRE_SYNC, 54); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + 8 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 54); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 55: C.ADDI */ - std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI"); - - this->gen_sync(PRE_SYNC, 55); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 55); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 56: C.NOP */ - std::tuple __c_nop(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.NOP"); - - this->gen_sync(PRE_SYNC, 56); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("c.nop"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - /* TODO: describe operations for C.NOP ! */ - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 56); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 57: C.JAL */ - std::tuple __c_jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JAL"); - - this->gen_sync(PRE_SYNC, 57); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(1 + traits::X0), false); - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 57); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 58: C.LI */ - std::tuple __c_li(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LI"); - - this->gen_sync(PRE_SYNC, 58); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rd == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 58); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 59: C.LUI */ - std::tuple __c_lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LUI"); - - this->gen_sync(PRE_SYNC, 59); - - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rd == 0){ - this->gen_raise_trap(0, 2); - } - if(imm == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 59); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 60: C.ADDI16SP */ - std::tuple __c_addi16sp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI16SP"); - - this->gen_sync(PRE_SYNC, 60); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(2 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(2 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 60); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 61: C.SRLI */ - std::tuple __c_srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRLI"); - - this->gen_sync(PRE_SYNC, 61); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 61); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 62: C.SRAI */ - std::tuple __c_srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRAI"); - - this->gen_sync(PRE_SYNC, 62); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 62); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 63: C.ANDI */ - std::tuple __c_andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ANDI"); - - this->gen_sync(PRE_SYNC, 63); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 63); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 64: C.SUB */ - std::tuple __c_sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SUB"); - - this->gen_sync(PRE_SYNC, 64); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 64); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 65: C.XOR */ - std::tuple __c_xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.XOR"); - - this->gen_sync(PRE_SYNC, 65); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 65); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 66: C.OR */ - std::tuple __c_or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.OR"); - - this->gen_sync(PRE_SYNC, 66); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 66); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 67: C.AND */ - std::tuple __c_and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.AND"); - - this->gen_sync(PRE_SYNC, 67); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 67); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 68: C.J */ - std::tuple __c_j(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.J"); - - this->gen_sync(PRE_SYNC, 68); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 68); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 69: C.BEQZ */ - std::tuple __c_beqz(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.BEQZ"); - - this->gen_sync(PRE_SYNC, 69); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 69); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 70: C.BNEZ */ - std::tuple __c_bnez(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.BNEZ"); - - this->gen_sync(PRE_SYNC, 70); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 70); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 71: C.SLLI */ - std::tuple __c_slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SLLI"); - - this->gen_sync(PRE_SYNC, 71); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rs1 == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 71); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 72: C.LWSP */ - std::tuple __c_lwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LWSP"); - - this->gen_sync(PRE_SYNC, 72); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 72); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 73: C.MV */ - std::tuple __c_mv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.MV"); - - this->gen_sync(PRE_SYNC, 73); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 73); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 74: C.JR */ - std::tuple __c_jr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JR"); - - this->gen_sync(PRE_SYNC, 74); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 74); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 75: C.ADD */ - std::tuple __c_add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADD"); - - this->gen_sync(PRE_SYNC, 75); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(rd + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 75); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 76: C.JALR */ - std::tuple __c_jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JALR"); - - this->gen_sync(PRE_SYNC, 76); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(1 + traits::X0), false); - Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 76); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 77: C.EBREAK */ - std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.EBREAK"); - - this->gen_sync(PRE_SYNC, 77); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("c.ebreak"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 77); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 78: C.SWSP */ - std::tuple __c_swsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SWSP"); - - this->gen_sync(PRE_SYNC, 78); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 78); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 79: DII */ - std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DII"); - - this->gen_sync(PRE_SYNC, 79); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("dii"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - this->gen_raise_trap(0, 2); - this->gen_sync(POST_SYNC, 79); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { - this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); - this->builder.CreateStore( - this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits::ICOUNT), true), - this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - this->gen_raise_trap(0, 2); // illegal instruction trap - this->gen_sync(iss::POST_SYNC, instr_descr.size()); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } -}; - -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 -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, this_block); -} - -template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { - this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); -} - -template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { - auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); - this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); -} - -template void vm_impl::gen_leave_trap(unsigned lvl) { - std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) }; - this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); - auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); -} - -template void vm_impl::gen_wait(unsigned type) { - std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) }; - this->builder.CreateCall(this->mod->getFunction("wait"), args); -} - -template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { - this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), - get_reg_ptr(traits::LAST_BRANCH), false); - std::vector args{this->core_ptr, this->adj_to64(trap_state_val), - this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; - this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); - auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateRet(trap_addr_val); -} - -template inline void vm_impl::gen_trap_check(BasicBlock *bb) { - auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, v, - ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, this->trap_blk, 1); -} - -} // namespace mnrv32 - -template <> -std::unique_ptr create(arch::mnrv32 *core, unsigned short port, bool dump) { - auto ret = new mnrv32::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} // namespace llvm -} // namespace iss diff --git a/src/vm/llvm/vm_rv32gc.cpp b/src/vm/llvm/vm_rv32gc.cpp deleted file mode 100644 index 03b1fec..0000000 --- a/src/vm/llvm/vm_rv32gc.cpp +++ /dev/null @@ -1,8865 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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 -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace llvm { -namespace fp_impl { -void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); -} - -namespace rv32gc { -using namespace ::llvm; -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::llvm::vm_base { -public: - using super = typename iss::llvm::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; - - 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 (vm_base::tgt_adapter == nullptr) - vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm_base::tgt_adapter; - } - -protected: - using vm_base::get_reg_ptr; - - inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - template inline ConstantInt *size(T type) { - return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); - } - - void setup_module(Module* m) override { - super::setup_module(m); - iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); - } - - inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { - return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); - } - - std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override; - - void gen_leave_behavior(BasicBlock *leave_blk) override; - - void gen_raise_trap(uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(unsigned lvl); - - void gen_wait(unsigned type); - - void gen_trap_behavior(BasicBlock *) override; - - void gen_trap_check(BasicBlock *bb); - - inline Value *gen_reg_load(unsigned i, unsigned level = 0) { - return this->builder.CreateLoad(get_reg_ptr(i), false); - } - - inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { - Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); - this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); - } - - // 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) }; - - using this_class = vm_impl; - using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, - code_word_t instr, - BasicBlock *bb); - 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; - } - -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, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &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, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &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 MUL */ - {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH */ - {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU */ - {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU */ - {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV */ - {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU */ - {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM */ - {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU */ - {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction LR.W */ - {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lr_w}, - /* instruction SC.W */ - {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__sc_w}, - /* instruction AMOSWAP.W */ - {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_w}, - /* instruction AMOADD.W */ - {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_w}, - /* instruction AMOXOR.W */ - {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_w}, - /* instruction AMOAND.W */ - {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_w}, - /* instruction AMOOR.W */ - {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_w}, - /* instruction AMOMIN.W */ - {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_w}, - /* instruction AMOMAX.W */ - {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_w}, - /* instruction AMOMINU.W */ - {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_w}, - /* instruction AMOMAXU.W */ - {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_w}, - /* instruction FLW */ - {32, 0b00000000000000000010000000000111, 0b00000000000000000111000001111111, &this_class::__flw}, - /* instruction FSW */ - {32, 0b00000000000000000010000000100111, 0b00000000000000000111000001111111, &this_class::__fsw}, - /* instruction FMADD.S */ - {32, 0b00000000000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_s}, - /* instruction FMSUB.S */ - {32, 0b00000000000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_s}, - /* instruction FNMADD.S */ - {32, 0b00000000000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_s}, - /* instruction FNMSUB.S */ - {32, 0b00000000000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_s}, - /* instruction FADD.S */ - {32, 0b00000000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_s}, - /* instruction FSUB.S */ - {32, 0b00001000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_s}, - /* instruction FMUL.S */ - {32, 0b00010000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_s}, - /* instruction FDIV.S */ - {32, 0b00011000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_s}, - /* instruction FSQRT.S */ - {32, 0b01011000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_s}, - /* instruction FSGNJ.S */ - {32, 0b00100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_s}, - /* instruction FSGNJN.S */ - {32, 0b00100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_s}, - /* instruction FSGNJX.S */ - {32, 0b00100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_s}, - /* instruction FMIN.S */ - {32, 0b00101000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_s}, - /* instruction FMAX.S */ - {32, 0b00101000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_s}, - /* instruction FCVT.W.S */ - {32, 0b11000000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_s}, - /* instruction FCVT.WU.S */ - {32, 0b11000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_s}, - /* instruction FEQ.S */ - {32, 0b10100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_s}, - /* instruction FLT.S */ - {32, 0b10100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_s}, - /* instruction FLE.S */ - {32, 0b10100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_s}, - /* instruction FCLASS.S */ - {32, 0b11100000000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_s}, - /* instruction FCVT.S.W */ - {32, 0b11010000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_w}, - /* instruction FCVT.S.WU */ - {32, 0b11010000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_wu}, - /* instruction FMV.X.W */ - {32, 0b11100000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_w}, - /* instruction FMV.W.X */ - {32, 0b11110000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_w_x}, - /* instruction FLD */ - {32, 0b00000000000000000011000000000111, 0b00000000000000000111000001111111, &this_class::__fld}, - /* instruction FSD */ - {32, 0b00000000000000000011000000100111, 0b00000000000000000111000001111111, &this_class::__fsd}, - /* instruction FMADD.D */ - {32, 0b00000010000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_d}, - /* instruction FMSUB.D */ - {32, 0b00000010000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_d}, - /* instruction FNMADD.D */ - {32, 0b00000010000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_d}, - /* instruction FNMSUB.D */ - {32, 0b00000010000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_d}, - /* instruction FADD.D */ - {32, 0b00000010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_d}, - /* instruction FSUB.D */ - {32, 0b00001010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_d}, - /* instruction FMUL.D */ - {32, 0b00010010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_d}, - /* instruction FDIV.D */ - {32, 0b00011010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_d}, - /* instruction FSQRT.D */ - {32, 0b01011010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_d}, - /* instruction FSGNJ.D */ - {32, 0b00100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_d}, - /* instruction FSGNJN.D */ - {32, 0b00100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_d}, - /* instruction FSGNJX.D */ - {32, 0b00100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_d}, - /* instruction FMIN.D */ - {32, 0b00101010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_d}, - /* instruction FMAX.D */ - {32, 0b00101010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_d}, - /* instruction FCVT.S.D */ - {32, 0b01000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_d}, - /* instruction FCVT.D.S */ - {32, 0b01000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_s}, - /* instruction FEQ.D */ - {32, 0b10100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_d}, - /* instruction FLT.D */ - {32, 0b10100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_d}, - /* instruction FLE.D */ - {32, 0b10100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_d}, - /* instruction FCLASS.D */ - {32, 0b11100010000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_d}, - /* instruction FCVT.W.D */ - {32, 0b11000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_d}, - /* instruction FCVT.WU.D */ - {32, 0b11000010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_d}, - /* instruction FCVT.D.W */ - {32, 0b11010010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_w}, - /* instruction FCVT.D.WU */ - {32, 0b11010010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_wu}, - /* instruction C.ADDI4SPN */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII */ - {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, - /* instruction C.FLW */ - {16, 0b0110000000000000, 0b1110000000000011, &this_class::__c_flw}, - /* instruction C.FSW */ - {16, 0b1110000000000000, 0b1110000000000011, &this_class::__c_fsw}, - /* instruction C.FLWSP */ - {16, 0b0110000000000010, 0b1110000000000011, &this_class::__c_flwsp}, - /* instruction C.FSWSP */ - {16, 0b1110000000000010, 0b1110000000000011, &this_class::__c_fswsp}, - /* instruction C.FLD */ - {16, 0b0010000000000000, 0b1110000000000011, &this_class::__c_fld}, - /* instruction C.FSD */ - {16, 0b1010000000000000, 0b1110000000000011, &this_class::__c_fsd}, - /* instruction C.FLDSP */ - {16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_fldsp}, - /* instruction C.FSDSP */ - {16, 0b1010000000000010, 0b1110000000000011, &this_class::__c_fsdsp}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LUI"); - - this->gen_sync(PRE_SYNC, 0); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 0); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 1: AUIPC */ - std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AUIPC"); - - this->gen_sync(PRE_SYNC, 1); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 1); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 2: JAL */ - std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JAL"); - - this->gen_sync(PRE_SYNC, 2); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 2); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 3: JALR */ - std::tuple __jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JALR"); - - this->gen_sync(PRE_SYNC, 3); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* new_pc_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAnd( - new_pc_val, - this->builder.CreateNot(this->gen_const(32U, 0x1))); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 3); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 4: BEQ */ - std::tuple __beq(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BEQ"); - - this->gen_sync(PRE_SYNC, 4); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 4); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 5: BNE */ - std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BNE"); - - this->gen_sync(PRE_SYNC, 5); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 5); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 6: BLT */ - std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLT"); - - this->gen_sync(PRE_SYNC, 6); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 6); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 7: BGE */ - std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGE"); - - this->gen_sync(PRE_SYNC, 7); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGE, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 7); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 8: BLTU */ - std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLTU"); - - this->gen_sync(PRE_SYNC, 8); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 8); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 9: BGEU */ - std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGEU"); - - this->gen_sync(PRE_SYNC, 9); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 9); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 10: LB */ - std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LB"); - - this->gen_sync(PRE_SYNC, 10); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 10); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 11: LH */ - std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LH"); - - this->gen_sync(PRE_SYNC, 11); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 11); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 12: LW */ - std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LW"); - - this->gen_sync(PRE_SYNC, 12); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 12); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 13: LBU */ - std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LBU"); - - this->gen_sync(PRE_SYNC, 13); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 13); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 14: LHU */ - std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LHU"); - - this->gen_sync(PRE_SYNC, 14); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 14); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 15: SB */ - std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SB"); - - this->gen_sync(PRE_SYNC, 15); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 15); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 16: SH */ - std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SH"); - - this->gen_sync(PRE_SYNC, 16); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(16))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 16); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 17: SW */ - std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SW"); - - this->gen_sync(PRE_SYNC, 17); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 17); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 18: ADDI */ - std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDI"); - - this->gen_sync(PRE_SYNC, 18); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 18); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 19: SLTI */ - std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTI"); - - this->gen_sync(PRE_SYNC, 19); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 19); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 20: SLTIU */ - std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTIU"); - - this->gen_sync(PRE_SYNC, 20); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - int32_t full_imm_val = imm; - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, full_imm_val)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 20); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 21: XORI */ - std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XORI"); - - this->gen_sync(PRE_SYNC, 21); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 21); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 22: ORI */ - std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ORI"); - - this->gen_sync(PRE_SYNC, 22); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 22); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 23: ANDI */ - std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ANDI"); - - this->gen_sync(PRE_SYNC, 23); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 23); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 24: SLLI */ - std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 24); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 25: SRLI */ - std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 25); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 26: SRAI */ - std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 26); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 27: ADD */ - std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADD"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 27); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 28: SUB */ - std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SUB"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 28); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 29: SLL */ - std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLL"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 29); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 30: SLT */ - std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLT"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 30); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 31: SLTU */ - std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTU"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, - false)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 31); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 32: XOR */ - std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XOR"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 32); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 33: SRL */ - std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRL"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 33); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 34: SRA */ - std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRA"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 34); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 35: OR */ - std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("OR"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 35); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 36: AND */ - std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AND"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 36); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 37: FENCE */ - std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE"); - - this->gen_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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(32U, pred), - this->gen_const(32U, 4)), - this->gen_const(32U, succ)); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 0), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 37); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 38: FENCE_I */ - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE_I"); - - this->gen_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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence_i"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, imm); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 1), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 38); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(FLUSH, nullptr); - } - - /* instruction 39: ECALL */ - std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ECALL"); - - this->gen_sync(PRE_SYNC, 39); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ecall"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 11); - this->gen_sync(POST_SYNC, 39); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 40: EBREAK */ - std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("EBREAK"); - - this->gen_sync(PRE_SYNC, 40); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ebreak"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 40); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 41: URET */ - std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("URET"); - - this->gen_sync(PRE_SYNC, 41); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("uret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(0); - this->gen_sync(POST_SYNC, 41); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 42: SRET */ - std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRET"); - - this->gen_sync(PRE_SYNC, 42); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(1); - this->gen_sync(POST_SYNC, 42); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 43: MRET */ - std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MRET"); - - this->gen_sync(PRE_SYNC, 43); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("mret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(3); - this->gen_sync(POST_SYNC, 43); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 44: WFI */ - std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("WFI"); - - this->gen_sync(PRE_SYNC, 44); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("wfi"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_wait(1); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 44); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 45: SFENCE.VMA */ - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SFENCE.VMA"); - - this->gen_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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sfence.vma"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, rs1); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 2), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - Value* FENCEtmp1_val = this->gen_const(32U, rs2); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 3), - this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 45); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 46: CSRRW */ - std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRW"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* CSRtmp0_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - Value* Xtmp1_val = csr_val_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* CSRtmp2_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 46); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 47: CSRRS */ - std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRS"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateOr( - xrd_val, - xrs1_val); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 47); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 48: CSRRC */ - std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRC"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - xrd_val, - this->builder.CreateNot(xrs1_val)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 48); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 49: CSRRWI */ - std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRWI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* CSRtmp1_val = this->gen_ext( - this->gen_const(32U, zimm), - 32, - false); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 49); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 50: CSRRSI */ - std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRSI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - if(zimm != 0){ - Value* CSRtmp0_val = this->builder.CreateOr( - res_val, - this->gen_ext( - this->gen_const(32U, zimm), - 32, - false)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - } - if(rd != 0){ - Value* Xtmp1_val = res_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 50); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 51: CSRRCI */ - std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRCI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(zimm != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - res_val, - this->builder.CreateNot(this->gen_ext( - this->gen_const(32U, zimm), - 32, - false))); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 51); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 52: MUL */ - std::tuple __mul(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MUL"); - - this->gen_sync(PRE_SYNC, 52); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 128, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 128, - false)); - Value* Xtmp0_val = this->gen_ext( - res_val, - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 52); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 53: MULH */ - std::tuple __mulh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULH"); - - this->gen_sync(PRE_SYNC, 53); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 128, - true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 128, - true)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(32U, 32)), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 53); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 54: MULHSU */ - std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULHSU"); - - this->gen_sync(PRE_SYNC, 54); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 128, - true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 128, - false)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(32U, 32)), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 54); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 55: MULHU */ - std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULHU"); - - this->gen_sync(PRE_SYNC, 55); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 128, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 128, - false)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(32U, 32)), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 55); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 56: DIV */ - std::tuple __div(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIV"); - - this->gen_sync(PRE_SYNC, 56); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint8_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateAnd( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_const(32U, MMIN_val)), - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs2 + traits::X0, 1), - this->gen_const(32U, M1_val))), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->gen_const(32U, MMIN_val); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateSDiv( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 2), - 32, true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp2_val = this->builder.CreateNeg(this->gen_const(32U, 1)); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 56); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 57: DIVU */ - std::tuple __divu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIVU"); - - this->gen_sync(PRE_SYNC, 57); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->builder.CreateUDiv( - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_reg_load(rs2 + traits::X0, 1)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateNeg(this->gen_const(32U, 1)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 57); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 58: REM */ - std::tuple __rem(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REM"); - - this->gen_sync(PRE_SYNC, 58); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint32_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateAnd( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_const(32U, MMIN_val)), - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs2 + traits::X0, 1), - this->gen_const(32U, M1_val))), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->gen_const(32U, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateSRem( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 2), - 32, true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp2_val = this->gen_reg_load(rs1 + traits::X0, 1); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 58); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 59: REMU */ - std::tuple __remu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REMU"); - - this->gen_sync(PRE_SYNC, 59); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->builder.CreateURem( - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_reg_load(rs2 + traits::X0, 1)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->gen_reg_load(rs1 + traits::X0, 1); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 59); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 60: LR.W */ - std::tuple __lr_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LR.W"); - - this->gen_sync(PRE_SYNC, 60); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* REStmp1_val = this->gen_ext( - this->builder.CreateNeg(this->gen_const(8U, 1)), - 32, - true); - this->gen_write_mem( - traits::RES, - offs_val, - this->builder.CreateZExtOrTrunc(REStmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 60); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 61: SC.W */ - std::tuple __sc_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SC.W"); - - this->gen_sync(PRE_SYNC, 61); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_read_mem(traits::RES, offs_val, 32/8); - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - res1_val, - this->gen_const(32U, 0)), - bb_then, - bbnext); - this->builder.SetInsertPoint(bb_then); - { - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 1); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - if(rd != 0){ - Value* Xtmp1_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - res1_val, - this->gen_ext( - this->gen_const(32U, 0), - 32, - false)), - this->gen_const(32U, 0), - this->gen_const(32U, 1), - 32); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 61); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 62: AMOSWAP.W */ - std::tuple __amoswap_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOSWAP.W"); - - this->gen_sync(PRE_SYNC, 62); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* MEMtmp1_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 62); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 63: AMOADD.W */ - std::tuple __amoadd_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOADD.W"); - - this->gen_sync(PRE_SYNC, 63); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateAdd( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 63); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 64: AMOXOR.W */ - std::tuple __amoxor_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOXOR.W"); - - this->gen_sync(PRE_SYNC, 64); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateXor( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 64); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 65: AMOAND.W */ - std::tuple __amoand_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOAND.W"); - - this->gen_sync(PRE_SYNC, 65); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateAnd( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 65); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 66: AMOOR.W */ - std::tuple __amoor_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOOR.W"); - - this->gen_sync(PRE_SYNC, 66); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateOr( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 66); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 67: AMOMIN.W */ - std::tuple __amomin_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMIN.W"); - - this->gen_sync(PRE_SYNC, 67); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGT, - this->gen_ext( - res1_val, - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 32); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 67); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 68: AMOMAX.W */ - std::tuple __amomax_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAX.W"); - - this->gen_sync(PRE_SYNC, 68); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - res1_val, - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 32); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 68); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 69: AMOMINU.W */ - std::tuple __amominu_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMINU.W"); - - this->gen_sync(PRE_SYNC, 69); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGT, - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 32); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 69); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 70: AMOMAXU.W */ - std::tuple __amomaxu_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAXU.W"); - - this->gen_sync(PRE_SYNC, 70); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 32); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 70); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 71: FLW */ - std::tuple __flw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLW"); - - this->gen_sync(PRE_SYNC, 71); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}(x{rs1})", fmt::arg("mnemonic", "flw"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 71); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 72: FSW */ - std::tuple __fsw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSW"); - - this->gen_sync(PRE_SYNC, 72); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}(x{rs1})", fmt::arg("mnemonic", "fsw"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(32) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 72); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 73: FMADD.S */ - std::tuple __fmadd_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMADD.S"); - - this->gen_sync(PRE_SYNC, 73); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_reg_load(rs3 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs3 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - frs1_val, - frs2_val, - frs3_val, - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 73); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 74: FMSUB.S */ - std::tuple __fmsub_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMSUB.S"); - - this->gen_sync(PRE_SYNC, 74); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_reg_load(rs3 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs3 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - frs1_val, - frs2_val, - frs3_val, - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 74); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 75: FNMADD.S */ - std::tuple __fnmadd_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FNMADD.S"); - - this->gen_sync(PRE_SYNC, 75); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_reg_load(rs3 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs3 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - frs1_val, - frs2_val, - frs3_val, - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 75); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 76: FNMSUB.S */ - std::tuple __fnmsub_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FNMSUB.S"); - - this->gen_sync(PRE_SYNC, 76); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_reg_load(rs3 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs3 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - frs1_val, - frs2_val, - frs3_val, - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 76); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 77: FADD.S */ - std::tuple __fadd_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FADD.S"); - - this->gen_sync(PRE_SYNC, 77); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fadd_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fadd_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 77); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 78: FSUB.S */ - std::tuple __fsub_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSUB.S"); - - this->gen_sync(PRE_SYNC, 78); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsub_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsub_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 78); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 79: FMUL.S */ - std::tuple __fmul_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMUL.S"); - - this->gen_sync(PRE_SYNC, 79); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmul_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmul_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 79); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 80: FDIV.S */ - std::tuple __fdiv_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FDIV.S"); - - this->gen_sync(PRE_SYNC, 80); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fdiv_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fdiv_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 80); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 81: FSQRT.S */ - std::tuple __fsqrt_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSQRT.S"); - - this->gen_sync(PRE_SYNC, 81); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsqrt_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsqrt_s"), std::vector{ - frs1_val, - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 81); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 82: FSGNJ.S */ - std::tuple __fsgnj_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJ.S"); - - this->gen_sync(PRE_SYNC, 82); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateOr( - this->builder.CreateAnd( - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_const(64U, 0x7fffffff)), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_const(64U, 0x80000000))); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateOr( - this->builder.CreateAnd( - frs1_val, - this->gen_const(32U, 0x7fffffff)), - this->builder.CreateAnd( - frs2_val, - this->gen_const(32U, 0x80000000))); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 82); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 83: FSGNJN.S */ - std::tuple __fsgnjn_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJN.S"); - - this->gen_sync(PRE_SYNC, 83); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateOr( - this->builder.CreateAnd( - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_const(64U, 0x7fffffff)), - this->builder.CreateAnd( - this->builder.CreateNot(this->gen_reg_load(rs2 + traits::F0, 0)), - this->gen_const(64U, 0x80000000))); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateOr( - this->builder.CreateAnd( - frs1_val, - this->gen_const(32U, 0x7fffffff)), - this->builder.CreateAnd( - this->builder.CreateNot(frs2_val), - this->gen_const(32U, 0x80000000))); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 83); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 84: FSGNJX.S */ - std::tuple __fsgnjx_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJX.S"); - - this->gen_sync(PRE_SYNC, 84); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateXor( - this->gen_reg_load(rs1 + traits::F0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_const(64U, 0x80000000))); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateXor( - frs1_val, - this->builder.CreateAnd( - frs2_val, - this->gen_const(32U, 0x80000000))); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 84); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 85: FMIN.S */ - std::tuple __fmin_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMIN.S"); - - this->gen_sync(PRE_SYNC, 85); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 85); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 86: FMAX.S */ - std::tuple __fmax_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMAX.S"); - - this->gen_sync(PRE_SYNC, 86); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 86); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 87: FCVT.W.S */ - std::tuple __fcvt_w_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.W.S"); - - this->gen_sync(PRE_SYNC, 87); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_const(8U, rm) - }), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - frs1_val, - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_const(8U, rm) - }), - 32, - true); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 87); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 88: FCVT.WU.S */ - std::tuple __fcvt_wu_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.WU.S"); - - this->gen_sync(PRE_SYNC, 88); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_const(8U, rm) - }), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - frs1_val, - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_const(8U, rm) - }), - 32, - true); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 88); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 89: FEQ.S */ - std::tuple __feq_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FEQ.S"); - - this->gen_sync(PRE_SYNC, 89); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }), - 32, - false); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 89); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 90: FLT.S */ - std::tuple __flt_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLT.S"); - - this->gen_sync(PRE_SYNC, 90); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false) - }), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false) - }), - 32, - false); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - Value* Xtmp2_val = this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false) - }); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 90); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 91: FLE.S */ - std::tuple __fle_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLE.S"); - - this->gen_sync(PRE_SYNC, 91); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }), - 32, - false); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 91); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 92: FCLASS.S */ - std::tuple __fclass_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCLASS.S"); - - this->gen_sync(PRE_SYNC, 92); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->builder.CreateCall(this->mod->getFunction("fclass_s"), std::vector{ - this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 92); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 93: FCVT.S.W */ - std::tuple __fcvt_s_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.S.W"); - - this->gen_sync(PRE_SYNC, 93); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_const(8U, rm) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_const(8U, rm) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 93); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 94: FCVT.S.WU */ - std::tuple __fcvt_s_wu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.S.WU"); - - this->gen_sync(PRE_SYNC, 94); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_const(8U, rm) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_const(8U, rm) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 94); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 95: FMV.X.W */ - std::tuple __fmv_x_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMV.X.W"); - - this->gen_sync(PRE_SYNC, 95); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fmv.x.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(32) - ), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 95); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 96: FMV.W.X */ - std::tuple __fmv_w_x(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMV.W.X"); - - this->gen_sync(PRE_SYNC, 96); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fmv.w.x"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 96); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 97: FLD */ - std::tuple __fld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLD"); - - this->gen_sync(PRE_SYNC, 97); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}({rs1})", fmt::arg("mnemonic", "fld"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 64/8); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 97); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 98: FSD */ - std::tuple __fsd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSD"); - - this->gen_sync(PRE_SYNC, 98); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}({rs1})", fmt::arg("mnemonic", "fsd"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 98); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 99: FMADD.D */ - std::tuple __fmadd_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMADD.D"); - - this->gen_sync(PRE_SYNC, 99); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs3 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 64, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 99); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 100: FMSUB.D */ - std::tuple __fmsub_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMSUB.D"); - - this->gen_sync(PRE_SYNC, 100); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs3 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 100); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 101: FNMADD.D */ - std::tuple __fnmadd_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FNMADD.D"); - - this->gen_sync(PRE_SYNC, 101); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs3 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 101); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 102: FNMSUB.D */ - std::tuple __fnmsub_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FNMSUB.D"); - - this->gen_sync(PRE_SYNC, 102); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs3 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 102); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 103: FADD.D */ - std::tuple __fadd_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FADD.D"); - - this->gen_sync(PRE_SYNC, 103); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fadd_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 103); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 104: FSUB.D */ - std::tuple __fsub_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSUB.D"); - - this->gen_sync(PRE_SYNC, 104); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsub_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 104); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 105: FMUL.D */ - std::tuple __fmul_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMUL.D"); - - this->gen_sync(PRE_SYNC, 105); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmul_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 105); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 106: FDIV.D */ - std::tuple __fdiv_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FDIV.D"); - - this->gen_sync(PRE_SYNC, 106); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fdiv_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 106); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 107: FSQRT.D */ - std::tuple __fsqrt_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSQRT.D"); - - this->gen_sync(PRE_SYNC, 107); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsqrt_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 107); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 108: FSGNJ.D */ - std::tuple __fsgnj_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJ.D"); - - this->gen_sync(PRE_SYNC, 108); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - Value* res_val = this->builder.CreateOr( - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_const(64U, MSK2_val)), - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_const(64U, MSK1_val))); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 108); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 109: FSGNJN.D */ - std::tuple __fsgnjn_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJN.D"); - - this->gen_sync(PRE_SYNC, 109); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - Value* res_val = this->builder.CreateOr( - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_const(64U, MSK2_val)), - this->builder.CreateAnd( - this->builder.CreateNot(this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - )), - this->gen_const(64U, MSK1_val))); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 109); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 110: FSGNJX.D */ - std::tuple __fsgnjx_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJX.D"); - - this->gen_sync(PRE_SYNC, 110); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - Value* res_val = this->builder.CreateXor( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_const(64U, MSK1_val))); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 110); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 111: FMIN.D */ - std::tuple __fmin_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMIN.D"); - - this->gen_sync(PRE_SYNC, 111); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 111); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 112: FMAX.D */ - std::tuple __fmax_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMAX.D"); - - this->gen_sync(PRE_SYNC, 112); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 112); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 113: FCVT.S.D */ - std::tuple __fcvt_s_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.S.D"); - - this->gen_sync(PRE_SYNC, 113); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.s.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fconv_d2f"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_const(8U, rm) - }); - uint64_t upper_val = - 1; - Value* Ftmp0_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 113); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 114: FCVT.D.S */ - std::tuple __fcvt_d_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.D.S"); - - this->gen_sync(PRE_SYNC, 114); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.d.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fconv_f2d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(32) - ), - this->gen_const(8U, rm) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 114); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 115: FEQ.D */ - std::tuple __feq_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FEQ.D"); - - this->gen_sync(PRE_SYNC, 115); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 115); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 116: FLT.D */ - std::tuple __flt_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLT.D"); - - this->gen_sync(PRE_SYNC, 116); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false) - }), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 116); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 117: FLE.D */ - std::tuple __fle_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLE.D"); - - this->gen_sync(PRE_SYNC, 117); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 117); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 118: FCLASS.D */ - std::tuple __fclass_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCLASS.D"); - - this->gen_sync(PRE_SYNC, 118); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->builder.CreateCall(this->mod->getFunction("fclass_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 118); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 119: FCVT.W.D */ - std::tuple __fcvt_w_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.W.D"); - - this->gen_sync(PRE_SYNC, 119); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_64_32"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_const(8U, rm) - }), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 119); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 120: FCVT.WU.D */ - std::tuple __fcvt_wu_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.WU.D"); - - this->gen_sync(PRE_SYNC, 120); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_64_32"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_const(8U, rm) - }), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 120); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 121: FCVT.D.W */ - std::tuple __fcvt_d_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.D.W"); - - this->gen_sync(PRE_SYNC, 121); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_32_64"), std::vector{ - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - 64, - true), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_const(8U, rm) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 121); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 122: FCVT.D.WU */ - std::tuple __fcvt_d_wu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.D.WU"); - - this->gen_sync(PRE_SYNC, 122); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_32_64"), std::vector{ - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - 64, - false), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_const(8U, rm) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 122); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 123: C.ADDI4SPN */ - std::tuple __c_addi4spn(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI4SPN"); - - this->gen_sync(PRE_SYNC, 123); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(imm == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 123); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 124: C.LW */ - std::tuple __c_lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LW"); - - this->gen_sync(PRE_SYNC, 124); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 124); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 125: C.SW */ - std::tuple __c_sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SW"); - - this->gen_sync(PRE_SYNC, 125); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + 8 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 125); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 126: C.ADDI */ - std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI"); - - this->gen_sync(PRE_SYNC, 126); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 126); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 127: C.NOP */ - std::tuple __c_nop(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.NOP"); - - this->gen_sync(PRE_SYNC, 127); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("c.nop"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - /* TODO: describe operations for C.NOP ! */ - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 127); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 128: C.JAL */ - std::tuple __c_jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JAL"); - - this->gen_sync(PRE_SYNC, 128); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(1 + traits::X0), false); - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 128); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 129: C.LI */ - std::tuple __c_li(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LI"); - - this->gen_sync(PRE_SYNC, 129); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rd == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 129); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 130: C.LUI */ - std::tuple __c_lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LUI"); - - this->gen_sync(PRE_SYNC, 130); - - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rd == 0){ - this->gen_raise_trap(0, 2); - } - if(imm == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 130); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 131: C.ADDI16SP */ - std::tuple __c_addi16sp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI16SP"); - - this->gen_sync(PRE_SYNC, 131); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(2 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(2 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 131); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 132: C.SRLI */ - std::tuple __c_srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRLI"); - - this->gen_sync(PRE_SYNC, 132); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 132); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 133: C.SRAI */ - std::tuple __c_srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRAI"); - - this->gen_sync(PRE_SYNC, 133); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 133); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 134: C.ANDI */ - std::tuple __c_andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ANDI"); - - this->gen_sync(PRE_SYNC, 134); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 134); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 135: C.SUB */ - std::tuple __c_sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SUB"); - - this->gen_sync(PRE_SYNC, 135); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 135); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 136: C.XOR */ - std::tuple __c_xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.XOR"); - - this->gen_sync(PRE_SYNC, 136); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 136); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 137: C.OR */ - std::tuple __c_or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.OR"); - - this->gen_sync(PRE_SYNC, 137); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 137); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 138: C.AND */ - std::tuple __c_and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.AND"); - - this->gen_sync(PRE_SYNC, 138); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 138); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 139: C.J */ - std::tuple __c_j(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.J"); - - this->gen_sync(PRE_SYNC, 139); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 139); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 140: C.BEQZ */ - std::tuple __c_beqz(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.BEQZ"); - - this->gen_sync(PRE_SYNC, 140); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 140); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 141: C.BNEZ */ - std::tuple __c_bnez(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.BNEZ"); - - this->gen_sync(PRE_SYNC, 141); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 141); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 142: C.SLLI */ - std::tuple __c_slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SLLI"); - - this->gen_sync(PRE_SYNC, 142); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rs1 == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 142); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 143: C.LWSP */ - std::tuple __c_lwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LWSP"); - - this->gen_sync(PRE_SYNC, 143); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 143); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 144: C.MV */ - std::tuple __c_mv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.MV"); - - this->gen_sync(PRE_SYNC, 144); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 144); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 145: C.JR */ - std::tuple __c_jr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JR"); - - this->gen_sync(PRE_SYNC, 145); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 145); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 146: C.ADD */ - std::tuple __c_add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADD"); - - this->gen_sync(PRE_SYNC, 146); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(rd + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 146); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 147: C.JALR */ - std::tuple __c_jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JALR"); - - this->gen_sync(PRE_SYNC, 147); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(1 + traits::X0), false); - Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 147); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 148: C.EBREAK */ - std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.EBREAK"); - - this->gen_sync(PRE_SYNC, 148); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("c.ebreak"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 148); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 149: C.SWSP */ - std::tuple __c_swsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SWSP"); - - this->gen_sync(PRE_SYNC, 149); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 149); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 150: DII */ - std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DII"); - - this->gen_sync(PRE_SYNC, 150); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("dii"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - this->gen_raise_trap(0, 2); - this->gen_sync(POST_SYNC, 150); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 151: C.FLW */ - std::tuple __c_flw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FLW"); - - this->gen_sync(PRE_SYNC, 151); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rd}), {uimm}({rs1})", fmt::arg("mnemonic", "c.flw"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + 8 + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + 8 + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 151); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 152: C.FSW */ - std::tuple __c_fsw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FSW"); - - this->gen_sync(PRE_SYNC, 152); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rs2}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fsw"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + 8 + traits::F0, 0), - this-> get_type(32) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 152); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 153: C.FLWSP */ - std::tuple __c_flwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FLWSP"); - - this->gen_sync(PRE_SYNC, 153); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {uimm}(x2)", fmt::arg("mnemonic", "c.flwsp"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 153); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 154: C.FSWSP */ - std::tuple __c_fswsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FSWSP"); - - this->gen_sync(PRE_SYNC, 154); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {uimm}(x2), ", fmt::arg("mnemonic", "c.fswsp"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(32) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 154); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 155: C.FLD */ - std::tuple __c_fld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FLD"); - - this->gen_sync(PRE_SYNC, 155); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rd}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fld"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 64/8); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + 8 + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + 8 + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 155); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 156: C.FSD */ - std::tuple __c_fsd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FSD"); - - this->gen_sync(PRE_SYNC, 156); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rs2}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fsd"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + 8 + traits::F0, 0), - this-> get_type(64) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 156); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 157: C.FLDSP */ - std::tuple __c_fldsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FLDSP"); - - this->gen_sync(PRE_SYNC, 157); - - uint16_t uimm = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {uimm}(x2)", fmt::arg("mnemonic", "c.fldsp"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 64/8); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 157); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 158: C.FSDSP */ - std::tuple __c_fsdsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FSDSP"); - - this->gen_sync(PRE_SYNC, 158); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint16_t uimm = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {uimm}(x2), ", fmt::arg("mnemonic", "c.fsdsp"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 158); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { - this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); - this->builder.CreateStore( - this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits::ICOUNT), true), - this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - this->gen_raise_trap(0, 2); // illegal instruction trap - this->gen_sync(iss::POST_SYNC, instr_descr.size()); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } -}; - -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 -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, this_block); -} - -template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { - this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); -} - -template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { - auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); - this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); -} - -template void vm_impl::gen_leave_trap(unsigned lvl) { - std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) }; - this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); - auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); -} - -template void vm_impl::gen_wait(unsigned type) { - std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) }; - this->builder.CreateCall(this->mod->getFunction("wait"), args); -} - -template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { - this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), - get_reg_ptr(traits::LAST_BRANCH), false); - std::vector args{this->core_ptr, this->adj_to64(trap_state_val), - this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; - this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); - auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateRet(trap_addr_val); -} - -template inline void vm_impl::gen_trap_check(BasicBlock *bb) { - auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, v, - ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, this->trap_blk, 1); -} - -} // namespace rv32gc - -template <> -std::unique_ptr create(arch::rv32gc *core, unsigned short port, bool dump) { - auto ret = new rv32gc::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} // namespace llvm -} // namespace iss diff --git a/src/vm/llvm/vm_rv64gc.cpp b/src/vm/llvm/vm_rv64gc.cpp deleted file mode 100644 index 90f5867..0000000 --- a/src/vm/llvm/vm_rv64gc.cpp +++ /dev/null @@ -1,11355 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 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 -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace llvm { -namespace fp_impl { -void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); -} - -namespace rv64gc { -using namespace ::llvm; -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::llvm::vm_base { -public: - using super = typename iss::llvm::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; - - 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 (vm_base::tgt_adapter == nullptr) - vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm_base::tgt_adapter; - } - -protected: - using vm_base::get_reg_ptr; - - inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - template inline ConstantInt *size(T type) { - return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); - } - - void setup_module(Module* m) override { - super::setup_module(m); - iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); - } - - inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { - return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); - } - - std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override; - - void gen_leave_behavior(BasicBlock *leave_blk) override; - - void gen_raise_trap(uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(unsigned lvl); - - void gen_wait(unsigned type); - - void gen_trap_behavior(BasicBlock *) override; - - void gen_trap_check(BasicBlock *bb); - - inline Value *gen_reg_load(unsigned i, unsigned level = 0) { - return this->builder.CreateLoad(get_reg_ptr(i), false); - } - - inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { - Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); - this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); - } - - // 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) }; - - using this_class = vm_impl; - using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, - code_word_t instr, - BasicBlock *bb); - 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; - } - -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, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &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, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &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 LWU */ - {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, - /* instruction LD */ - {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, &this_class::__ld}, - /* instruction SD */ - {32, 0b00000000000000000011000000100011, 0b00000000000000000111000001111111, &this_class::__sd}, - /* instruction ADDIW */ - {32, 0b00000000000000000000000000011011, 0b00000000000000000111000001111111, &this_class::__addiw}, - /* instruction SLLIW */ - {32, 0b00000000000000000001000000011011, 0b11111110000000000111000001111111, &this_class::__slliw}, - /* instruction SRLIW */ - {32, 0b00000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__srliw}, - /* instruction SRAIW */ - {32, 0b01000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__sraiw}, - /* instruction ADDW */ - {32, 0b00000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__addw}, - /* instruction SUBW */ - {32, 0b01000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__subw}, - /* instruction SLLW */ - {32, 0b00000000000000000001000000111011, 0b11111110000000000111000001111111, &this_class::__sllw}, - /* instruction SRLW */ - {32, 0b00000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__srlw}, - /* instruction SRAW */ - {32, 0b01000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__sraw}, - /* instruction MUL */ - {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH */ - {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU */ - {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU */ - {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV */ - {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU */ - {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM */ - {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU */ - {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction MULW */ - {32, 0b00000010000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__mulw}, - /* instruction DIVW */ - {32, 0b00000010000000000100000000111011, 0b11111110000000000111000001111111, &this_class::__divw}, - /* instruction DIVUW */ - {32, 0b00000010000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__divuw}, - /* instruction REMW */ - {32, 0b00000010000000000110000000111011, 0b11111110000000000111000001111111, &this_class::__remw}, - /* instruction REMUW */ - {32, 0b00000010000000000111000000111011, 0b11111110000000000111000001111111, &this_class::__remuw}, - /* instruction LR.W */ - {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lr_w}, - /* instruction SC.W */ - {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__sc_w}, - /* instruction AMOSWAP.W */ - {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_w}, - /* instruction AMOADD.W */ - {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_w}, - /* instruction AMOXOR.W */ - {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_w}, - /* instruction AMOAND.W */ - {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_w}, - /* instruction AMOOR.W */ - {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_w}, - /* instruction AMOMIN.W */ - {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_w}, - /* instruction AMOMAX.W */ - {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_w}, - /* instruction AMOMINU.W */ - {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_w}, - /* instruction AMOMAXU.W */ - {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_w}, - /* instruction LR.D */ - {32, 0b00010000000000000011000000101111, 0b11111001111100000111000001111111, &this_class::__lr_d}, - /* instruction SC.D */ - {32, 0b00011000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__sc_d}, - /* instruction AMOSWAP.D */ - {32, 0b00001000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_d}, - /* instruction AMOADD.D */ - {32, 0b00000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_d}, - /* instruction AMOXOR.D */ - {32, 0b00100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_d}, - /* instruction AMOAND.D */ - {32, 0b01100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_d}, - /* instruction AMOOR.D */ - {32, 0b01000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_d}, - /* instruction AMOMIN.D */ - {32, 0b10000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_d}, - /* instruction AMOMAX.D */ - {32, 0b10100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_d}, - /* instruction AMOMINU.D */ - {32, 0b11000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_d}, - /* instruction AMOMAXU.D */ - {32, 0b11100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_d}, - /* instruction FLW */ - {32, 0b00000000000000000010000000000111, 0b00000000000000000111000001111111, &this_class::__flw}, - /* instruction FSW */ - {32, 0b00000000000000000010000000100111, 0b00000000000000000111000001111111, &this_class::__fsw}, - /* instruction FMADD.S */ - {32, 0b00000000000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_s}, - /* instruction FMSUB.S */ - {32, 0b00000000000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_s}, - /* instruction FNMADD.S */ - {32, 0b00000000000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_s}, - /* instruction FNMSUB.S */ - {32, 0b00000000000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_s}, - /* instruction FADD.S */ - {32, 0b00000000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_s}, - /* instruction FSUB.S */ - {32, 0b00001000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_s}, - /* instruction FMUL.S */ - {32, 0b00010000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_s}, - /* instruction FDIV.S */ - {32, 0b00011000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_s}, - /* instruction FSQRT.S */ - {32, 0b01011000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_s}, - /* instruction FSGNJ.S */ - {32, 0b00100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_s}, - /* instruction FSGNJN.S */ - {32, 0b00100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_s}, - /* instruction FSGNJX.S */ - {32, 0b00100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_s}, - /* instruction FMIN.S */ - {32, 0b00101000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_s}, - /* instruction FMAX.S */ - {32, 0b00101000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_s}, - /* instruction FCVT.W.S */ - {32, 0b11000000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_s}, - /* instruction FCVT.WU.S */ - {32, 0b11000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_s}, - /* instruction FEQ.S */ - {32, 0b10100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_s}, - /* instruction FLT.S */ - {32, 0b10100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_s}, - /* instruction FLE.S */ - {32, 0b10100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_s}, - /* instruction FCLASS.S */ - {32, 0b11100000000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_s}, - /* instruction FCVT.S.W */ - {32, 0b11010000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_w}, - /* instruction FCVT.S.WU */ - {32, 0b11010000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_wu}, - /* instruction FMV.X.W */ - {32, 0b11100000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_w}, - /* instruction FMV.W.X */ - {32, 0b11110000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_w_x}, - /* instruction FCVT.L.S */ - {32, 0b11000000001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_l_s}, - /* instruction FCVT.LU.S */ - {32, 0b11000000001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_lu_s}, - /* instruction FCVT.S.L */ - {32, 0b11010000001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_l}, - /* instruction FCVT.S.LU */ - {32, 0b11010000001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_lu}, - /* instruction FLD */ - {32, 0b00000000000000000011000000000111, 0b00000000000000000111000001111111, &this_class::__fld}, - /* instruction FSD */ - {32, 0b00000000000000000011000000100111, 0b00000000000000000111000001111111, &this_class::__fsd}, - /* instruction FMADD.D */ - {32, 0b00000010000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_d}, - /* instruction FMSUB.D */ - {32, 0b00000010000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_d}, - /* instruction FNMADD.D */ - {32, 0b00000010000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_d}, - /* instruction FNMSUB.D */ - {32, 0b00000010000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_d}, - /* instruction FADD.D */ - {32, 0b00000010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_d}, - /* instruction FSUB.D */ - {32, 0b00001010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_d}, - /* instruction FMUL.D */ - {32, 0b00010010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_d}, - /* instruction FDIV.D */ - {32, 0b00011010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_d}, - /* instruction FSQRT.D */ - {32, 0b01011010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_d}, - /* instruction FSGNJ.D */ - {32, 0b00100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_d}, - /* instruction FSGNJN.D */ - {32, 0b00100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_d}, - /* instruction FSGNJX.D */ - {32, 0b00100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_d}, - /* instruction FMIN.D */ - {32, 0b00101010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_d}, - /* instruction FMAX.D */ - {32, 0b00101010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_d}, - /* instruction FCVT.S.D */ - {32, 0b01000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_d}, - /* instruction FCVT.D.S */ - {32, 0b01000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_s}, - /* instruction FEQ.D */ - {32, 0b10100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_d}, - /* instruction FLT.D */ - {32, 0b10100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_d}, - /* instruction FLE.D */ - {32, 0b10100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_d}, - /* instruction FCLASS.D */ - {32, 0b11100010000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_d}, - /* instruction FCVT.W.D */ - {32, 0b11000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_d}, - /* instruction FCVT.WU.D */ - {32, 0b11000010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_d}, - /* instruction FCVT.D.W */ - {32, 0b11010010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_w}, - /* instruction FCVT.D.WU */ - {32, 0b11010010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_wu}, - /* instruction FCVT.L.D */ - {32, 0b11000010001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_l_d}, - /* instruction FCVT.LU.D */ - {32, 0b11000010001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_lu_d}, - /* instruction FCVT.D.L */ - {32, 0b11010010001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_l}, - /* instruction FCVT.D.LU */ - {32, 0b11010010001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_lu}, - /* instruction FMV.X.D */ - {32, 0b11100010000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_d}, - /* instruction FMV.D.X */ - {32, 0b11110010000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_d_x}, - /* instruction C.ADDI4SPN */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII */ - {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, - /* instruction C.LD */ - {16, 0b0110000000000000, 0b1110000000000011, &this_class::__c_ld}, - /* instruction C.SD */ - {16, 0b1110000000000000, 0b1110000000000011, &this_class::__c_sd}, - /* instruction C.SUBW */ - {16, 0b1001110000000001, 0b1111110001100011, &this_class::__c_subw}, - /* instruction C.ADDW */ - {16, 0b1001110000100001, 0b1111110001100011, &this_class::__c_addw}, - /* instruction C.ADDIW */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_addiw}, - /* instruction C.LDSP */ - {16, 0b0110000000000010, 0b1110000000000011, &this_class::__c_ldsp}, - /* instruction C.SDSP */ - {16, 0b1110000000000010, 0b1110000000000011, &this_class::__c_sdsp}, - /* instruction C.FLW */ - {16, 0b0110000000000000, 0b1110000000000011, &this_class::__c_flw}, - /* instruction C.FSW */ - {16, 0b1110000000000000, 0b1110000000000011, &this_class::__c_fsw}, - /* instruction C.FLWSP */ - {16, 0b0110000000000010, 0b1110000000000011, &this_class::__c_flwsp}, - /* instruction C.FSWSP */ - {16, 0b1110000000000010, 0b1110000000000011, &this_class::__c_fswsp}, - /* instruction C.FLD */ - {16, 0b0010000000000000, 0b1110000000000011, &this_class::__c_fld}, - /* instruction C.FSD */ - {16, 0b1010000000000000, 0b1110000000000011, &this_class::__c_fsd}, - /* instruction C.FLDSP */ - {16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_fldsp}, - /* instruction C.FSDSP */ - {16, 0b1010000000000010, 0b1110000000000011, &this_class::__c_fsdsp}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LUI"); - - this->gen_sync(PRE_SYNC, 0); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_const(64U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 0); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 1: AUIPC */ - std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AUIPC"); - - this->gen_sync(PRE_SYNC, 1); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 1); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 2: JAL */ - std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JAL"); - - this->gen_sync(PRE_SYNC, 2); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 2); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 3: JALR */ - std::tuple __jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JALR"); - - this->gen_sync(PRE_SYNC, 3); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* new_pc_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAnd( - new_pc_val, - this->builder.CreateNot(this->gen_const(64U, 0x1))); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 3); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 4: BEQ */ - std::tuple __beq(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BEQ"); - - this->gen_sync(PRE_SYNC, 4); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 4); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 5: BNE */ - std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BNE"); - - this->gen_sync(PRE_SYNC, 5); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 5); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 6: BLT */ - std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLT"); - - this->gen_sync(PRE_SYNC, 6); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 6); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 7: BGE */ - std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGE"); - - this->gen_sync(PRE_SYNC, 7); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGE, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 7); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 8: BLTU */ - std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLTU"); - - this->gen_sync(PRE_SYNC, 8); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 8); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 9: BGEU */ - std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGEU"); - - this->gen_sync(PRE_SYNC, 9); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 9); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 10: LB */ - std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LB"); - - this->gen_sync(PRE_SYNC, 10); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 10); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 11: LH */ - std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LH"); - - this->gen_sync(PRE_SYNC, 11); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 11); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 12: LW */ - std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LW"); - - this->gen_sync(PRE_SYNC, 12); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 12); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 13: LBU */ - std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LBU"); - - this->gen_sync(PRE_SYNC, 13); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 13); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 14: LHU */ - std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LHU"); - - this->gen_sync(PRE_SYNC, 14); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 14); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 15: SB */ - std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SB"); - - this->gen_sync(PRE_SYNC, 15); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 15); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 16: SH */ - std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SH"); - - this->gen_sync(PRE_SYNC, 16); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(16))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 16); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 17: SW */ - std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SW"); - - this->gen_sync(PRE_SYNC, 17); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 17); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 18: ADDI */ - std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDI"); - - this->gen_sync(PRE_SYNC, 18); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 18); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 19: SLTI */ - std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTI"); - - this->gen_sync(PRE_SYNC, 19); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 19); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 20: SLTIU */ - std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTIU"); - - this->gen_sync(PRE_SYNC, 20); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - int64_t full_imm_val = imm; - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(64U, full_imm_val)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 20); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 21: XORI */ - std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XORI"); - - this->gen_sync(PRE_SYNC, 21); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 21); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 22: ORI */ - std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ORI"); - - this->gen_sync(PRE_SYNC, 22); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 22); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 23: ANDI */ - std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ANDI"); - - this->gen_sync(PRE_SYNC, 23); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 23); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 24: SLLI */ - std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(64U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 24); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 25: SRLI */ - std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(64U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 25); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 26: SRAI */ - std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(64U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 26); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 27: ADD */ - std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADD"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 27); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 28: SUB */ - std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SUB"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 28); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 29: SLL */ - std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLL"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(64U, 64), - this->gen_const(64U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 29); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 30: SLT */ - std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLT"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, true)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 30); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 31: SLTU */ - std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTU"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, - false)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 31); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 32: XOR */ - std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XOR"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 32); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 33: SRL */ - std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRL"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(64U, 64), - this->gen_const(64U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 33); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 34: SRA */ - std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRA"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(64U, 64), - this->gen_const(64U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 34); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 35: OR */ - std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("OR"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 35); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 36: AND */ - std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AND"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 36); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 37: FENCE */ - std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE"); - - this->gen_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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, pred), - this->gen_const(64U, 4)), - this->gen_const(64U, succ)); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 0), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 37); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 38: FENCE_I */ - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE_I"); - - this->gen_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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence_i"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(64U, imm); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 1), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 38); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(FLUSH, nullptr); - } - - /* instruction 39: ECALL */ - std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ECALL"); - - this->gen_sync(PRE_SYNC, 39); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ecall"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 11); - this->gen_sync(POST_SYNC, 39); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 40: EBREAK */ - std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("EBREAK"); - - this->gen_sync(PRE_SYNC, 40); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ebreak"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 40); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 41: URET */ - std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("URET"); - - this->gen_sync(PRE_SYNC, 41); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("uret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_leave_trap(0); - this->gen_sync(POST_SYNC, 41); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 42: SRET */ - std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRET"); - - this->gen_sync(PRE_SYNC, 42); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_leave_trap(1); - this->gen_sync(POST_SYNC, 42); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 43: MRET */ - std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MRET"); - - this->gen_sync(PRE_SYNC, 43); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("mret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_leave_trap(3); - this->gen_sync(POST_SYNC, 43); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 44: WFI */ - std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("WFI"); - - this->gen_sync(PRE_SYNC, 44); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("wfi"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_wait(1); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 44); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 45: SFENCE.VMA */ - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SFENCE.VMA"); - - this->gen_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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sfence.vma"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(64U, rs1); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 2), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); - Value* FENCEtmp1_val = this->gen_const(64U, rs2); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 3), - this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 45); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 46: CSRRW */ - std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRW"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); - Value* CSRtmp0_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(64))); - Value* Xtmp1_val = csr_val_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* CSRtmp2_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(64))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 46); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 47: CSRRS */ - std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRS"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateOr( - xrd_val, - xrs1_val); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 47); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 48: CSRRC */ - std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRC"); - - this->gen_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))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - xrd_val, - this->builder.CreateNot(xrs1_val)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 48); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 49: CSRRWI */ - std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRWI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* CSRtmp1_val = this->gen_ext( - this->gen_const(64U, zimm), - 64, - false); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 49); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 50: CSRRSI */ - std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRSI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); - if(zimm != 0){ - Value* CSRtmp0_val = this->builder.CreateOr( - res_val, - this->gen_ext( - this->gen_const(64U, zimm), - 64, - false)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(64))); - } - if(rd != 0){ - Value* Xtmp1_val = res_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 50); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 51: CSRRCI */ - std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRCI"); - - this->gen_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)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(zimm != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - res_val, - this->builder.CreateNot(this->gen_ext( - this->gen_const(64U, zimm), - 64, - false))); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 51); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 52: LWU */ - std::tuple __lwu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LWU"); - - this->gen_sync(PRE_SYNC, 52); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lwu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 52); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 53: LD */ - std::tuple __ld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LD"); - - this->gen_sync(PRE_SYNC, 53); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "ld"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 53); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 54: SD */ - std::tuple __sd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SD"); - - this->gen_sync(PRE_SYNC, 54); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sd"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 54); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 55: ADDIW */ - std::tuple __addiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDIW"); - - this->gen_sync(PRE_SYNC, 55); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateAdd( - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - 32, true), - this->gen_const(32U, imm)); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 55); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 56: SLLIW */ - std::tuple __slliw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLIW"); - - this->gen_sync(PRE_SYNC, 56); - - 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", "slliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* sh_val_val = this->builder.CreateShl( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, shamt)); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 56); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 57: SRLIW */ - std::tuple __srliw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLIW"); - - this->gen_sync(PRE_SYNC, 57); - - 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", "srliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* sh_val_val = this->builder.CreateLShr( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, shamt)); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 57); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 58: SRAIW */ - std::tuple __sraiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAIW"); - - this->gen_sync(PRE_SYNC, 58); - - 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", "sraiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* sh_val_val = this->builder.CreateAShr( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, shamt)); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 58); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 59: ADDW */ - std::tuple __addw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDW"); - - this->gen_sync(PRE_SYNC, 59); - - 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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("addw"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateAdd( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - )); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 59); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 60: SUBW */ - std::tuple __subw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SUBW"); - - this->gen_sync(PRE_SYNC, 60); - - 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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("subw"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateSub( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - )); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 60); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 61: SLLW */ - std::tuple __sllw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLW"); - - this->gen_sync(PRE_SYNC, 61); - - 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", "sllw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - uint32_t mask_val = 0x1f; - Value* count_val = this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, mask_val)); - Value* sh_val_val = this->builder.CreateShl( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - count_val); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 61); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 62: SRLW */ - std::tuple __srlw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLW"); - - this->gen_sync(PRE_SYNC, 62); - - 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", "srlw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - uint32_t mask_val = 0x1f; - Value* count_val = this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, mask_val)); - Value* sh_val_val = this->builder.CreateLShr( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - count_val); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 62); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 63: SRAW */ - std::tuple __sraw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAW"); - - this->gen_sync(PRE_SYNC, 63); - - 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", "sraw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - uint32_t mask_val = 0x1f; - Value* count_val = this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, mask_val)); - Value* sh_val_val = this->builder.CreateAShr( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - count_val); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 63); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 64: MUL */ - std::tuple __mul(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MUL"); - - this->gen_sync(PRE_SYNC, 64); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 128, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 128, - false)); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 64); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 65: MULH */ - std::tuple __mulh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULH"); - - this->gen_sync(PRE_SYNC, 65); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 128, - true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 128, - true)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(64U, 64)), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 65); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 66: MULHSU */ - std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULHSU"); - - this->gen_sync(PRE_SYNC, 66); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 128, - true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 128, - false)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(64U, 64)), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 66); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 67: MULHU */ - std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULHU"); - - this->gen_sync(PRE_SYNC, 67); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 128, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 128, - false)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(64U, 64)), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 67); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 68: DIV */ - std::tuple __div(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIV"); - - this->gen_sync(PRE_SYNC, 68); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(64U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint64_t M1_val = - 1; - uint8_t XLM1_val = 64 - 1; - uint64_t ONE_val = 1; - uint64_t MMIN_val = ONE_val << XLM1_val; - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateAnd( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_const(64U, MMIN_val)), - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs2 + traits::X0, 1), - this->gen_const(64U, M1_val))), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->gen_const(64U, MMIN_val); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateSDiv( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 2), - 64, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 2), - 64, true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp2_val = this->builder.CreateNeg(this->gen_const(64U, 1)); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 68); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 69: DIVU */ - std::tuple __divu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIVU"); - - this->gen_sync(PRE_SYNC, 69); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(64U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->builder.CreateUDiv( - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_reg_load(rs2 + traits::X0, 1)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateNeg(this->gen_const(64U, 1)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 69); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 70: REM */ - std::tuple __rem(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REM"); - - this->gen_sync(PRE_SYNC, 70); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(64U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint64_t M1_val = - 1; - uint32_t XLM1_val = 64 - 1; - uint64_t ONE_val = 1; - uint64_t MMIN_val = ONE_val << XLM1_val; - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateAnd( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_const(64U, MMIN_val)), - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs2 + traits::X0, 1), - this->gen_const(64U, M1_val))), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->gen_const(64U, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateSRem( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 2), - 64, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 2), - 64, true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp2_val = this->gen_reg_load(rs1 + traits::X0, 1); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 70); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 71: REMU */ - std::tuple __remu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REMU"); - - this->gen_sync(PRE_SYNC, 71); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(64U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->builder.CreateURem( - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_reg_load(rs2 + traits::X0, 1)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->gen_reg_load(rs1 + traits::X0, 1); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 71); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 72: MULW */ - std::tuple __mulw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULW"); - - this->gen_sync(PRE_SYNC, 72); - - 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", "mulw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateMul( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - )), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 72); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 73: DIVW */ - std::tuple __divw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIVW"); - - this->gen_sync(PRE_SYNC, 73); - - 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", "divw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(64U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << 31; - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateAnd( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 1), - this-> get_type(32) - ), - this->gen_const(32U, MMIN_val)), - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 1), - this-> get_type(32) - ), - this->gen_const(32U, M1_val))), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->builder.CreateShl( - this->builder.CreateNeg(this->gen_const(64U, 1)), - this->gen_const(64U, 31)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateSDiv( - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 2), - this-> get_type(32) - ), - 64, true), - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 2), - this-> get_type(32) - ), - 64, true)), - 64, - true); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp2_val = this->builder.CreateNeg(this->gen_const(64U, 1)); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 73); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 74: DIVUW */ - std::tuple __divuw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIVUW"); - - this->gen_sync(PRE_SYNC, 74); - - 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", "divuw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateUDiv( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 1), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 1), - this-> get_type(32) - )), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateNeg(this->gen_const(64U, 1)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 74); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 75: REMW */ - std::tuple __remw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REMW"); - - this->gen_sync(PRE_SYNC, 75); - - 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", "remw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(64U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << 31; - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateAnd( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 1), - this-> get_type(32) - ), - this->gen_const(32U, MMIN_val)), - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs2 + traits::X0, 1), - this->gen_const(64U, M1_val))), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->gen_const(64U, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateSRem( - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 2), - this-> get_type(32) - ), - 64, true), - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 2), - this-> get_type(32) - ), - 64, true)), - 64, - true); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp2_val = this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 1), - this-> get_type(32) - ), - 64, - true); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 75); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 76: REMUW */ - std::tuple __remuw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REMUW"); - - this->gen_sync(PRE_SYNC, 76); - - 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", "remuw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateURem( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 1), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 1), - this-> get_type(32) - )), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 1), - this-> get_type(32) - ), - 64, - true); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 76); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 77: LR.W */ - std::tuple __lr_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LR.W"); - - this->gen_sync(PRE_SYNC, 77); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* REStmp1_val = this->gen_ext( - this->builder.CreateNeg(this->gen_const(8U, 1)), - 32, - true); - this->gen_write_mem( - traits::RES, - offs_val, - this->builder.CreateZExtOrTrunc(REStmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 77); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 78: SC.W */ - std::tuple __sc_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SC.W"); - - this->gen_sync(PRE_SYNC, 78); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_read_mem(traits::RES, offs_val, 32/8); - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - res1_val, - this->gen_const(32U, 0)), - bb_then, - bbnext); - this->builder.SetInsertPoint(bb_then); - { - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 1); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - if(rd != 0){ - Value* Xtmp1_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - res1_val, - this->gen_ext( - this->gen_const(64U, 0), - 32, - false)), - this->gen_const(64U, 0), - this->gen_const(64U, 1), - 64); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 78); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 79: AMOSWAP.W */ - std::tuple __amoswap_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOSWAP.W"); - - this->gen_sync(PRE_SYNC, 79); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* MEMtmp1_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 79); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 80: AMOADD.W */ - std::tuple __amoadd_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOADD.W"); - - this->gen_sync(PRE_SYNC, 80); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateAdd( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 80); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 81: AMOXOR.W */ - std::tuple __amoxor_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOXOR.W"); - - this->gen_sync(PRE_SYNC, 81); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateXor( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 81); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 82: AMOAND.W */ - std::tuple __amoand_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOAND.W"); - - this->gen_sync(PRE_SYNC, 82); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateAnd( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 82); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 83: AMOOR.W */ - std::tuple __amoor_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOOR.W"); - - this->gen_sync(PRE_SYNC, 83); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateOr( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 83); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 84: AMOMIN.W */ - std::tuple __amomin_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMIN.W"); - - this->gen_sync(PRE_SYNC, 84); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGT, - this->gen_ext( - res1_val, - 64, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, true)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 64); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 84); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 85: AMOMAX.W */ - std::tuple __amomax_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAX.W"); - - this->gen_sync(PRE_SYNC, 85); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - res1_val, - 64, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, true)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 64); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 85); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 86: AMOMINU.W */ - std::tuple __amominu_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMINU.W"); - - this->gen_sync(PRE_SYNC, 86); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGT, - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 64); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 86); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 87: AMOMAXU.W */ - std::tuple __amomaxu_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAXU.W"); - - this->gen_sync(PRE_SYNC, 87); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 64); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 87); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 88: LR.D */ - std::tuple __lr_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LR.D"); - - this->gen_sync(PRE_SYNC, 88); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* REStmp1_val = this->gen_ext( - this->builder.CreateNeg(this->gen_const(8U, 1)), - 64, - true); - this->gen_write_mem( - traits::RES, - offs_val, - this->builder.CreateZExtOrTrunc(REStmp1_val,this->get_type(64))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 88); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 89: SC.D */ - std::tuple __sc_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SC.D"); - - this->gen_sync(PRE_SYNC, 89); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res_val = this->gen_read_mem(traits::RES, offs_val, 8/8); - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - res_val, - this->gen_const(64U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 1); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64)));if(rd != 0){ - Value* Xtmp1_val = this->gen_const(64U, 0); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - if(rd != 0){ - Value* Xtmp2_val = this->gen_const(64U, 1); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 89); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 90: AMOSWAP.D */ - std::tuple __amoswap_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOSWAP.D"); - - this->gen_sync(PRE_SYNC, 90); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* MEMtmp1_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 90); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 91: AMOADD.D */ - std::tuple __amoadd_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOADD.D"); - - this->gen_sync(PRE_SYNC, 91); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateAdd( - res_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 91); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 92: AMOXOR.D */ - std::tuple __amoxor_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOXOR.D"); - - this->gen_sync(PRE_SYNC, 92); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateXor( - res_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 92); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 93: AMOAND.D */ - std::tuple __amoand_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOAND.D"); - - this->gen_sync(PRE_SYNC, 93); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateAnd( - res_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 93); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 94: AMOOR.D */ - std::tuple __amoor_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOOR.D"); - - this->gen_sync(PRE_SYNC, 94); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateOr( - res_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 94); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 95: AMOMIN.D */ - std::tuple __amomin_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMIN.D"); - - this->gen_sync(PRE_SYNC, 95); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGT, - this->gen_ext( - res1_val, - 64, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, true)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 64); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 95); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 96: AMOMAX.D */ - std::tuple __amomax_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAX.D"); - - this->gen_sync(PRE_SYNC, 96); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - res_val, - 64, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, true)), - this->gen_reg_load(rs2 + traits::X0, 0), - res_val, - 64); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 96); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 97: AMOMINU.D */ - std::tuple __amominu_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMINU.D"); - - this->gen_sync(PRE_SYNC, 97); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGT, - res_val, - this->gen_reg_load(rs2 + traits::X0, 0)), - this->gen_reg_load(rs2 + traits::X0, 0), - res_val, - 64); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 97); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 98: AMOMAXU.D */ - std::tuple __amomaxu_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAXU.D"); - - this->gen_sync(PRE_SYNC, 98); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 64); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 98); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 99: FLW */ - std::tuple __flw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLW"); - - this->gen_sync(PRE_SYNC, 99); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}(x{rs1})", fmt::arg("mnemonic", "flw"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 99); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 100: FSW */ - std::tuple __fsw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSW"); - - this->gen_sync(PRE_SYNC, 100); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}(x{rs1})", fmt::arg("mnemonic", "fsw"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(32) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 100); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 101: FMADD.S */ - std::tuple __fmadd_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMADD.S"); - - this->gen_sync(PRE_SYNC, 101); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_reg_load(rs3 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs3 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - frs1_val, - frs2_val, - frs3_val, - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 101); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 102: FMSUB.S */ - std::tuple __fmsub_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMSUB.S"); - - this->gen_sync(PRE_SYNC, 102); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_reg_load(rs3 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs3 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - frs1_val, - frs2_val, - frs3_val, - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 102); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 103: FNMADD.S */ - std::tuple __fnmadd_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FNMADD.S"); - - this->gen_sync(PRE_SYNC, 103); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_reg_load(rs3 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs3 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - frs1_val, - frs2_val, - frs3_val, - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 103); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 104: FNMSUB.S */ - std::tuple __fnmsub_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FNMSUB.S"); - - this->gen_sync(PRE_SYNC, 104); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_reg_load(rs3 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs3 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ - frs1_val, - frs2_val, - frs3_val, - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 104); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 105: FADD.S */ - std::tuple __fadd_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FADD.S"); - - this->gen_sync(PRE_SYNC, 105); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fadd_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fadd_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 105); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 106: FSUB.S */ - std::tuple __fsub_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSUB.S"); - - this->gen_sync(PRE_SYNC, 106); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsub_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsub_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 106); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 107: FMUL.S */ - std::tuple __fmul_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMUL.S"); - - this->gen_sync(PRE_SYNC, 107); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmul_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmul_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 107); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 108: FDIV.S */ - std::tuple __fdiv_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FDIV.S"); - - this->gen_sync(PRE_SYNC, 108); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fdiv_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fdiv_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 108); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 109: FSQRT.S */ - std::tuple __fsqrt_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSQRT.S"); - - this->gen_sync(PRE_SYNC, 109); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsqrt_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsqrt_s"), std::vector{ - frs1_val, - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 109); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 110: FSGNJ.S */ - std::tuple __fsgnj_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJ.S"); - - this->gen_sync(PRE_SYNC, 110); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateOr( - this->builder.CreateAnd( - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_const(64U, 0x7fffffff)), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_const(64U, 0x80000000))); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateOr( - this->builder.CreateAnd( - frs1_val, - this->gen_const(32U, 0x7fffffff)), - this->builder.CreateAnd( - frs2_val, - this->gen_const(32U, 0x80000000))); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 110); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 111: FSGNJN.S */ - std::tuple __fsgnjn_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJN.S"); - - this->gen_sync(PRE_SYNC, 111); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateOr( - this->builder.CreateAnd( - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_const(64U, 0x7fffffff)), - this->builder.CreateAnd( - this->builder.CreateNot(this->gen_reg_load(rs2 + traits::F0, 0)), - this->gen_const(64U, 0x80000000))); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateOr( - this->builder.CreateAnd( - frs1_val, - this->gen_const(32U, 0x7fffffff)), - this->builder.CreateAnd( - this->builder.CreateNot(frs2_val), - this->gen_const(32U, 0x80000000))); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 111); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 112: FSGNJX.S */ - std::tuple __fsgnjx_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJX.S"); - - this->gen_sync(PRE_SYNC, 112); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateXor( - this->gen_reg_load(rs1 + traits::F0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_const(64U, 0x80000000))); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateXor( - frs1_val, - this->builder.CreateAnd( - frs2_val, - this->gen_const(32U, 0x80000000))); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 112); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 113: FMIN.S */ - std::tuple __fmin_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMIN.S"); - - this->gen_sync(PRE_SYNC, 113); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 113); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 114: FMAX.S */ - std::tuple __fmax_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMAX.S"); - - this->gen_sync(PRE_SYNC, 114); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 114); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 115: FCVT.W.S */ - std::tuple __fcvt_w_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.W.S"); - - this->gen_sync(PRE_SYNC, 115); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_const(8U, rm) - }), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - frs1_val, - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_const(8U, rm) - }), - 64, - true); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 115); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 116: FCVT.WU.S */ - std::tuple __fcvt_wu_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.WU.S"); - - this->gen_sync(PRE_SYNC, 116); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_const(8U, rm) - }), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - frs1_val, - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_const(8U, rm) - }), - 64, - true); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 116); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 117: FEQ.S */ - std::tuple __feq_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FEQ.S"); - - this->gen_sync(PRE_SYNC, 117); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }), - 64, - false); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 117); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 118: FLT.S */ - std::tuple __flt_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLT.S"); - - this->gen_sync(PRE_SYNC, 118); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false) - }), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false) - }), - 64, - false); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - Value* Xtmp2_val = this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false) - }); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 118); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 119: FLE.S */ - std::tuple __fle_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLE.S"); - - this->gen_sync(PRE_SYNC, 119); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_reg_load(rs2 + traits::F0, 0), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }); - Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs2 + traits::F0, 0) - }); - Value* Xtmp1_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ - frs1_val, - frs2_val, - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }), - 64, - false); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 119); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 120: FCLASS.S */ - std::tuple __fclass_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCLASS.S"); - - this->gen_sync(PRE_SYNC, 120); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->builder.CreateCall(this->mod->getFunction("fclass_s"), std::vector{ - this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 120); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 121: FCVT.S.W */ - std::tuple __fcvt_s_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.S.W"); - - this->gen_sync(PRE_SYNC, 121); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_const(8U, rm) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_const(8U, rm) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 121); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 122: FCVT.S.WU */ - std::tuple __fcvt_s_wu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.S.WU"); - - this->gen_sync(PRE_SYNC, 122); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_const(8U, rm) - }); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_const(8U, rm) - }); - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 122); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 123: FMV.X.W */ - std::tuple __fmv_x_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMV.X.W"); - - this->gen_sync(PRE_SYNC, 123); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fmv.x.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(32) - ), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 123); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 124: FMV.W.X */ - std::tuple __fmv_w_x(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMV.W.X"); - - this->gen_sync(PRE_SYNC, 124); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fmv.w.x"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 124); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 125: FCVT.L.S */ - std::tuple __fcvt_l_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.L.S"); - - this->gen_sync(PRE_SYNC, 125); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.l.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_32_64"), std::vector{ - this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_const(8U, rm) - }); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 125); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 126: FCVT.LU.S */ - std::tuple __fcvt_lu_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.LU.S"); - - this->gen_sync(PRE_SYNC, 126); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} x{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.lu.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_32_64"), std::vector{ - this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0) - }), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_const(8U, rm) - }); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 126); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 127: FCVT.S.L */ - std::tuple __fcvt_s_l(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.S.L"); - - this->gen_sync(PRE_SYNC, 127); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, x{rs1}", fmt::arg("mnemonic", "fcvt.s.l"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_64_32"), std::vector{ - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_const(8U, rm) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 127); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 128: FCVT.S.LU */ - std::tuple __fcvt_s_lu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.S.LU"); - - this->gen_sync(PRE_SYNC, 128); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, x{rs1}", fmt::arg("mnemonic", "fcvt.s.lu"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_64_32"), std::vector{ - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_const(8U, rm) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 128); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 129: FLD */ - std::tuple __fld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLD"); - - this->gen_sync(PRE_SYNC, 129); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}({rs1})", fmt::arg("mnemonic", "fld"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 64/8); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 129); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 130: FSD */ - std::tuple __fsd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSD"); - - this->gen_sync(PRE_SYNC, 130); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}({rs1})", fmt::arg("mnemonic", "fsd"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 130); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 131: FMADD.D */ - std::tuple __fmadd_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMADD.D"); - - this->gen_sync(PRE_SYNC, 131); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs3 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 64, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 131); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 132: FMSUB.D */ - std::tuple __fmsub_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMSUB.D"); - - this->gen_sync(PRE_SYNC, 132); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs3 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 132); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 133: FNMADD.D */ - std::tuple __fnmadd_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FNMADD.D"); - - this->gen_sync(PRE_SYNC, 133); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs3 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 133); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 134: FNMSUB.D */ - std::tuple __fnmsub_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FNMSUB.D"); - - this->gen_sync(PRE_SYNC, 134); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs3 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 134); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 135: FADD.D */ - std::tuple __fadd_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FADD.D"); - - this->gen_sync(PRE_SYNC, 135); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fadd_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 135); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 136: FSUB.D */ - std::tuple __fsub_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSUB.D"); - - this->gen_sync(PRE_SYNC, 136); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsub_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 136); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 137: FMUL.D */ - std::tuple __fmul_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMUL.D"); - - this->gen_sync(PRE_SYNC, 137); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmul_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 137); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 138: FDIV.D */ - std::tuple __fdiv_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FDIV.D"); - - this->gen_sync(PRE_SYNC, 138); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fdiv_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 138); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 139: FSQRT.D */ - std::tuple __fsqrt_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSQRT.D"); - - this->gen_sync(PRE_SYNC, 139); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsqrt_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, rm), - this->gen_const(8U, 7)), - this->gen_const(8U, rm), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 139); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 140: FSGNJ.D */ - std::tuple __fsgnj_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJ.D"); - - this->gen_sync(PRE_SYNC, 140); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - Value* res_val = this->builder.CreateOr( - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_const(64U, MSK2_val)), - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_const(64U, MSK1_val))); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 140); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 141: FSGNJN.D */ - std::tuple __fsgnjn_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJN.D"); - - this->gen_sync(PRE_SYNC, 141); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - Value* res_val = this->builder.CreateOr( - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_const(64U, MSK2_val)), - this->builder.CreateAnd( - this->builder.CreateNot(this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - )), - this->gen_const(64U, MSK1_val))); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 141); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 142: FSGNJX.D */ - std::tuple __fsgnjx_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSGNJX.D"); - - this->gen_sync(PRE_SYNC, 142); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - Value* res_val = this->builder.CreateXor( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_const(64U, MSK1_val))); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 142); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 143: FMIN.D */ - std::tuple __fmin_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMIN.D"); - - this->gen_sync(PRE_SYNC, 143); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 143); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 144: FMAX.D */ - std::tuple __fmax_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMAX.D"); - - this->gen_sync(PRE_SYNC, 144); - - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 144); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 145: FCVT.S.D */ - std::tuple __fcvt_s_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.S.D"); - - this->gen_sync(PRE_SYNC, 145); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.s.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fconv_d2f"), std::vector{ - this->gen_reg_load(rs1 + traits::F0, 0), - this->gen_const(8U, rm) - }); - uint64_t upper_val = - 1; - Value* Ftmp0_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 145); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 146: FCVT.D.S */ - std::tuple __fcvt_d_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.D.S"); - - this->gen_sync(PRE_SYNC, 146); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.d.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fconv_f2d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(32) - ), - this->gen_const(8U, rm) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 146); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 147: FEQ.D */ - std::tuple __feq_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FEQ.D"); - - this->gen_sync(PRE_SYNC, 147); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 147); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 148: FLT.D */ - std::tuple __flt_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLT.D"); - - this->gen_sync(PRE_SYNC, 148); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false) - }), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 148); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 149: FLE.D */ - std::tuple __fle_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLE.D"); - - this->gen_sync(PRE_SYNC, 149); - - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcmp_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 149); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 150: FCLASS.D */ - std::tuple __fclass_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCLASS.D"); - - this->gen_sync(PRE_SYNC, 150); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->builder.CreateCall(this->mod->getFunction("fclass_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 150); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 151: FCVT.W.D */ - std::tuple __fcvt_w_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.W.D"); - - this->gen_sync(PRE_SYNC, 151); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_64_32"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_const(8U, rm) - }), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 151); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 152: FCVT.WU.D */ - std::tuple __fcvt_wu_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.WU.D"); - - this->gen_sync(PRE_SYNC, 152); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_64_32"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_const(8U, rm) - }), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 152); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 153: FCVT.D.W */ - std::tuple __fcvt_d_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.D.W"); - - this->gen_sync(PRE_SYNC, 153); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_32_64"), std::vector{ - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - 64, - true), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_const(8U, rm) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 153); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 154: FCVT.D.WU */ - std::tuple __fcvt_d_wu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.D.WU"); - - this->gen_sync(PRE_SYNC, 154); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_32_64"), std::vector{ - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - 64, - false), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_const(8U, rm) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 154); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 155: FCVT.L.D */ - std::tuple __fcvt_l_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.L.D"); - - this->gen_sync(PRE_SYNC, 155); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.l.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_const(8U, rm) - }), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 155); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 156: FCVT.LU.D */ - std::tuple __fcvt_lu_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.LU.D"); - - this->gen_sync(PRE_SYNC, 156); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.lu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_const(8U, rm) - }), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ - }); - Value* FCSR_val = this->builder.CreateAdd( - this->builder.CreateAnd( - this->gen_reg_load(traits::FCSR, 0), - this->builder.CreateNot(this->gen_const(32U, 0x1f))), - flags_val); - this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 156); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 157: FCVT.D.L */ - std::tuple __fcvt_d_l(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.D.L"); - - this->gen_sync(PRE_SYNC, 157); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.l"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_d"), std::vector{ - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - true), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_const(8U, rm) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 157); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 158: FCVT.D.LU */ - std::tuple __fcvt_d_lu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.D.LU"); - - this->gen_sync(PRE_SYNC, 158); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.lu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_d"), std::vector{ - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - false), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_const(8U, rm) - }); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 158); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 159: FMV.X.D */ - std::tuple __fmv_x_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMV.X.D"); - - this->gen_sync(PRE_SYNC, 159); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fmv.x.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->gen_reg_load(rs1 + traits::F0, 0), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 159); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 160: FMV.D.X */ - std::tuple __fmv_d_x(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMV.D.X"); - - this->gen_sync(PRE_SYNC, 160); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fmv.d.x"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* Ftmp0_val = this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - false); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 160); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 161: C.ADDI4SPN */ - std::tuple __c_addi4spn(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI4SPN"); - - this->gen_sync(PRE_SYNC, 161); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - if(imm == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(64U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 161); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 162: C.LW */ - std::tuple __c_lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LW"); - - this->gen_sync(PRE_SYNC, 162); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 162); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 163: C.SW */ - std::tuple __c_sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SW"); - - this->gen_sync(PRE_SYNC, 163); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + 8 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 163); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 164: C.ADDI */ - std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI"); - - this->gen_sync(PRE_SYNC, 164); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 164); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 165: C.NOP */ - std::tuple __c_nop(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.NOP"); - - this->gen_sync(PRE_SYNC, 165); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("c.nop"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - /* TODO: describe operations for C.NOP ! */ - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 165); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 166: C.JAL */ - std::tuple __c_jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JAL"); - - this->gen_sync(PRE_SYNC, 166); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 2)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(1 + traits::X0), false); - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 166); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 167: C.LI */ - std::tuple __c_li(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LI"); - - this->gen_sync(PRE_SYNC, 167); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - if(rd == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->gen_const(64U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 167); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 168: C.LUI */ - std::tuple __c_lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LUI"); - - this->gen_sync(PRE_SYNC, 168); - - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - if(rd == 0){ - this->gen_raise_trap(0, 2); - } - if(imm == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->gen_const(64U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 168); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 169: C.ADDI16SP */ - std::tuple __c_addi16sp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI16SP"); - - this->gen_sync(PRE_SYNC, 169); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(2 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(2 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 169); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 170: C.SRLI */ - std::tuple __c_srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRLI"); - - this->gen_sync(PRE_SYNC, 170); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(64U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 170); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 171: C.SRAI */ - std::tuple __c_srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRAI"); - - this->gen_sync(PRE_SYNC, 171); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(64U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 171); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 172: C.ANDI */ - std::tuple __c_andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ANDI"); - - this->gen_sync(PRE_SYNC, 172); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 172); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 173: C.SUB */ - std::tuple __c_sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SUB"); - - this->gen_sync(PRE_SYNC, 173); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 173); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 174: C.XOR */ - std::tuple __c_xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.XOR"); - - this->gen_sync(PRE_SYNC, 174); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 174); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 175: C.OR */ - std::tuple __c_or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.OR"); - - this->gen_sync(PRE_SYNC, 175); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 175); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 176: C.AND */ - std::tuple __c_and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.AND"); - - this->gen_sync(PRE_SYNC, 176); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 176); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 177: C.J */ - std::tuple __c_j(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.J"); - - this->gen_sync(PRE_SYNC, 177); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 177); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 178: C.BEQZ */ - std::tuple __c_beqz(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.BEQZ"); - - this->gen_sync(PRE_SYNC, 178); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(64U, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 2)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 178); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 179: C.BNEZ */ - std::tuple __c_bnez(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.BNEZ"); - - this->gen_sync(PRE_SYNC, 179); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(64U, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 2)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 179); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 180: C.SLLI */ - std::tuple __c_slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SLLI"); - - this->gen_sync(PRE_SYNC, 180); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - if(rs1 == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(64U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 180); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 181: C.LWSP */ - std::tuple __c_lwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LWSP"); - - this->gen_sync(PRE_SYNC, 181); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 181); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 182: C.MV */ - std::tuple __c_mv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.MV"); - - this->gen_sync(PRE_SYNC, 182); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 182); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 183: C.JR */ - std::tuple __c_jr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JR"); - - this->gen_sync(PRE_SYNC, 183); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 183); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 184: C.ADD */ - std::tuple __c_add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADD"); - - this->gen_sync(PRE_SYNC, 184); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(rd + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 184); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 185: C.JALR */ - std::tuple __c_jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JALR"); - - this->gen_sync(PRE_SYNC, 185); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 2)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(1 + traits::X0), false); - Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 185); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 186: C.EBREAK */ - std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.EBREAK"); - - this->gen_sync(PRE_SYNC, 186); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("c.ebreak"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 186); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 187: C.SWSP */ - std::tuple __c_swsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SWSP"); - - this->gen_sync(PRE_SYNC, 187); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 187); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 188: DII */ - std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DII"); - - this->gen_sync(PRE_SYNC, 188); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("dii"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - this->gen_raise_trap(0, 2); - this->gen_sync(POST_SYNC, 188); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 189: C.LD */ - std::tuple __c_ld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LD"); - - this->gen_sync(PRE_SYNC, 189); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm},({rs1})", fmt::arg("mnemonic", "c.ld"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 189); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 190: C.SD */ - std::tuple __c_sd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SD"); - - this->gen_sync(PRE_SYNC, 190); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm},({rs1})", fmt::arg("mnemonic", "c.sd"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + 8 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 190); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 191: C.SUBW */ - std::tuple __c_subw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SUBW"); - - this->gen_sync(PRE_SYNC, 191); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* res_val = this->builder.CreateSub( - this->builder.CreateTrunc( - this->gen_reg_load(rd + 8 + traits::X0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + 8 + traits::X0, 0), - this-> get_type(32) - )); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 191); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 192: C.ADDW */ - std::tuple __c_addw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDW"); - - this->gen_sync(PRE_SYNC, 192); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* res_val = this->builder.CreateAdd( - this->builder.CreateTrunc( - this->gen_reg_load(rd + 8 + traits::X0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + 8 + traits::X0, 0), - this-> get_type(32) - )); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 192); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 193: C.ADDIW */ - std::tuple __c_addiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDIW"); - - this->gen_sync(PRE_SYNC, 193); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addiw"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - if(rs1 != 0){ - Value* res_val = this->builder.CreateAdd( - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - 32, true), - this->gen_const(32U, imm)); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 193); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 194: C.LDSP */ - std::tuple __c_ldsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LDSP"); - - this->gen_sync(PRE_SYNC, 194); - - uint16_t uimm = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm}(sp)", fmt::arg("mnemonic", "c.ldsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(64U, uimm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 194); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 195: C.SDSP */ - std::tuple __c_sdsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SDSP"); - - this->gen_sync(PRE_SYNC, 195); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint16_t uimm = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm}(sp)", fmt::arg("mnemonic", "c.sdsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 195); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 196: C.FLW */ - std::tuple __c_flw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FLW"); - - this->gen_sync(PRE_SYNC, 196); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rd}), {uimm}({rs1})", fmt::arg("mnemonic", "c.flw"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + 8 + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + 8 + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 196); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 197: C.FSW */ - std::tuple __c_fsw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FSW"); - - this->gen_sync(PRE_SYNC, 197); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rs2}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fsw"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + 8 + traits::F0, 0), - this-> get_type(32) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 197); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 198: C.FLWSP */ - std::tuple __c_flwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FLWSP"); - - this->gen_sync(PRE_SYNC, 198); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {uimm}(x2)", fmt::arg("mnemonic", "c.flwsp"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 32)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 198); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 199: C.FSWSP */ - std::tuple __c_fswsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FSWSP"); - - this->gen_sync(PRE_SYNC, 199); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {uimm}(x2), ", fmt::arg("mnemonic", "c.fswsp"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(32) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 199); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 200: C.FLD */ - std::tuple __c_fld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FLD"); - - this->gen_sync(PRE_SYNC, 200); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rd}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fld"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 64/8); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + 8 + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + 8 + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 200); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 201: C.FSD */ - std::tuple __c_fsd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FSD"); - - this->gen_sync(PRE_SYNC, 201); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rs2}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fsd"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + 8 + traits::F0, 0), - this-> get_type(64) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 201); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 202: C.FLDSP */ - std::tuple __c_fldsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FLDSP"); - - this->gen_sync(PRE_SYNC, 202); - - uint16_t uimm = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {uimm}(x2)", fmt::arg("mnemonic", "c.fldsp"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 64/8); - if(64 == 64){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); - } else { - uint64_t upper_val = - 1; - Value* Ftmp1_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, upper_val), - this->gen_const(64U, 64)), - this->gen_ext( - res_val, - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 202); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 203: C.FSDSP */ - std::tuple __c_fsdsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.FSDSP"); - - this->gen_sync(PRE_SYNC, 203); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint16_t uimm = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {uimm}(x2), ", fmt::arg("mnemonic", "c.fsdsp"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(64U, uimm)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::F0, 0), - this-> get_type(64) - ); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 203); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { - this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); - this->builder.CreateStore( - this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits::ICOUNT), true), - this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - this->gen_raise_trap(0, 2); // illegal instruction trap - this->gen_sync(iss::POST_SYNC, instr_descr.size()); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } -}; - -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 -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, this_block); -} - -template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { - this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); -} - -template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { - auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); - this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); -} - -template void vm_impl::gen_leave_trap(unsigned lvl) { - std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) }; - this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); - auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); -} - -template void vm_impl::gen_wait(unsigned type) { - std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) }; - this->builder.CreateCall(this->mod->getFunction("wait"), args); -} - -template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { - this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), - get_reg_ptr(traits::LAST_BRANCH), false); - std::vector args{this->core_ptr, this->adj_to64(trap_state_val), - this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; - this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); - auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateRet(trap_addr_val); -} - -template inline void vm_impl::gen_trap_check(BasicBlock *bb) { - auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, v, - ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, this->trap_blk, 1); -} - -} // namespace rv64gc - -template <> -std::unique_ptr create(arch::rv64gc *core, unsigned short port, bool dump) { - auto ret = new rv64gc::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} // namespace llvm -} // namespace iss diff --git a/src/vm/llvm/vm_rv64i.cpp b/src/vm/llvm/vm_tgf01.cpp similarity index 75% rename from src/vm/llvm/vm_rv64i.cpp rename to src/vm/llvm/vm_tgf01.cpp index fdc3227..a69e455 100644 --- a/src/vm/llvm/vm_rv64i.cpp +++ b/src/vm/llvm/vm_tgf01.cpp @@ -30,8 +30,8 @@ * *******************************************************************************/ -#include -#include +#include +#include #include #include #include @@ -52,7 +52,7 @@ namespace fp_impl { void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); } -namespace rv64i { +namespace tgf01 { using namespace ::llvm; using namespace iss::arch; using namespace iss::debugger; @@ -187,7 +187,7 @@ private: compile_func op; }; - const std::array instr_descr = {{ + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, @@ -238,11 +238,11 @@ private: /* instruction ANDI */ {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, /* instruction SLLI */ - {32, 0b00000000000000000001000000010011, 0b11111100000000000111000001111111, &this_class::__slli}, + {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srli}, + {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srai}, + {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, /* instruction ADD */ {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, /* instruction SUB */ @@ -293,30 +293,6 @@ private: {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, /* instruction CSRRCI */ {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction LWU */ - {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, - /* instruction LD */ - {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, &this_class::__ld}, - /* instruction SD */ - {32, 0b00000000000000000011000000100011, 0b00000000000000000111000001111111, &this_class::__sd}, - /* instruction ADDIW */ - {32, 0b00000000000000000000000000011011, 0b00000000000000000111000001111111, &this_class::__addiw}, - /* instruction SLLIW */ - {32, 0b00000000000000000001000000011011, 0b11111110000000000111000001111111, &this_class::__slliw}, - /* instruction SRLIW */ - {32, 0b00000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__srliw}, - /* instruction SRAIW */ - {32, 0b01000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__sraiw}, - /* instruction ADDW */ - {32, 0b00000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__addw}, - /* instruction SUBW */ - {32, 0b01000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__subw}, - /* instruction SLLW */ - {32, 0b00000000000000000001000000111011, 0b11111110000000000111000001111111, &this_class::__sllw}, - /* instruction SRLW */ - {32, 0b00000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__srlw}, - /* instruction SRAW */ - {32, 0b01000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__sraw}, }}; /* instruction definitions */ @@ -341,11 +317,11 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ - Value* Xtmp0_val = this->gen_const(64U, imm); + Value* Xtmp0_val = this->gen_const(32U, imm); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -376,15 +352,15 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ Value* Xtmp0_val = this->builder.CreateAdd( this->gen_ext( cur_pc_val, - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -415,22 +391,22 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ Value* Xtmp0_val = this->builder.CreateAdd( cur_pc_val, - this->gen_const(64U, 4)); + this->gen_const(32U, 4)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } Value* PC_val = this->builder.CreateAdd( this->gen_ext( cur_pc_val, - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); this->gen_sync(POST_SYNC, 2); this->gen_trap_check(this->leave_blk); @@ -459,17 +435,17 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* new_pc_val = this->builder.CreateAdd( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); Value* align_val = this->builder.CreateAnd( new_pc_val, - this->gen_const(64U, 0x2)); + this->gen_const(32U, 0x2)); { BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); @@ -478,7 +454,7 @@ private: this->gen_cond_branch(this->builder.CreateICmp( ICmpInst::ICMP_NE, align_val, - this->gen_const(64U, 0)), + this->gen_const(32U, 0)), bb_then, bb_else); this->builder.SetInsertPoint(bb_then); @@ -491,12 +467,12 @@ private: if(rd != 0){ Value* Xtmp0_val = this->builder.CreateAdd( cur_pc_val, - this->gen_const(64U, 4)); + this->gen_const(32U, 4)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } Value* PC_val = this->builder.CreateAnd( new_pc_val, - this->builder.CreateNot(this->gen_const(64U, 0x1))); + this->builder.CreateNot(this->gen_const(32U, 0x1))); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } @@ -531,7 +507,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* PC_val = this->gen_choose( @@ -542,14 +518,14 @@ private: this->builder.CreateAdd( this->gen_ext( cur_pc_val, - 64, true), - this->gen_const(64U, imm)), + 32, true), + this->gen_const(32U, imm)), this->builder.CreateAdd( cur_pc_val, - this->gen_const(64U, 4)), - 64); + this->gen_const(32U, 4)), + 32); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); this->gen_sync(POST_SYNC, 4); this->gen_trap_check(this->leave_blk); @@ -578,7 +554,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* PC_val = this->gen_choose( @@ -589,14 +565,14 @@ private: this->builder.CreateAdd( this->gen_ext( cur_pc_val, - 64, true), - this->gen_const(64U, imm)), + 32, true), + this->gen_const(32U, imm)), this->builder.CreateAdd( cur_pc_val, - this->gen_const(64U, 4)), - 64); + this->gen_const(32U, 4)), + 32); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); this->gen_sync(POST_SYNC, 5); this->gen_trap_check(this->leave_blk); @@ -625,7 +601,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* PC_val = this->gen_choose( @@ -633,21 +609,21 @@ private: ICmpInst::ICMP_SLT, this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), + 32, true), this->gen_ext( this->gen_reg_load(rs2 + traits::X0, 0), - 64, true)), + 32, true)), this->builder.CreateAdd( this->gen_ext( cur_pc_val, - 64, true), - this->gen_const(64U, imm)), + 32, true), + this->gen_const(32U, imm)), this->builder.CreateAdd( cur_pc_val, - this->gen_const(64U, 4)), - 64); + this->gen_const(32U, 4)), + 32); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); this->gen_sync(POST_SYNC, 6); this->gen_trap_check(this->leave_blk); @@ -676,7 +652,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* PC_val = this->gen_choose( @@ -684,21 +660,21 @@ private: ICmpInst::ICMP_SGE, this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), + 32, true), this->gen_ext( this->gen_reg_load(rs2 + traits::X0, 0), - 64, true)), + 32, true)), this->builder.CreateAdd( this->gen_ext( cur_pc_val, - 64, true), - this->gen_const(64U, imm)), + 32, true), + this->gen_const(32U, imm)), this->builder.CreateAdd( cur_pc_val, - this->gen_const(64U, 4)), - 64); + this->gen_const(32U, 4)), + 32); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); this->gen_sync(POST_SYNC, 7); this->gen_trap_check(this->leave_blk); @@ -727,7 +703,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* PC_val = this->gen_choose( @@ -738,14 +714,14 @@ private: this->builder.CreateAdd( this->gen_ext( cur_pc_val, - 64, true), - this->gen_const(64U, imm)), + 32, true), + this->gen_const(32U, imm)), this->builder.CreateAdd( cur_pc_val, - this->gen_const(64U, 4)), - 64); + this->gen_const(32U, 4)), + 32); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); this->gen_sync(POST_SYNC, 8); this->gen_trap_check(this->leave_blk); @@ -774,7 +750,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* PC_val = this->gen_choose( @@ -785,14 +761,14 @@ private: this->builder.CreateAdd( this->gen_ext( cur_pc_val, - 64, true), - this->gen_const(64U, imm)), + 32, true), + this->gen_const(32U, imm)), this->builder.CreateAdd( cur_pc_val, - this->gen_const(64U, 4)), - 64); + this->gen_const(32U, 4)), + 32); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); this->gen_sync(POST_SYNC, 9); this->gen_trap_check(this->leave_blk); @@ -821,18 +797,18 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* offs_val = this->builder.CreateAdd( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); if(rd != 0){ Value* Xtmp0_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 8/8), - 64, + 32, true); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } @@ -865,18 +841,18 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* offs_val = this->builder.CreateAdd( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); if(rd != 0){ Value* Xtmp0_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 16/8), - 64, + 32, true); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } @@ -909,18 +885,18 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* offs_val = this->builder.CreateAdd( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); if(rd != 0){ Value* Xtmp0_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, + 32, true); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } @@ -953,18 +929,18 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* offs_val = this->builder.CreateAdd( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); if(rd != 0){ Value* Xtmp0_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 8/8), - 64, + 32, false); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } @@ -997,18 +973,18 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* offs_val = this->builder.CreateAdd( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); if(rd != 0){ Value* Xtmp0_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 16/8), - 64, + 32, false); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } @@ -1041,14 +1017,14 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* offs_val = this->builder.CreateAdd( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); this->gen_write_mem( traits::MEM, @@ -1083,14 +1059,14 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* offs_val = this->builder.CreateAdd( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); this->gen_write_mem( traits::MEM, @@ -1125,14 +1101,14 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* offs_val = this->builder.CreateAdd( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); this->gen_write_mem( traits::MEM, @@ -1167,15 +1143,15 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ Value* Xtmp0_val = this->builder.CreateAdd( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1207,7 +1183,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ @@ -1216,11 +1192,11 @@ private: ICmpInst::ICMP_SLT, this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); + 32, true), + this->gen_const(32U, imm)), + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1252,19 +1228,19 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - int64_t full_imm_val = imm; + int32_t full_imm_val = imm; if(rd != 0){ Value* Xtmp0_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(64U, full_imm_val)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); + this->gen_const(32U, full_imm_val)), + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1296,15 +1272,15 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ Value* Xtmp0_val = this->builder.CreateXor( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1336,15 +1312,15 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ Value* Xtmp0_val = this->builder.CreateOr( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1376,15 +1352,15 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ Value* Xtmp0_val = this->builder.CreateAnd( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); + 32, true), + this->gen_const(32U, imm)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1402,7 +1378,7 @@ private: uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,6>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( @@ -1416,14 +1392,18 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(64U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + if(shamt > 31){ + this->gen_raise_trap(0, 0); + } else { + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateShl( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_const(32U, shamt)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(POST_SYNC, 24); @@ -1440,7 +1420,7 @@ private: uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,6>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( @@ -1454,14 +1434,18 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(64U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + if(shamt > 31){ + this->gen_raise_trap(0, 0); + } else { + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateLShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_const(32U, shamt)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(POST_SYNC, 25); @@ -1478,7 +1462,7 @@ private: uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,6>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( @@ -1492,14 +1476,18 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(64U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + if(shamt > 31){ + this->gen_raise_trap(0, 0); + } else { + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_const(32U, shamt)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(POST_SYNC, 26); @@ -1530,7 +1518,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ @@ -1568,7 +1556,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ @@ -1606,7 +1594,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ @@ -1615,8 +1603,8 @@ private: this->builder.CreateAnd( this->gen_reg_load(rs2 + traits::X0, 0), this->builder.CreateSub( - this->gen_const(64U, 64), - this->gen_const(64U, 1)))); + this->gen_const(32U, 32), + this->gen_const(32U, 1)))); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1648,7 +1636,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ @@ -1657,13 +1645,13 @@ private: ICmpInst::ICMP_SLT, this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), + 32, true), this->gen_ext( this->gen_reg_load(rs2 + traits::X0, 0), - 64, true)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); + 32, true)), + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1695,7 +1683,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ @@ -1704,15 +1692,15 @@ private: ICmpInst::ICMP_ULT, this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 64, + 32, false), this->gen_ext( this->gen_reg_load(rs2 + traits::X0, 0), - 64, + 32, false)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1744,7 +1732,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ @@ -1782,7 +1770,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ @@ -1791,8 +1779,8 @@ private: this->builder.CreateAnd( this->gen_reg_load(rs2 + traits::X0, 0), this->builder.CreateSub( - this->gen_const(64U, 64), - this->gen_const(64U, 1)))); + this->gen_const(32U, 32), + this->gen_const(32U, 1)))); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1824,7 +1812,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ @@ -1833,8 +1821,8 @@ private: this->builder.CreateAnd( this->gen_reg_load(rs2 + traits::X0, 0), this->builder.CreateSub( - this->gen_const(64U, 64), - this->gen_const(64U, 1)))); + this->gen_const(32U, 32), + this->gen_const(32U, 1)))); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1866,7 +1854,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ @@ -1904,7 +1892,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ @@ -1940,18 +1928,18 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* FENCEtmp0_val = this->builder.CreateOr( this->builder.CreateShl( - this->gen_const(64U, pred), - this->gen_const(64U, 4)), - this->gen_const(64U, succ)); + this->gen_const(32U, pred), + this->gen_const(32U, 4)), + this->gen_const(32U, succ)); this->gen_write_mem( traits::FENCE, this->gen_const(64U, 0), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(POST_SYNC, 37); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -1978,14 +1966,14 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* FENCEtmp0_val = this->gen_const(64U, imm); + Value* FENCEtmp0_val = this->gen_const(32U, imm); this->gen_write_mem( traits::FENCE, this->gen_const(64U, 1), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(POST_SYNC, 38); @@ -2009,7 +1997,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; this->gen_raise_trap(0, 11); @@ -2034,7 +2022,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; this->gen_raise_trap(0, 3); @@ -2059,7 +2047,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; this->gen_leave_trap(0); @@ -2084,7 +2072,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; this->gen_leave_trap(1); @@ -2109,7 +2097,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; this->gen_leave_trap(3); @@ -2134,7 +2122,7 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; this->gen_wait(1); @@ -2163,19 +2151,19 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* FENCEtmp0_val = this->gen_const(64U, rs1); + Value* FENCEtmp0_val = this->gen_const(32U, rs1); this->gen_write_mem( traits::FENCE, this->gen_const(64U, 2), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); - Value* FENCEtmp1_val = this->gen_const(64U, rs2); + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); + Value* FENCEtmp1_val = this->gen_const(32U, rs2); this->gen_write_mem( traits::FENCE, this->gen_const(64U, 3), - this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(64))); + this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(POST_SYNC, 45); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -2205,17 +2193,17 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); if(rd != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); Value* CSRtmp0_val = rs_val_val; this->gen_write_mem( traits::CSR, this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(64))); + this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); Value* Xtmp1_val = csr_val_val; this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); } else { @@ -2223,7 +2211,7 @@ private: this->gen_write_mem( traits::CSR, this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(64))); + this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(POST_SYNC, 46); @@ -2254,10 +2242,10 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); if(rd != 0){ Value* Xtmp0_val = xrd_val; @@ -2270,7 +2258,7 @@ private: this->gen_write_mem( traits::CSR, this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(POST_SYNC, 47); @@ -2301,10 +2289,10 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); if(rd != 0){ Value* Xtmp0_val = xrd_val; @@ -2317,7 +2305,7 @@ private: this->gen_write_mem( traits::CSR, this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(POST_SYNC, 48); @@ -2348,21 +2336,21 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; if(rd != 0){ - Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } Value* CSRtmp1_val = this->gen_ext( - this->gen_const(64U, zimm), - 64, + this->gen_const(32U, zimm), + 32, false); this->gen_write_mem( traits::CSR, this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(POST_SYNC, 49); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -2392,21 +2380,21 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); if(zimm != 0){ Value* CSRtmp0_val = this->builder.CreateOr( res_val, this->gen_ext( - this->gen_const(64U, zimm), - 64, + this->gen_const(32U, zimm), + 32, false)); this->gen_write_mem( traits::CSR, this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(64))); + this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); } if(rd != 0){ Value* Xtmp1_val = res_val; @@ -2441,10 +2429,10 @@ private: this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } - Value* cur_pc_val = this->gen_const(64, pc.val); + Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); if(rd != 0){ Value* Xtmp0_val = res_val; this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); @@ -2453,13 +2441,13 @@ private: Value* CSRtmp1_val = this->builder.CreateAnd( res_val, this->builder.CreateNot(this->gen_ext( - this->gen_const(64U, zimm), - 64, + this->gen_const(32U, zimm), + 32, false))); this->gen_write_mem( traits::CSR, this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(POST_SYNC, 51); @@ -2468,564 +2456,6 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 52: LWU */ - std::tuple __lwu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LWU"); - - this->gen_sync(PRE_SYNC, 52); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lwu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 52); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 53: LD */ - std::tuple __ld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LD"); - - this->gen_sync(PRE_SYNC, 53); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "ld"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 53); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 54: SD */ - std::tuple __sd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SD"); - - this->gen_sync(PRE_SYNC, 54); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sd"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, true), - this->gen_const(64U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 54); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 55: ADDIW */ - std::tuple __addiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDIW"); - - this->gen_sync(PRE_SYNC, 55); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateAdd( - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - 32, true), - this->gen_const(32U, imm)); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 55); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 56: SLLIW */ - std::tuple __slliw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLIW"); - - this->gen_sync(PRE_SYNC, 56); - - 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", "slliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* sh_val_val = this->builder.CreateShl( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, shamt)); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 56); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 57: SRLIW */ - std::tuple __srliw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLIW"); - - this->gen_sync(PRE_SYNC, 57); - - 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", "srliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* sh_val_val = this->builder.CreateLShr( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, shamt)); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 57); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 58: SRAIW */ - std::tuple __sraiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAIW"); - - this->gen_sync(PRE_SYNC, 58); - - 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", "sraiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* sh_val_val = this->builder.CreateAShr( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, shamt)); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 58); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 59: ADDW */ - std::tuple __addw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDW"); - - this->gen_sync(PRE_SYNC, 59); - - 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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("addw"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateAdd( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - )); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 59); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 60: SUBW */ - std::tuple __subw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SUBW"); - - this->gen_sync(PRE_SYNC, 60); - - 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 */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("subw"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateSub( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - )); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 60); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 61: SLLW */ - std::tuple __sllw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLW"); - - this->gen_sync(PRE_SYNC, 61); - - 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", "sllw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - uint32_t mask_val = 0x1f; - Value* count_val = this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, mask_val)); - Value* sh_val_val = this->builder.CreateShl( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - count_val); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 61); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 62: SRLW */ - std::tuple __srlw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLW"); - - this->gen_sync(PRE_SYNC, 62); - - 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", "srlw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - uint32_t mask_val = 0x1f; - Value* count_val = this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, mask_val)); - Value* sh_val_val = this->builder.CreateLShr( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - count_val); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 62); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 63: SRAW */ - std::tuple __sraw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAW"); - - this->gen_sync(PRE_SYNC, 63); - - 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", "sraw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(rd != 0){ - uint32_t mask_val = 0x1f; - Value* count_val = this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(rs2 + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, mask_val)); - Value* sh_val_val = this->builder.CreateAShr( - this->builder.CreateTrunc( - this->gen_reg_load(rs1 + traits::X0, 0), - this-> get_type(32) - ), - count_val); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 63); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - /**************************************************************************** * end opcode definitions ****************************************************************************/ @@ -3140,11 +2570,11 @@ template inline void vm_impl::gen_trap_check(BasicBlock *b bb, this->trap_blk, 1); } -} // namespace rv64i +} // namespace tgf01 template <> -std::unique_ptr create(arch::rv64i *core, unsigned short port, bool dump) { - auto ret = new rv64i::vm_impl(*core, dump); +std::unique_ptr create(arch::tgf01 *core, unsigned short port, bool dump) { + auto ret = new tgf01::vm_impl(*core, dump); if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } diff --git a/src/vm/llvm/vm_rv32imac.cpp b/src/vm/llvm/vm_tgf02.cpp similarity index 86% rename from src/vm/llvm/vm_rv32imac.cpp rename to src/vm/llvm/vm_tgf02.cpp index 3b17cde..f23fa2d 100644 --- a/src/vm/llvm/vm_rv32imac.cpp +++ b/src/vm/llvm/vm_tgf02.cpp @@ -30,8 +30,8 @@ * *******************************************************************************/ -#include -#include +#include +#include #include #include #include @@ -52,7 +52,7 @@ namespace fp_impl { void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); } -namespace rv32imac { +namespace tgf02 { using namespace ::llvm; using namespace iss::arch; using namespace iss::debugger; @@ -187,7 +187,7 @@ private: compile_func op; }; - const std::array instr_descr = {{ + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, @@ -309,28 +309,6 @@ private: {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, /* instruction REMU */ {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction LR.W */ - {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lr_w}, - /* instruction SC.W */ - {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__sc_w}, - /* instruction AMOSWAP.W */ - {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_w}, - /* instruction AMOADD.W */ - {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_w}, - /* instruction AMOXOR.W */ - {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_w}, - /* instruction AMOAND.W */ - {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_w}, - /* instruction AMOOR.W */ - {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_w}, - /* instruction AMOMIN.W */ - {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_w}, - /* instruction AMOMAX.W */ - {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_w}, - /* instruction AMOMINU.W */ - {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_w}, - /* instruction AMOMAXU.W */ - {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_w}, /* instruction C.ADDI4SPN */ {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, /* instruction C.LW */ @@ -2553,11 +2531,11 @@ private: Value* res_val = this->builder.CreateMul( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 128, + 64, false), this->gen_ext( this->gen_reg_load(rs2 + traits::X0, 0), - 128, + 64, false)); Value* Xtmp0_val = this->gen_ext( res_val, @@ -2601,11 +2579,11 @@ private: Value* res_val = this->builder.CreateMul( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 128, + 64, true), this->gen_ext( this->gen_reg_load(rs2 + traits::X0, 0), - 128, + 64, true)); Value* Xtmp0_val = this->gen_ext( this->builder.CreateLShr( @@ -2651,11 +2629,11 @@ private: Value* res_val = this->builder.CreateMul( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 128, + 64, true), this->gen_ext( this->gen_reg_load(rs2 + traits::X0, 0), - 128, + 64, false)); Value* Xtmp0_val = this->gen_ext( this->builder.CreateLShr( @@ -2701,11 +2679,11 @@ private: Value* res_val = this->builder.CreateMul( this->gen_ext( this->gen_reg_load(rs1 + traits::X0, 0), - 128, + 64, false), this->gen_ext( this->gen_reg_load(rs2 + traits::X0, 0), - 128, + 64, false)); Value* Xtmp0_val = this->gen_ext( this->builder.CreateLShr( @@ -3044,615 +3022,11 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 60: LR.W */ - std::tuple __lr_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LR.W"); - - this->gen_sync(PRE_SYNC, 60); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - Value* REStmp1_val = this->gen_ext( - this->builder.CreateNeg(this->gen_const(8U, 1)), - 32, - true); - this->gen_write_mem( - traits::RES, - offs_val, - this->builder.CreateZExtOrTrunc(REStmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 60); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 61: SC.W */ - std::tuple __sc_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SC.W"); - - this->gen_sync(PRE_SYNC, 61); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_read_mem(traits::RES, offs_val, 32/8); - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - res1_val, - this->gen_const(32U, 0)), - bb_then, - bbnext); - this->builder.SetInsertPoint(bb_then); - { - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 1); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - if(rd != 0){ - Value* Xtmp1_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - res1_val, - this->gen_ext( - this->gen_const(32U, 0), - 32, - false)), - this->gen_const(32U, 0), - this->gen_const(32U, 1), - 32); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 61); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 62: AMOSWAP.W */ - std::tuple __amoswap_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOSWAP.W"); - - this->gen_sync(PRE_SYNC, 62); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* MEMtmp1_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 62); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 63: AMOADD.W */ - std::tuple __amoadd_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOADD.W"); - - this->gen_sync(PRE_SYNC, 63); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateAdd( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 63); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 64: AMOXOR.W */ - std::tuple __amoxor_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOXOR.W"); - - this->gen_sync(PRE_SYNC, 64); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateXor( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 64); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 65: AMOAND.W */ - std::tuple __amoand_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOAND.W"); - - this->gen_sync(PRE_SYNC, 65); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateAnd( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 65); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 66: AMOOR.W */ - std::tuple __amoor_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOOR.W"); - - this->gen_sync(PRE_SYNC, 66); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->builder.CreateOr( - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 66); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 67: AMOMIN.W */ - std::tuple __amomin_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMIN.W"); - - this->gen_sync(PRE_SYNC, 67); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGT, - this->gen_ext( - res1_val, - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 32); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 67); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 68: AMOMAX.W */ - std::tuple __amomax_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAX.W"); - - this->gen_sync(PRE_SYNC, 68); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - res1_val, - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 32); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 68); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 69: AMOMINU.W */ - std::tuple __amominu_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMINU.W"); - - this->gen_sync(PRE_SYNC, 69); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGT, - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 32); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 69); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 70: AMOMAXU.W */ - std::tuple __amomaxu_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAXU.W"); - - this->gen_sync(PRE_SYNC, 70); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - res1_val, - this->gen_reg_load(rs2 + traits::X0, 0)), - this->gen_reg_load(rs2 + traits::X0, 0), - res1_val, - 32); - Value* MEMtmp1_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 70); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 71: C.ADDI4SPN */ + /* instruction 60: C.ADDI4SPN */ std::tuple __c_addi4spn(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.ADDI4SPN"); - this->gen_sync(PRE_SYNC, 71); + this->gen_sync(PRE_SYNC, 60); uint8_t rd = ((bit_sub<2,3>(instr))); uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); @@ -3680,17 +3054,17 @@ private: this->gen_const(32U, imm)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 71); + this->gen_sync(POST_SYNC, 60); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 72: C.LW */ + /* instruction 61: C.LW */ std::tuple __c_lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.LW"); - this->gen_sync(PRE_SYNC, 72); + this->gen_sync(PRE_SYNC, 61); uint8_t rd = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); @@ -3720,17 +3094,17 @@ private: true); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 72); + this->gen_sync(POST_SYNC, 61); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 73: C.SW */ + /* instruction 62: C.SW */ std::tuple __c_sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.SW"); - this->gen_sync(PRE_SYNC, 73); + this->gen_sync(PRE_SYNC, 62); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); @@ -3760,17 +3134,17 @@ private: offs_val, this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 73); + this->gen_sync(POST_SYNC, 62); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 74: C.ADDI */ + /* instruction 63: C.ADDI */ std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.ADDI"); - this->gen_sync(PRE_SYNC, 74); + this->gen_sync(PRE_SYNC, 63); int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,5>(instr))); @@ -3797,17 +3171,17 @@ private: this->gen_const(32U, imm)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 74); + this->gen_sync(POST_SYNC, 63); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 75: C.NOP */ + /* instruction 64: C.NOP */ std::tuple __c_nop(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.NOP"); - this->gen_sync(PRE_SYNC, 75); + this->gen_sync(PRE_SYNC, 64); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3824,17 +3198,17 @@ private: /* TODO: describe operations for C.NOP ! */ this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 75); + this->gen_sync(POST_SYNC, 64); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 76: C.JAL */ + /* instruction 65: C.JAL */ std::tuple __c_jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.JAL"); - this->gen_sync(PRE_SYNC, 76); + this->gen_sync(PRE_SYNC, 65); int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ @@ -3865,16 +3239,16 @@ private: this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 76); + this->gen_sync(POST_SYNC, 65); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 77: C.LI */ + /* instruction 66: C.LI */ std::tuple __c_li(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.LI"); - this->gen_sync(PRE_SYNC, 77); + this->gen_sync(PRE_SYNC, 66); int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -3900,17 +3274,17 @@ private: Value* Xtmp0_val = this->gen_const(32U, imm); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 77); + this->gen_sync(POST_SYNC, 66); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 78: C.LUI */ + /* instruction 67: C.LUI */ std::tuple __c_lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.LUI"); - this->gen_sync(PRE_SYNC, 78); + this->gen_sync(PRE_SYNC, 67); int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -3939,17 +3313,17 @@ private: Value* Xtmp0_val = this->gen_const(32U, imm); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 78); + this->gen_sync(POST_SYNC, 67); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 79: C.ADDI16SP */ + /* instruction 68: C.ADDI16SP */ std::tuple __c_addi16sp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.ADDI16SP"); - this->gen_sync(PRE_SYNC, 79); + this->gen_sync(PRE_SYNC, 68); int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ @@ -3975,17 +3349,17 @@ private: this->gen_const(32U, imm)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(2 + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 79); + this->gen_sync(POST_SYNC, 68); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 80: C.SRLI */ + /* instruction 69: C.SRLI */ std::tuple __c_srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.SRLI"); - this->gen_sync(PRE_SYNC, 80); + this->gen_sync(PRE_SYNC, 69); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -4011,17 +3385,17 @@ private: this->gen_const(32U, shamt)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 80); + this->gen_sync(POST_SYNC, 69); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 81: C.SRAI */ + /* instruction 70: C.SRAI */ std::tuple __c_srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.SRAI"); - this->gen_sync(PRE_SYNC, 81); + this->gen_sync(PRE_SYNC, 70); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -4047,17 +3421,17 @@ private: this->gen_const(32U, shamt)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 81); + this->gen_sync(POST_SYNC, 70); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 82: C.ANDI */ + /* instruction 71: C.ANDI */ std::tuple __c_andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.ANDI"); - this->gen_sync(PRE_SYNC, 82); + this->gen_sync(PRE_SYNC, 71); int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -4085,17 +3459,17 @@ private: this->gen_const(32U, imm)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 82); + this->gen_sync(POST_SYNC, 71); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 83: C.SUB */ + /* instruction 72: C.SUB */ std::tuple __c_sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.SUB"); - this->gen_sync(PRE_SYNC, 83); + this->gen_sync(PRE_SYNC, 72); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -4121,17 +3495,17 @@ private: this->gen_reg_load(rs2 + 8 + traits::X0, 0)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 83); + this->gen_sync(POST_SYNC, 72); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 84: C.XOR */ + /* instruction 73: C.XOR */ std::tuple __c_xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.XOR"); - this->gen_sync(PRE_SYNC, 84); + this->gen_sync(PRE_SYNC, 73); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -4157,17 +3531,17 @@ private: this->gen_reg_load(rs2 + 8 + traits::X0, 0)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 84); + this->gen_sync(POST_SYNC, 73); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 85: C.OR */ + /* instruction 74: C.OR */ std::tuple __c_or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.OR"); - this->gen_sync(PRE_SYNC, 85); + this->gen_sync(PRE_SYNC, 74); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -4193,17 +3567,17 @@ private: this->gen_reg_load(rs2 + 8 + traits::X0, 0)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 85); + this->gen_sync(POST_SYNC, 74); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 86: C.AND */ + /* instruction 75: C.AND */ std::tuple __c_and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.AND"); - this->gen_sync(PRE_SYNC, 86); + this->gen_sync(PRE_SYNC, 75); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -4229,17 +3603,17 @@ private: this->gen_reg_load(rs2 + 8 + traits::X0, 0)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 86); + this->gen_sync(POST_SYNC, 75); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 87: C.J */ + /* instruction 76: C.J */ std::tuple __c_j(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.J"); - this->gen_sync(PRE_SYNC, 87); + this->gen_sync(PRE_SYNC, 76); int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ @@ -4266,16 +3640,16 @@ private: this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 87); + this->gen_sync(POST_SYNC, 76); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 88: C.BEQZ */ + /* instruction 77: C.BEQZ */ std::tuple __c_beqz(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.BEQZ"); - this->gen_sync(PRE_SYNC, 88); + this->gen_sync(PRE_SYNC, 77); int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -4312,16 +3686,16 @@ private: this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 88); + this->gen_sync(POST_SYNC, 77); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 89: C.BNEZ */ + /* instruction 78: C.BNEZ */ std::tuple __c_bnez(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.BNEZ"); - this->gen_sync(PRE_SYNC, 89); + this->gen_sync(PRE_SYNC, 78); int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -4358,16 +3732,16 @@ private: this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 89); + this->gen_sync(POST_SYNC, 78); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 90: C.SLLI */ + /* instruction 79: C.SLLI */ std::tuple __c_slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.SLLI"); - this->gen_sync(PRE_SYNC, 90); + this->gen_sync(PRE_SYNC, 79); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,5>(instr))); @@ -4395,17 +3769,17 @@ private: this->gen_const(32U, shamt)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 90); + this->gen_sync(POST_SYNC, 79); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 91: C.LWSP */ + /* instruction 80: C.LWSP */ std::tuple __c_lwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.LWSP"); - this->gen_sync(PRE_SYNC, 91); + this->gen_sync(PRE_SYNC, 80); uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -4434,17 +3808,17 @@ private: true); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 91); + this->gen_sync(POST_SYNC, 80); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 92: C.MV */ + /* instruction 81: C.MV */ std::tuple __c_mv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.MV"); - this->gen_sync(PRE_SYNC, 92); + this->gen_sync(PRE_SYNC, 81); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -4467,17 +3841,17 @@ private: Value* Xtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 92); + this->gen_sync(POST_SYNC, 81); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 93: C.JR */ + /* instruction 82: C.JR */ std::tuple __c_jr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.JR"); - this->gen_sync(PRE_SYNC, 93); + this->gen_sync(PRE_SYNC, 82); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -4499,16 +3873,16 @@ private: Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 93); + this->gen_sync(POST_SYNC, 82); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 94: C.ADD */ + /* instruction 83: C.ADD */ std::tuple __c_add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.ADD"); - this->gen_sync(PRE_SYNC, 94); + this->gen_sync(PRE_SYNC, 83); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -4533,17 +3907,17 @@ private: this->gen_reg_load(rs2 + traits::X0, 0)); this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 94); + this->gen_sync(POST_SYNC, 83); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 95: C.JALR */ + /* instruction 84: C.JALR */ std::tuple __c_jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.JALR"); - this->gen_sync(PRE_SYNC, 95); + this->gen_sync(PRE_SYNC, 84); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -4569,16 +3943,16 @@ private: Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 95); + this->gen_sync(POST_SYNC, 84); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 96: C.EBREAK */ + /* instruction 85: C.EBREAK */ std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.EBREAK"); - this->gen_sync(PRE_SYNC, 96); + this->gen_sync(PRE_SYNC, 85); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -4594,16 +3968,16 @@ private: pc=pc+2; this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 96); + this->gen_sync(POST_SYNC, 85); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 97: C.SWSP */ + /* instruction 86: C.SWSP */ std::tuple __c_swsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("C.SWSP"); - this->gen_sync(PRE_SYNC, 97); + this->gen_sync(PRE_SYNC, 86); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); @@ -4632,17 +4006,17 @@ private: offs_val, this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 97); + this->gen_sync(POST_SYNC, 86); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ this->gen_trap_check(bb); return std::make_tuple(CONT, bb); } - /* instruction 98: DII */ + /* instruction 87: DII */ std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("DII"); - this->gen_sync(PRE_SYNC, 98); + this->gen_sync(PRE_SYNC, 87); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -4658,7 +4032,7 @@ private: pc=pc+2; this->gen_raise_trap(0, 2); - this->gen_sync(POST_SYNC, 98); + this->gen_sync(POST_SYNC, 87); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } @@ -4777,11 +4151,11 @@ template inline void vm_impl::gen_trap_check(BasicBlock *b bb, this->trap_blk, 1); } -} // namespace rv32imac +} // namespace tgf02 template <> -std::unique_ptr create(arch::rv32imac *core, unsigned short port, bool dump) { - auto ret = new rv32imac::vm_impl(*core, dump); +std::unique_ptr create(arch::tgf02 *core, unsigned short port, bool dump) { + auto ret = new tgf02::vm_impl(*core, dump); if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } diff --git a/src/vm/tcc/vm_mnrv32.cpp b/src/vm/tcc/vm_mnrv32.cpp deleted file mode 100644 index 42eb30f..0000000 --- a/src/vm/tcc/vm_mnrv32.cpp +++ /dev/null @@ -1,2916 +0,0 @@ -/******************************************************************************* - * Copyright (C) 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 -#include -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace tcc { -namespace mnrv32 { -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::tcc::vm_base { -public: - using super = typename iss::tcc::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 tu_builder = typename super::tu_builder; - - 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 (vm_base::tgt_adapter == nullptr) - vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm_base::tgt_adapter; - } - -protected: - using vm_base::get_reg_ptr; - - using this_class = vm_impl; - using compile_ret_t = std::tuple; - using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&); - - inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - void setup_module(std::string m) override { - super::setup_module(m); - } - - compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, tu_builder&) override; - - void gen_trap_behavior(tu_builder& tu) override; - - void gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(tu_builder& tu, unsigned lvl); - - void gen_wait(tu_builder& tu, unsigned type); - - inline void gen_trap_check(tu_builder& tu) { - tu("if(*trap_state!=0) goto trap_entry;"); - } - - inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) { - switch(reg_num){ - case traits::NEXT_PC: - tu("*next_pc = {:#x};", pc.val); - break; - case traits::PC: - tu("*pc = {:#x};", pc.val); - break; - default: - if(!tu.defined_regs[reg_num]){ - tu("reg_t* reg{:02d} = (reg_t*){:#x};", reg_num, reinterpret_cast(get_reg_ptr(reg_num))); - tu.defined_regs[reg_num]=true; - } - tu("*reg{:02d} = {:#x};", reg_num, pc.val); - } - } - - // 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; - } - -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, encoding '.........................0110111' */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC, encoding '.........................0010111' */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL, encoding '.........................1101111' */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction BEQ, encoding '.................000.....1100011' */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE, encoding '.................001.....1100011' */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT, encoding '.................100.....1100011' */ - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE, encoding '.................101.....1100011' */ - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU, encoding '.................110.....1100011' */ - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU, encoding '.................111.....1100011' */ - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB, encoding '.................000.....0000011' */ - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH, encoding '.................001.....0000011' */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW, encoding '.................010.....0000011' */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU, encoding '.................100.....0000011' */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU, encoding '.................101.....0000011' */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB, encoding '.................000.....0100011' */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH, encoding '.................001.....0100011' */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW, encoding '.................010.....0100011' */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI, encoding '.................000.....0010011' */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI, encoding '.................010.....0010011' */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU, encoding '.................011.....0010011' */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI, encoding '.................100.....0010011' */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI, encoding '.................110.....0010011' */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI, encoding '.................111.....0010011' */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI, encoding '0000000..........001.....0010011' */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI, encoding '0000000..........101.....0010011' */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI, encoding '0100000..........101.....0010011' */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD, encoding '0000000..........000.....0110011' */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB, encoding '0100000..........000.....0110011' */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL, encoding '0000000..........001.....0110011' */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT, encoding '0000000..........010.....0110011' */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU, encoding '0000000..........011.....0110011' */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR, encoding '0000000..........100.....0110011' */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL, encoding '0000000..........101.....0110011' */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA, encoding '0100000..........101.....0110011' */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR, encoding '0000000..........110.....0110011' */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND, encoding '0000000..........111.....0110011' */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE, encoding '0000.............000.....0001111' */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I, encoding '.................001.....0001111' */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL, encoding '00000000000000000000000001110011' */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK, encoding '00000000000100000000000001110011' */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET, encoding '00000000001000000000000001110011' */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET, encoding '00010000001000000000000001110011' */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET, encoding '00110000001000000000000001110011' */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI, encoding '00010000010100000000000001110011' */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA, encoding '0001001..........000000001110011' */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW, encoding '.................001.....1110011' */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS, encoding '.................010.....1110011' */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC, encoding '.................011.....1110011' */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI, encoding '.................101.....1110011' */ - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI, encoding '.................110.....1110011' */ - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI, encoding '.................111.....1110011' */ - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction JALR, encoding '.................000.....1100111' */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction C.ADDI4SPN, encoding '000...........00' */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW, encoding '010...........00' */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW, encoding '110...........00' */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI, encoding '000...........01' */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP, encoding '0000000000000001' */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL, encoding '001...........01' */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI, encoding '010...........01' */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI, encoding '011...........01' */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP, encoding '011.00010.....01' */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI, encoding '100000........01' */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI, encoding '100001........01' */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI, encoding '100.10........01' */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB, encoding '100011...00...01' */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR, encoding '100011...01...01' */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR, encoding '100011...10...01' */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND, encoding '100011...11...01' */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J, encoding '101...........01' */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ, encoding '110...........01' */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ, encoding '111...........01' */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI, encoding '0000..........10' */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP, encoding '010...........10' */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV, encoding '1000..........10' */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR, encoding '1000.....0000010' */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD, encoding '1001..........10' */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR, encoding '1001.....0000010' */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK, encoding '1001000000000010' */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP, encoding '110...........10' */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII, encoding '0000000000000000' */ - {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 0); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.constant(imm, 32U), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 0); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 1: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AUIPC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 1); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 1); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 2: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 2); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 2); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 3: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BEQ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 3); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 3); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 4: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BNE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 4); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 4); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 5: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 5); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 5); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 6: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 6); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SGE, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 6); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 7: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 7); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 7); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 8: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGEU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 8); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_UGE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 8); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 9: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 9); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 9); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 10: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 10); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 10); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 11: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 11); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 11); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 12: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LBU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 12); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 12); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 13: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 13); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 13); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 14: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 14); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 8)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 14); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 15: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 15); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 16)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 15); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 16: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 16); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 16); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 17: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 17); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 17); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 18: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 18); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 18); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 19: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTIU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 19); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - int32_t full_imm_val = imm; - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.constant(full_imm_val, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 19); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 20: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 20); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 20); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 21: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 21); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 21); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 22: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 22); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 22); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 23: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 23); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 23); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 24: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 24); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 25: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 25); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 26: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 26); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 26); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 27: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.sub( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 27); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 28: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 28); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 29: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 29); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 30: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, - true)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 30); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 31: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 31); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 32: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 32); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 33: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 33); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 34: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 34); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 35: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 35); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 36: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 36); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(0, 64U), - tu.trunc(tu.l_or( - tu.shl( - tu.constant(pred, 32U), - tu.constant(4, 32U)), - tu.constant(succ, 32U)), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 36); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 37: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_I_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 37); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence_i"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(1, 64U), - tu.trunc(tu.constant(imm, 32U), 32)); - tu.close_scope(); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 37); - gen_trap_check(tu); - return std::make_tuple(FLUSH); - } - - /* instruction 38: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ECALL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 38); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ecall"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 11); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 38); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 39: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 39); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ebreak"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 39); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 40: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("URET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 40); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "uret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 0); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 40); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 41: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 41); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 1); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 41); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 42: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 42); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "mret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 42); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 43: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("WFI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 43); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "wfi"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_wait(tu, 1); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 43); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 44: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SFENCE_VMA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 44); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sfence.vma"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(2, 64U), - tu.trunc(tu.constant(rs1, 32U), 32)); - tu.write_mem( - traits::FENCE, - tu.constant(3, 64U), - tu.trunc(tu.constant(rs2, 32U), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 44); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 45: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 45); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto rs_val_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - auto csr_val_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); - tu.store(csr_val_val, rd + traits::X0); - } else { - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 45); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 46: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRS_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - xrd_val, - xrs1_val), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 46); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 47: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - xrd_val, - tu.l_not(xrs1_val)), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 47); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 48: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRWI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 48); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), rd + traits::X0); - } - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.ext( - tu.constant(zimm, 32U), - 32, - true), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 48); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 49: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRSI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - res_val, - tu.ext( - tu.constant(zimm, 32U), - 32, - true)), 32)); - } - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 49); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 50: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRCI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - res_val, - tu.l_not(tu.ext( - tu.constant(zimm, 32U), - 32, - true))), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 50); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 51: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 51); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto new_pc_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.l_and( - new_pc_val, - tu.l_not(tu.constant(0x1, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 51); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 52: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI4SPN_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 52); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(imm, 32U)), rd + 8 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 52); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 53: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 53); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + 8 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 53); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 54: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 54); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + 8 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 54); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 55: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 55); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rs1 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 55); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 56: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_NOP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 56); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.nop"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.close_scope(); - /* TODO: describe operations for C.NOP ! */ - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 56); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 57: C.JAL */ - compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 57); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - cur_pc_val, - tu.constant(2, 32U)), 1 + traits::X0); - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 57); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 58: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 58); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.constant(imm, 32U), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 58); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 59: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 59); - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); - } - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.constant(imm, 32U), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 59); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 60: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI16SP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 60); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(2 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 2 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 60); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 61: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 61); - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.lshr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 32U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 61); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 62: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 62); - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.ashr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 32U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 62); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 63: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 63); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.l_and( - tu.ext( - tu.load(rs1_idx_val + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 63); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 64: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 64); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.sub( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 64); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 65: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 65); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_xor( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 65); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 66: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 66); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_or( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 66); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 67: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 67); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_and( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 67); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 68: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_J_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 68); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 68); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 69: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BEQZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 69); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 32U)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(2, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 69); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 70: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BNEZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 70); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 32U)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(2, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 70); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 71: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 71); - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rs1 == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rs1 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 71); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 72: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 72); - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 72); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 73: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_MV_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 73); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.load(rs2 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 73); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 74: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 74); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 32); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 74); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 75: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 75); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.load(rd + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 75); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 76: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 76); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - cur_pc_val, - tu.constant(2, 32U)), 1 + traits::X0); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 32); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 76); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 77: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 77); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.ebreak"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 77); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 78: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 78); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 78); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 79: DII */ - compile_ret_t __dii(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DII_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 79); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "dii"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 2); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 79); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, tu_builder& tu) { - vm_impl::gen_sync(tu, iss::PRE_SYNC, instr_descr.size()); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - gen_raise_trap(tu, 0, 2); // illegal instruction trap - vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size()); - vm_impl::gen_trap_check(tu); - return BRANCH; - } -}; - -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 -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, tu); -} - -template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { - tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); -} - -template void vm_impl::gen_leave_trap(tu_builder& tu, unsigned lvl) { - tu("leave_trap(core_ptr, {});", lvl); - tu.store(tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN),traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); -} - -template void vm_impl::gen_wait(tu_builder& tu, unsigned type) { -} - -template void vm_impl::gen_trap_behavior(tu_builder& tu) { - tu("trap_entry:"); - tu("enter_trap(core_ptr, *trap_state, *pc);"); - tu.store(tu.constant(std::numeric_limits::max(),32),traits::LAST_BRANCH); - tu("return *next_pc;"); -} - -} // namespace mnrv32 - -template <> -std::unique_ptr create(arch::mnrv32 *core, unsigned short port, bool dump) { - auto ret = new mnrv32::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} -} // namespace iss diff --git a/src/vm/tcc/vm_rv32gc.cpp b/src/vm/tcc/vm_rv32gc.cpp deleted file mode 100644 index 35eef1f..0000000 --- a/src/vm/tcc/vm_rv32gc.cpp +++ /dev/null @@ -1,7240 +0,0 @@ -/******************************************************************************* - * Copyright (C) 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 -#include -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace tcc { -namespace rv32gc { -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::tcc::vm_base { -public: - using super = typename iss::tcc::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 tu_builder = typename super::tu_builder; - - 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 (vm_base::tgt_adapter == nullptr) - vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm_base::tgt_adapter; - } - -protected: - using vm_base::get_reg_ptr; - - using this_class = vm_impl; - using compile_ret_t = std::tuple; - using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&); - - inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - void setup_module(std::string m) override { - super::setup_module(m); - } - - compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, tu_builder&) override; - - void gen_trap_behavior(tu_builder& tu) override; - - void gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(tu_builder& tu, unsigned lvl); - - void gen_wait(tu_builder& tu, unsigned type); - - inline void gen_trap_check(tu_builder& tu) { - tu("if(*trap_state!=0) goto trap_entry;"); - } - - inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) { - switch(reg_num){ - case traits::NEXT_PC: - tu("*next_pc = {:#x};", pc.val); - break; - case traits::PC: - tu("*pc = {:#x};", pc.val); - break; - default: - if(!tu.defined_regs[reg_num]){ - tu("reg_t* reg{:02d} = (reg_t*){:#x};", reg_num, reinterpret_cast(get_reg_ptr(reg_num))); - tu.defined_regs[reg_num]=true; - } - tu("*reg{:02d} = {:#x};", reg_num, pc.val); - } - } - - // 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; - } - -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 MUL, encoding '0000001..........000.....0110011' */ - {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH, encoding '0000001..........001.....0110011' */ - {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU, encoding '0000001..........010.....0110011' */ - {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU, encoding '0000001..........011.....0110011' */ - {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV, encoding '0000001..........100.....0110011' */ - {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU, encoding '0000001..........101.....0110011' */ - {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM, encoding '0000001..........110.....0110011' */ - {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU, encoding '0000001..........111.....0110011' */ - {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction LR.W, encoding '00010..00000.....010.....0101111' */ - {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lr_w}, - /* instruction SC.W, encoding '00011............010.....0101111' */ - {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__sc_w}, - /* instruction AMOSWAP.W, encoding '00001............010.....0101111' */ - {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_w}, - /* instruction AMOADD.W, encoding '00000............010.....0101111' */ - {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_w}, - /* instruction AMOXOR.W, encoding '00100............010.....0101111' */ - {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_w}, - /* instruction AMOAND.W, encoding '01100............010.....0101111' */ - {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_w}, - /* instruction AMOOR.W, encoding '01000............010.....0101111' */ - {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_w}, - /* instruction AMOMIN.W, encoding '10000............010.....0101111' */ - {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_w}, - /* instruction AMOMAX.W, encoding '10100............010.....0101111' */ - {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_w}, - /* instruction AMOMINU.W, encoding '11000............010.....0101111' */ - {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_w}, - /* instruction AMOMAXU.W, encoding '11100............010.....0101111' */ - {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_w}, - /* instruction LUI, encoding '.........................0110111' */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC, encoding '.........................0010111' */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL, encoding '.........................1101111' */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction BEQ, encoding '.................000.....1100011' */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE, encoding '.................001.....1100011' */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT, encoding '.................100.....1100011' */ - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE, encoding '.................101.....1100011' */ - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU, encoding '.................110.....1100011' */ - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU, encoding '.................111.....1100011' */ - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB, encoding '.................000.....0000011' */ - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH, encoding '.................001.....0000011' */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW, encoding '.................010.....0000011' */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU, encoding '.................100.....0000011' */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU, encoding '.................101.....0000011' */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB, encoding '.................000.....0100011' */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH, encoding '.................001.....0100011' */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW, encoding '.................010.....0100011' */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI, encoding '.................000.....0010011' */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI, encoding '.................010.....0010011' */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU, encoding '.................011.....0010011' */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI, encoding '.................100.....0010011' */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI, encoding '.................110.....0010011' */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI, encoding '.................111.....0010011' */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI, encoding '0000000..........001.....0010011' */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI, encoding '0000000..........101.....0010011' */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI, encoding '0100000..........101.....0010011' */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD, encoding '0000000..........000.....0110011' */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB, encoding '0100000..........000.....0110011' */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL, encoding '0000000..........001.....0110011' */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT, encoding '0000000..........010.....0110011' */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU, encoding '0000000..........011.....0110011' */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR, encoding '0000000..........100.....0110011' */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL, encoding '0000000..........101.....0110011' */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA, encoding '0100000..........101.....0110011' */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR, encoding '0000000..........110.....0110011' */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND, encoding '0000000..........111.....0110011' */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE, encoding '0000.............000.....0001111' */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I, encoding '.................001.....0001111' */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL, encoding '00000000000000000000000001110011' */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK, encoding '00000000000100000000000001110011' */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET, encoding '00000000001000000000000001110011' */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET, encoding '00010000001000000000000001110011' */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET, encoding '00110000001000000000000001110011' */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI, encoding '00010000010100000000000001110011' */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA, encoding '0001001..........000000001110011' */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW, encoding '.................001.....1110011' */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS, encoding '.................010.....1110011' */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC, encoding '.................011.....1110011' */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI, encoding '.................101.....1110011' */ - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI, encoding '.................110.....1110011' */ - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI, encoding '.................111.....1110011' */ - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction FLW, encoding '.................010.....0000111' */ - {32, 0b00000000000000000010000000000111, 0b00000000000000000111000001111111, &this_class::__flw}, - /* instruction FSW, encoding '.................010.....0100111' */ - {32, 0b00000000000000000010000000100111, 0b00000000000000000111000001111111, &this_class::__fsw}, - /* instruction FMADD.S, encoding '.....00..................1000011' */ - {32, 0b00000000000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_s}, - /* instruction FMSUB.S, encoding '.....00..................1000111' */ - {32, 0b00000000000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_s}, - /* instruction FNMADD.S, encoding '.....00..................1001111' */ - {32, 0b00000000000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_s}, - /* instruction FNMSUB.S, encoding '.....00..................1001011' */ - {32, 0b00000000000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_s}, - /* instruction FADD.S, encoding '0000000..................1010011' */ - {32, 0b00000000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_s}, - /* instruction FSUB.S, encoding '0000100..................1010011' */ - {32, 0b00001000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_s}, - /* instruction FMUL.S, encoding '0001000..................1010011' */ - {32, 0b00010000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_s}, - /* instruction FDIV.S, encoding '0001100..................1010011' */ - {32, 0b00011000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_s}, - /* instruction FSQRT.S, encoding '010110000000.............1010011' */ - {32, 0b01011000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_s}, - /* instruction FSGNJ.S, encoding '0010000..........000.....1010011' */ - {32, 0b00100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_s}, - /* instruction FSGNJN.S, encoding '0010000..........001.....1010011' */ - {32, 0b00100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_s}, - /* instruction FSGNJX.S, encoding '0010000..........010.....1010011' */ - {32, 0b00100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_s}, - /* instruction FMIN.S, encoding '0010100..........000.....1010011' */ - {32, 0b00101000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_s}, - /* instruction FMAX.S, encoding '0010100..........001.....1010011' */ - {32, 0b00101000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_s}, - /* instruction FCVT.W.S, encoding '110000000000.............1010011' */ - {32, 0b11000000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_s}, - /* instruction FCVT.WU.S, encoding '110000000001.............1010011' */ - {32, 0b11000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_s}, - /* instruction FEQ.S, encoding '1010000..........010.....1010011' */ - {32, 0b10100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_s}, - /* instruction FLT.S, encoding '1010000..........001.....1010011' */ - {32, 0b10100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_s}, - /* instruction FLE.S, encoding '1010000..........000.....1010011' */ - {32, 0b10100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_s}, - /* instruction FCLASS.S, encoding '111000000000.....001.....1010011' */ - {32, 0b11100000000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_s}, - /* instruction FCVT.S.W, encoding '110100000000.............1010011' */ - {32, 0b11010000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_w}, - /* instruction FCVT.S.WU, encoding '110100000001.............1010011' */ - {32, 0b11010000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_wu}, - /* instruction FMV.X.W, encoding '111000000000.....000.....1010011' */ - {32, 0b11100000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_w}, - /* instruction FMV.W.X, encoding '111100000000.....000.....1010011' */ - {32, 0b11110000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_w_x}, - /* instruction FLD, encoding '.................011.....0000111' */ - {32, 0b00000000000000000011000000000111, 0b00000000000000000111000001111111, &this_class::__fld}, - /* instruction FSD, encoding '.................011.....0100111' */ - {32, 0b00000000000000000011000000100111, 0b00000000000000000111000001111111, &this_class::__fsd}, - /* instruction FMADD.D, encoding '.....01..................1000011' */ - {32, 0b00000010000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_d}, - /* instruction FMSUB.D, encoding '.....01..................1000111' */ - {32, 0b00000010000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_d}, - /* instruction FNMADD.D, encoding '.....01..................1001111' */ - {32, 0b00000010000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_d}, - /* instruction FNMSUB.D, encoding '.....01..................1001011' */ - {32, 0b00000010000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_d}, - /* instruction FADD.D, encoding '0000001..................1010011' */ - {32, 0b00000010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_d}, - /* instruction FSUB.D, encoding '0000101..................1010011' */ - {32, 0b00001010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_d}, - /* instruction FMUL.D, encoding '0001001..................1010011' */ - {32, 0b00010010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_d}, - /* instruction FDIV.D, encoding '0001101..................1010011' */ - {32, 0b00011010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_d}, - /* instruction FSQRT.D, encoding '010110100000.............1010011' */ - {32, 0b01011010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_d}, - /* instruction FSGNJ.D, encoding '0010001..........000.....1010011' */ - {32, 0b00100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_d}, - /* instruction FSGNJN.D, encoding '0010001..........001.....1010011' */ - {32, 0b00100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_d}, - /* instruction FSGNJX.D, encoding '0010001..........010.....1010011' */ - {32, 0b00100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_d}, - /* instruction FMIN.D, encoding '0010101..........000.....1010011' */ - {32, 0b00101010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_d}, - /* instruction FMAX.D, encoding '0010101..........001.....1010011' */ - {32, 0b00101010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_d}, - /* instruction FCVT.S.D, encoding '010000000001.............1010011' */ - {32, 0b01000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_d}, - /* instruction FCVT.D.S, encoding '010000100000.............1010011' */ - {32, 0b01000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_s}, - /* instruction FEQ.D, encoding '1010001..........010.....1010011' */ - {32, 0b10100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_d}, - /* instruction FLT.D, encoding '1010001..........001.....1010011' */ - {32, 0b10100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_d}, - /* instruction FLE.D, encoding '1010001..........000.....1010011' */ - {32, 0b10100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_d}, - /* instruction FCLASS.D, encoding '111000100000.....001.....1010011' */ - {32, 0b11100010000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_d}, - /* instruction FCVT.W.D, encoding '110000100000.............1010011' */ - {32, 0b11000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_d}, - /* instruction FCVT.WU.D, encoding '110000100001.............1010011' */ - {32, 0b11000010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_d}, - /* instruction FCVT.D.W, encoding '110100100000.............1010011' */ - {32, 0b11010010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_w}, - /* instruction FCVT.D.WU, encoding '110100100001.............1010011' */ - {32, 0b11010010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_wu}, - /* instruction JALR, encoding '.................000.....1100111' */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction C.ADDI4SPN, encoding '000...........00' */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW, encoding '010...........00' */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW, encoding '110...........00' */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI, encoding '000...........01' */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP, encoding '0000000000000001' */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL, encoding '001...........01' */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI, encoding '010...........01' */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI, encoding '011...........01' */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP, encoding '011.00010.....01' */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI, encoding '100000........01' */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI, encoding '100001........01' */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI, encoding '100.10........01' */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB, encoding '100011...00...01' */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR, encoding '100011...01...01' */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR, encoding '100011...10...01' */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND, encoding '100011...11...01' */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J, encoding '101...........01' */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ, encoding '110...........01' */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ, encoding '111...........01' */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI, encoding '0000..........10' */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP, encoding '010...........10' */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV, encoding '1000..........10' */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR, encoding '1000.....0000010' */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD, encoding '1001..........10' */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR, encoding '1001.....0000010' */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK, encoding '1001000000000010' */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP, encoding '110...........10' */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII, encoding '0000000000000000' */ - {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, - /* instruction C.FLW, encoding '011...........00' */ - {16, 0b0110000000000000, 0b1110000000000011, &this_class::__c_flw}, - /* instruction C.FSW, encoding '111...........00' */ - {16, 0b1110000000000000, 0b1110000000000011, &this_class::__c_fsw}, - /* instruction C.FLWSP, encoding '011...........10' */ - {16, 0b0110000000000010, 0b1110000000000011, &this_class::__c_flwsp}, - /* instruction C.FSWSP, encoding '111...........10' */ - {16, 0b1110000000000010, 0b1110000000000011, &this_class::__c_fswsp}, - /* instruction C.FLD, encoding '001...........00' */ - {16, 0b0010000000000000, 0b1110000000000011, &this_class::__c_fld}, - /* instruction C.FSD, encoding '101...........00' */ - {16, 0b1010000000000000, 0b1110000000000011, &this_class::__c_fsd}, - /* instruction C.FLDSP, encoding '001...........10' */ - {16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_fldsp}, - /* instruction C.FSDSP, encoding '101...........10' */ - {16, 0b1010000000000010, 0b1110000000000011, &this_class::__c_fsdsp}, - }}; - - /* instruction definitions */ - /* instruction 0: MUL */ - compile_ret_t __mul(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MUL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 0); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - res_val, - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 0); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 1: MULH */ - compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MULH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 1); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - false)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 1); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 2: MULHSU */ - compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MULHSU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 2); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 2); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 3: MULHU */ - compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MULHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 3); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 3); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 4: DIV */ - compile_ret_t __div(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DIV_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 4); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - uint32_t M1_val = - 1; - uint8_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.constant(MMIN_val, 32U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs2 + traits::X0, 0), - tu.constant(M1_val, 32U)))); - tu.store(tu.constant(MMIN_val, 32U), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.sdiv( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 32U)), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 4); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 5: DIVU */ - compile_ret_t __divu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DIVU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 5); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - tu.store(tu.udiv( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 32U)), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 5); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 6: REM */ - compile_ret_t __rem(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("REM_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 6); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - uint32_t M1_val = - 1; - uint32_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.constant(MMIN_val, 32U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs2 + traits::X0, 0), - tu.constant(M1_val, 32U)))); - tu.store(tu.constant(0, 32U), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.srem( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.load(rs1 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 6); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 7: REMU */ - compile_ret_t __remu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("REMU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 7); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - tu.store(tu.urem( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.load(rs1 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 7); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 8: LR.W */ - compile_ret_t __lr_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LR_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 8); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); - tu.write_mem( - traits::RES, - offs_val, - tu.trunc(tu.ext( - tu.neg(tu.constant(1, 8U)), - 32, - false), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 8); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 9: SC.W */ - compile_ret_t __sc_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SC_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 9); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.read_mem(traits::RES, offs_val, 32), 32); - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - res1_val, - tu.constant(0, 32U))); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - res1_val, - tu.ext( - tu.constant(0, 32U), - 32, - true)), - tu.constant(0, 32U), - tu.constant(1, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 9); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 10: AMOSWAP.W */ - compile_ret_t __amoswap_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOSWAP_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 10); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); - } - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 10); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 11: AMOADD.W */ - compile_ret_t __amoadd_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOADD_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 11); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.add( - res1_val, - tu.load(rs2 + traits::X0, 0)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 11); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 12: AMOXOR.W */ - compile_ret_t __amoxor_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOXOR_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 12); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_xor( - res1_val, - tu.load(rs2 + traits::X0, 0)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 12); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 13: AMOAND.W */ - compile_ret_t __amoand_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOAND_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 13); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_and( - res1_val, - tu.load(rs2 + traits::X0, 0)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 13); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 14: AMOOR.W */ - compile_ret_t __amoor_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOOR_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 14); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_or( - res1_val, - tu.load(rs2 + traits::X0, 0)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 14); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 15: AMOMIN.W */ - compile_ret_t __amomin_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMIN_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 15); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_SGT, - tu.ext( - res1_val, - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.load(rs2 + traits::X0, 0), - res1_val), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 15); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 16: AMOMAX.W */ - compile_ret_t __amomax_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMAX_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 16); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - res1_val, - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.load(rs2 + traits::X0, 0), - res1_val), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 16); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 17: AMOMINU.W */ - compile_ret_t __amominu_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMINU_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 17); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_UGT, - res1_val, - tu.load(rs2 + traits::X0, 0)), - tu.load(rs2 + traits::X0, 0), - res1_val), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 17); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 18: AMOMAXU.W */ - compile_ret_t __amomaxu_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMAXU_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 18); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - res1_val, - tu.load(rs2 + traits::X0, 0)), - tu.load(rs2 + traits::X0, 0), - res1_val), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 18); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 19: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 19); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.constant(imm, 32U), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 19); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 20: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AUIPC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 20); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 20); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 21: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 21); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 21); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 22: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BEQ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 22); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 22); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 23: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BNE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 23); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 23); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 24: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 24); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 24); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 25: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 25); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SGE, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 25); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 26: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 26); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 26); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 27: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGEU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 27); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_UGE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 27); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 28: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 28); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 28); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 29: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 29); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 29); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 30: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 30); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 30); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 31: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LBU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 31); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 31); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 32: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 32); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 32); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 33: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 33); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 8)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 33); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 34: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 34); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 16)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 34); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 35: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 35); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 35); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 36: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 36); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 36); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 37: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 37); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 37); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 38: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTIU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 38); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - int32_t full_imm_val = imm; - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.constant(full_imm_val, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 38); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 39: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 39); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 39); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 40: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 40); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 40); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 41: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 41); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 41); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 42: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 42); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 42); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 43: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 43); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 43); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 44: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 44); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 44); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 45: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 45); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 45); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 46: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 46); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.sub( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 46); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 47: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 47); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 47); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 48: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 48); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 48); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 49: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 49); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, - true)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 49); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 50: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 50); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 50); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 51: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 51); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 51); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 52: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 52); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 52); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 53: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 53); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 53); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 54: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 54); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 54); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 55: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 55); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(0, 64U), - tu.trunc(tu.l_or( - tu.shl( - tu.constant(pred, 32U), - tu.constant(4, 32U)), - tu.constant(succ, 32U)), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 55); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 56: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_I_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 56); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence_i"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(1, 64U), - tu.trunc(tu.constant(imm, 32U), 32)); - tu.close_scope(); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 56); - gen_trap_check(tu); - return std::make_tuple(FLUSH); - } - - /* instruction 57: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ECALL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 57); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ecall"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 11); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 57); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 58: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 58); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ebreak"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 58); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 59: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("URET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 59); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "uret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 0); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 59); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 60: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 60); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 1); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 60); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 61: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 61); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "mret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 61); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 62: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("WFI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 62); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "wfi"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_wait(tu, 1); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 62); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 63: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SFENCE_VMA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 63); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sfence.vma"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(2, 64U), - tu.trunc(tu.constant(rs1, 32U), 32)); - tu.write_mem( - traits::FENCE, - tu.constant(3, 64U), - tu.trunc(tu.constant(rs2, 32U), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 63); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 64: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 64); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto rs_val_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - auto csr_val_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); - tu.store(csr_val_val, rd + traits::X0); - } else { - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 64); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 65: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRS_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 65); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - xrd_val, - xrs1_val), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 65); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 66: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 66); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - xrd_val, - tu.l_not(xrs1_val)), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 66); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 67: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRWI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 67); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), rd + traits::X0); - } - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.ext( - tu.constant(zimm, 32U), - 32, - true), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 67); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 68: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRSI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 68); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - res_val, - tu.ext( - tu.constant(zimm, 32U), - 32, - true)), 32)); - } - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 68); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 69: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRCI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 69); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - res_val, - tu.l_not(tu.ext( - tu.constant(zimm, 32U), - 32, - true))), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 69); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 70: FLW */ - compile_ret_t __flw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 70); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}({rs1})", fmt::arg("mnemonic", "flw"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - auto res_val = tu.assignment(tu.read_mem(traits::MEM, offs_val, 32), 32); - if(64 == 32){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 70); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 71: FSW */ - compile_ret_t __fsw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 71); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}({name(rs1)])", fmt::arg("mnemonic", "fsw"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.trunc( - tu.load(rs2 + traits::F0, 0), - 32 - ), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 71); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 72: FMADD.S */ - compile_ret_t __fmadd_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMADD_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 72); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fmadd_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.load(rs3 + traits::F0, 0), - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto frs3_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs3 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fmadd_s", - frs1_val, - frs2_val, - frs3_val, - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 72); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 73: FMSUB.S */ - compile_ret_t __fmsub_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMSUB_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 73); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fmadd_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.load(rs3 + traits::F0, 0), - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto frs3_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs3 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fmadd_s", - frs1_val, - frs2_val, - frs3_val, - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 73); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 74: FNMADD.S */ - compile_ret_t __fnmadd_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FNMADD_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 74); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} name(rd), f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.s"), - fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fmadd_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.load(rs3 + traits::F0, 0), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto frs3_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs3 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fmadd_s", - frs1_val, - frs2_val, - frs3_val, - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 74); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 75: FNMSUB.S */ - compile_ret_t __fnmsub_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FNMSUB_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 75); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fmadd_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.load(rs3 + traits::F0, 0), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto frs3_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs3 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fmadd_s", - frs1_val, - frs2_val, - frs3_val, - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 75); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 76: FADD.S */ - compile_ret_t __fadd_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FADD_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 76); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fadd_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fadd_s", - frs1_val, - frs2_val, - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 76); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 77: FSUB.S */ - compile_ret_t __fsub_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSUB_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 77); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fsub_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fsub_s", - frs1_val, - frs2_val, - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 77); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 78: FMUL.S */ - compile_ret_t __fmul_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMUL_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 78); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fmul_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fmul_s", - frs1_val, - frs2_val, - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 78); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 79: FDIV.S */ - compile_ret_t __fdiv_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FDIV_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 79); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fdiv_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fdiv_s", - frs1_val, - frs2_val, - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 79); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 80: FSQRT.S */ - compile_ret_t __fsqrt_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSQRT_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 80); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fsqrt_s", - tu.load(rs1 + traits::F0, 0), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fsqrt_s", - frs1_val, - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 80); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 81: FSGNJ.S */ - compile_ret_t __fsgnj_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJ_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 81); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.l_or( - tu.l_and( - tu.load(rs1 + traits::F0, 0), - tu.constant(0x7fffffff, 64U)), - tu.l_and( - tu.load(rs2 + traits::F0, 0), - tu.constant(0x80000000, 64U))), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.l_or( - tu.l_and( - frs1_val, - tu.constant(0x7fffffff, 32U)), - tu.l_and( - frs2_val, - tu.constant(0x80000000, 32U))), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 81); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 82: FSGNJN.S */ - compile_ret_t __fsgnjn_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJN_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 82); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.l_or( - tu.l_and( - tu.load(rs1 + traits::F0, 0), - tu.constant(0x7fffffff, 64U)), - tu.l_and( - tu.l_not(tu.load(rs2 + traits::F0, 0)), - tu.constant(0x80000000, 64U))), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.l_or( - tu.l_and( - frs1_val, - tu.constant(0x7fffffff, 32U)), - tu.l_and( - tu.l_not(frs2_val), - tu.constant(0x80000000, 32U))), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 82); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 83: FSGNJX.S */ - compile_ret_t __fsgnjx_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJX_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 83); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.l_xor( - tu.load(rs1 + traits::F0, 0), - tu.l_and( - tu.load(rs2 + traits::F0, 0), - tu.constant(0x80000000, 64U))), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.l_xor( - frs1_val, - tu.l_and( - frs2_val, - tu.constant(0x80000000, 32U))), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 83); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 84: FMIN.S */ - compile_ret_t __fmin_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMIN_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 84); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fsel_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fsel_s", - frs1_val, - frs2_val, - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 84); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 85: FMAX.S */ - compile_ret_t __fmax_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMAX_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 85); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fsel_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fsel_s", - frs1_val, - frs2_val, - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 85); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 86: FCVT.W.S */ - compile_ret_t __fcvt_w_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_W_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 86); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.ext( - tu.callf("fcvt_s", - tu.load(rs1 + traits::F0, 0), - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 32, - false), rd + traits::X0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - tu.store(tu.ext( - tu.callf("fcvt_s", - frs1_val, - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 32, - false), rd + traits::X0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 86); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 87: FCVT.WU.S */ - compile_ret_t __fcvt_wu_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_WU_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 87); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.ext( - tu.callf("fcvt_s", - tu.load(rs1 + traits::F0, 0), - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 32, - false), rd + traits::X0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - tu.store(tu.ext( - tu.callf("fcvt_s", - frs1_val, - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 32, - false), rd + traits::X0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 87); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 88: FEQ.S */ - compile_ret_t __feq_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FEQ_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 88); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.ext( - tu.callf("fcmp_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), - 32, - true), rd + traits::X0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - tu.store(tu.ext( - tu.callf("fcmp_s", - frs1_val, - frs2_val, - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), - 32, - true), rd + traits::X0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 88); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 89: FLT.S */ - compile_ret_t __flt_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLT_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 89); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.ext( - tu.callf("fcmp_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.ext( - tu.constant(2LL, 64U), - 32, - true) - ), - 32, - true), rd + traits::X0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - tu.store(tu.ext( - tu.callf("fcmp_s", - frs1_val, - frs2_val, - tu.ext( - tu.constant(2LL, 64U), - 32, - true) - ), - 32, - true), rd + traits::X0); - } - tu.store(tu.callf("fcmp_s", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 32 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 32 - ), - tu.ext( - tu.constant(2LL, 64U), - 32, - true) - ), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 89); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 90: FLE.S */ - compile_ret_t __fle_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLE_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 90); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.ext( - tu.callf("fcmp_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), - 32, - true), rd + traits::X0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - tu.store(tu.ext( - tu.callf("fcmp_s", - frs1_val, - frs2_val, - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), - 32, - true), rd + traits::X0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 90); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 91: FCLASS.S */ - compile_ret_t __fclass_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCLASS_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 91); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.callf("fclass_s", - tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ) - ), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 91); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 92: FCVT.S.W */ - compile_ret_t __fcvt_s_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_S_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 92); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fcvt_s", - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), rd + traits::F0); - } else { - auto res_val = tu.assignment(tu.callf("fcvt_s", - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 92); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 93: FCVT.S.WU */ - compile_ret_t __fcvt_s_wu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_S_WU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 93); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fcvt_s", - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), rd + traits::F0); - } else { - auto res_val = tu.assignment(tu.callf("fcvt_s", - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 93); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 94: FMV.X.W */ - compile_ret_t __fmv_x_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMV_X_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 94); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fmv.x.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 32 - ), - 32, - false), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 94); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 95: FMV.W.X */ - compile_ret_t __fmv_w_x(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMV_W_X_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 95); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fmv.w.x"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 95); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 96: FLD */ - compile_ret_t __fld(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 96); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}({rs1})", fmt::arg("mnemonic", "fld"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - auto res_val = tu.assignment(tu.read_mem(traits::MEM, offs_val, 64), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 96); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 97: FSD */ - compile_ret_t __fsd(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 97); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}({rs1})", fmt::arg("mnemonic", "fsd"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 97); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 98: FMADD.D */ - compile_ret_t __fmadd_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMADD_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 98); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fmadd_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs3 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(0LL, 64U), - 64, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 98); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 99: FMSUB.D */ - compile_ret_t __fmsub_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMSUB_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 99); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fmadd_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs3 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 99); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 100: FNMADD.D */ - compile_ret_t __fnmadd_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FNMADD_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 100); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fmadd_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs3 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 100); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 101: FNMSUB.D */ - compile_ret_t __fnmsub_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FNMSUB_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 101); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fmadd_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs3 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 101); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 102: FADD.D */ - compile_ret_t __fadd_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FADD_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 102); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fadd_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 102); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 103: FSUB.D */ - compile_ret_t __fsub_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSUB_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 103); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fsub_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 103); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 104: FMUL.D */ - compile_ret_t __fmul_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMUL_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 104); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fmul_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 104); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 105: FDIV.D */ - compile_ret_t __fdiv_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FDIV_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 105); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fdiv_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 105); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 106: FSQRT.D */ - compile_ret_t __fsqrt_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSQRT_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 106); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fsqrt_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 106); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 107: FSGNJ.D */ - compile_ret_t __fsgnj_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJ_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 107); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - auto res_val = tu.assignment(tu.l_or( - tu.l_and( - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.constant(MSK2_val, 64U)), - tu.l_and( - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.constant(MSK1_val, 64U))), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 107); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 108: FSGNJN.D */ - compile_ret_t __fsgnjn_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJN_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 108); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - auto res_val = tu.assignment(tu.l_or( - tu.l_and( - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.constant(MSK2_val, 64U)), - tu.l_and( - tu.l_not(tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - )), - tu.constant(MSK1_val, 64U))), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 108); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 109: FSGNJX.D */ - compile_ret_t __fsgnjx_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJX_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 109); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - auto res_val = tu.assignment(tu.l_xor( - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.l_and( - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.constant(MSK1_val, 64U))), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 109); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 110: FMIN.D */ - compile_ret_t __fmin_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMIN_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 110); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fsel_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 110); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 111: FMAX.D */ - compile_ret_t __fmax_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMAX_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 111); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fsel_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 111); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 112: FCVT.S.D */ - compile_ret_t __fcvt_s_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_S_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 112); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.s.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fconv_d2f", - tu.load(rs1 + traits::F0, 0), - tu.constant(rm, 8U) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 112); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 113: FCVT.D.S */ - compile_ret_t __fcvt_d_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_D_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 113); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.d.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fconv_f2d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 32 - ), - tu.constant(rm, 8U) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 113); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 114: FEQ.D */ - compile_ret_t __feq_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FEQ_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 114); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcmp_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), - 32, - true), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 114); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 115: FLT.D */ - compile_ret_t __flt_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLT_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 115); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcmp_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(2LL, 64U), - 32, - true) - ), - 32, - true), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 115); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 116: FLE.D */ - compile_ret_t __fle_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLE_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 116); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcmp_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), - 32, - true), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 116); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 117: FCLASS.D */ - compile_ret_t __fclass_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCLASS_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 117); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.callf("fclass_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ) - ), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 117); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 118: FCVT.W.D */ - compile_ret_t __fcvt_w_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_W_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 118); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcvt_64_32", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 32, - false), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 118); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 119: FCVT.WU.D */ - compile_ret_t __fcvt_wu_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_WU_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 119); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcvt_64_32", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 32, - false), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 119); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 120: FCVT.D.W */ - compile_ret_t __fcvt_d_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_D_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 120); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fcvt_32_64", - tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 64, - false), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 120); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 121: FCVT.D.WU */ - compile_ret_t __fcvt_d_wu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_D_WU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 121); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fcvt_32_64", - tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 64, - true), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 121); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 122: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 122); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto new_pc_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.l_and( - new_pc_val, - tu.l_not(tu.constant(0x1, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 122); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 123: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI4SPN_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 123); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(imm, 32U)), rd + 8 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 123); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 124: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 124); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + 8 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 124); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 125: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 125); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + 8 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 125); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 126: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 126); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rs1 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 126); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 127: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_NOP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 127); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.nop"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.close_scope(); - /* TODO: describe operations for C.NOP ! */ - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 127); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 128: C.JAL */ - compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 128); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - cur_pc_val, - tu.constant(2, 32U)), 1 + traits::X0); - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 128); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 129: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 129); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.constant(imm, 32U), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 129); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 130: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 130); - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); - } - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.constant(imm, 32U), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 130); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 131: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI16SP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 131); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(2 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 2 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 131); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 132: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 132); - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.lshr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 32U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 132); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 133: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 133); - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.ashr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 32U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 133); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 134: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 134); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.l_and( - tu.ext( - tu.load(rs1_idx_val + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 134); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 135: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 135); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.sub( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 135); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 136: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 136); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_xor( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 136); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 137: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 137); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_or( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 137); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 138: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 138); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_and( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 138); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 139: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_J_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 139); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 139); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 140: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BEQZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 140); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 32U)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(2, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 140); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 141: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BNEZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 141); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 32U)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(2, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 141); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 142: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 142); - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rs1 == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rs1 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 142); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 143: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 143); - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 143); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 144: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_MV_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 144); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.load(rs2 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 144); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 145: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 145); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 32); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 145); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 146: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 146); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.load(rd + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 146); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 147: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 147); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - cur_pc_val, - tu.constant(2, 32U)), 1 + traits::X0); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 32); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 147); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 148: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 148); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.ebreak"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 148); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 149: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 149); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 149); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 150: DII */ - compile_ret_t __dii(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DII_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 150); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "dii"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 2); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 150); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 151: C.FLW */ - compile_ret_t __c_flw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FLW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 151); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rd}), {uimm}({rs1})", fmt::arg("mnemonic", "c.flw"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - auto res_val = tu.assignment(tu.read_mem(traits::MEM, offs_val, 32), 32); - if(64 == 32){ - tu.store(res_val, rd + 8 + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + 8 + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 151); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 152: C.FSW */ - compile_ret_t __c_fsw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FSW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 152); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rs2}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fsw"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.trunc( - tu.load(rs2 + 8 + traits::F0, 0), - 32 - ), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 152); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 153: C.FLWSP */ - compile_ret_t __c_flwsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FLWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 153); - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {uimm}(x2)", fmt::arg("mnemonic", "c.flwsp"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - auto res_val = tu.assignment(tu.read_mem(traits::MEM, offs_val, 32), 32); - if(64 == 32){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 153); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 154: C.FSWSP */ - compile_ret_t __c_fswsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FSWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 154); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {uimm}(x2), ", fmt::arg("mnemonic", "c.fswsp"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.trunc( - tu.load(rs2 + traits::F0, 0), - 32 - ), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 154); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 155: C.FLD */ - compile_ret_t __c_fld(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FLD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 155); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rd}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fld"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - auto res_val = tu.assignment(tu.read_mem(traits::MEM, offs_val, 64), 64); - if(64 == 64){ - tu.store(res_val, rd + 8 + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + 8 + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 155); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 156: C.FSD */ - compile_ret_t __c_fsd(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FSD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 156); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rs2}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fsd"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.trunc( - tu.load(rs2 + 8 + traits::F0, 0), - 64 - ), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 156); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 157: C.FLDSP */ - compile_ret_t __c_fldsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FLDSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 157); - uint16_t uimm = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {uimm}(x2)", fmt::arg("mnemonic", "c.fldsp"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - auto res_val = tu.assignment(tu.read_mem(traits::MEM, offs_val, 64), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 157); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 158: C.FSDSP */ - compile_ret_t __c_fsdsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FSDSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 158); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint16_t uimm = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {uimm}(x2), ", fmt::arg("mnemonic", "c.fsdsp"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 158); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, tu_builder& tu) { - vm_impl::gen_sync(tu, iss::PRE_SYNC, instr_descr.size()); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - gen_raise_trap(tu, 0, 2); // illegal instruction trap - vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size()); - vm_impl::gen_trap_check(tu); - return BRANCH; - } -}; - -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 -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, tu); -} - -template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { - tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); -} - -template void vm_impl::gen_leave_trap(tu_builder& tu, unsigned lvl) { - tu("leave_trap(core_ptr, {});", lvl); - tu.store(tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN),traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); -} - -template void vm_impl::gen_wait(tu_builder& tu, unsigned type) { -} - -template void vm_impl::gen_trap_behavior(tu_builder& tu) { - tu("trap_entry:"); - tu("enter_trap(core_ptr, *trap_state, *pc);"); - tu.store(tu.constant(std::numeric_limits::max(),32),traits::LAST_BRANCH); - tu("return *next_pc;"); -} - -} // namespace mnrv32 - -template <> -std::unique_ptr create(arch::rv32gc *core, unsigned short port, bool dump) { - auto ret = new rv32gc::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} -} // namespace iss diff --git a/src/vm/tcc/vm_rv32imac.cpp b/src/vm/tcc/vm_rv32imac.cpp deleted file mode 100644 index 9398720..0000000 --- a/src/vm/tcc/vm_rv32imac.cpp +++ /dev/null @@ -1,3777 +0,0 @@ -/******************************************************************************* - * Copyright (C) 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 -#include -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace tcc { -namespace rv32imac { -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::tcc::vm_base { -public: - using super = typename iss::tcc::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 tu_builder = typename super::tu_builder; - - 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 (vm_base::tgt_adapter == nullptr) - vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm_base::tgt_adapter; - } - -protected: - using vm_base::get_reg_ptr; - - using this_class = vm_impl; - using compile_ret_t = std::tuple; - using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&); - - inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - void setup_module(std::string m) override { - super::setup_module(m); - } - - compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, tu_builder&) override; - - void gen_trap_behavior(tu_builder& tu) override; - - void gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(tu_builder& tu, unsigned lvl); - - void gen_wait(tu_builder& tu, unsigned type); - - inline void gen_trap_check(tu_builder& tu) { - tu("if(*trap_state!=0) goto trap_entry;"); - } - - inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) { - switch(reg_num){ - case traits::NEXT_PC: - tu("*next_pc = {:#x};", pc.val); - break; - case traits::PC: - tu("*pc = {:#x};", pc.val); - break; - default: - if(!tu.defined_regs[reg_num]){ - tu("reg_t* reg{:02d} = (reg_t*){:#x};", reg_num, reinterpret_cast(get_reg_ptr(reg_num))); - tu.defined_regs[reg_num]=true; - } - tu("*reg{:02d} = {:#x};", reg_num, pc.val); - } - } - - // 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; - } - -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, encoding '.........................0110111' */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC, encoding '.........................0010111' */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL, encoding '.........................1101111' */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction BEQ, encoding '.................000.....1100011' */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE, encoding '.................001.....1100011' */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT, encoding '.................100.....1100011' */ - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE, encoding '.................101.....1100011' */ - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU, encoding '.................110.....1100011' */ - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU, encoding '.................111.....1100011' */ - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB, encoding '.................000.....0000011' */ - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH, encoding '.................001.....0000011' */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW, encoding '.................010.....0000011' */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU, encoding '.................100.....0000011' */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU, encoding '.................101.....0000011' */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB, encoding '.................000.....0100011' */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH, encoding '.................001.....0100011' */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW, encoding '.................010.....0100011' */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI, encoding '.................000.....0010011' */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI, encoding '.................010.....0010011' */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU, encoding '.................011.....0010011' */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI, encoding '.................100.....0010011' */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI, encoding '.................110.....0010011' */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI, encoding '.................111.....0010011' */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI, encoding '0000000..........001.....0010011' */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI, encoding '0000000..........101.....0010011' */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI, encoding '0100000..........101.....0010011' */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD, encoding '0000000..........000.....0110011' */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB, encoding '0100000..........000.....0110011' */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL, encoding '0000000..........001.....0110011' */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT, encoding '0000000..........010.....0110011' */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU, encoding '0000000..........011.....0110011' */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR, encoding '0000000..........100.....0110011' */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL, encoding '0000000..........101.....0110011' */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA, encoding '0100000..........101.....0110011' */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR, encoding '0000000..........110.....0110011' */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND, encoding '0000000..........111.....0110011' */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE, encoding '0000.............000.....0001111' */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I, encoding '.................001.....0001111' */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL, encoding '00000000000000000000000001110011' */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK, encoding '00000000000100000000000001110011' */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET, encoding '00000000001000000000000001110011' */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET, encoding '00010000001000000000000001110011' */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET, encoding '00110000001000000000000001110011' */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI, encoding '00010000010100000000000001110011' */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA, encoding '0001001..........000000001110011' */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW, encoding '.................001.....1110011' */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS, encoding '.................010.....1110011' */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC, encoding '.................011.....1110011' */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI, encoding '.................101.....1110011' */ - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI, encoding '.................110.....1110011' */ - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI, encoding '.................111.....1110011' */ - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction MUL, encoding '0000001..........000.....0110011' */ - {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH, encoding '0000001..........001.....0110011' */ - {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU, encoding '0000001..........010.....0110011' */ - {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU, encoding '0000001..........011.....0110011' */ - {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV, encoding '0000001..........100.....0110011' */ - {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU, encoding '0000001..........101.....0110011' */ - {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM, encoding '0000001..........110.....0110011' */ - {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU, encoding '0000001..........111.....0110011' */ - {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction LR.W, encoding '00010..00000.....010.....0101111' */ - {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lr_w}, - /* instruction SC.W, encoding '00011............010.....0101111' */ - {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__sc_w}, - /* instruction AMOSWAP.W, encoding '00001............010.....0101111' */ - {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_w}, - /* instruction AMOADD.W, encoding '00000............010.....0101111' */ - {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_w}, - /* instruction AMOXOR.W, encoding '00100............010.....0101111' */ - {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_w}, - /* instruction AMOAND.W, encoding '01100............010.....0101111' */ - {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_w}, - /* instruction AMOOR.W, encoding '01000............010.....0101111' */ - {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_w}, - /* instruction AMOMIN.W, encoding '10000............010.....0101111' */ - {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_w}, - /* instruction AMOMAX.W, encoding '10100............010.....0101111' */ - {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_w}, - /* instruction AMOMINU.W, encoding '11000............010.....0101111' */ - {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_w}, - /* instruction AMOMAXU.W, encoding '11100............010.....0101111' */ - {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_w}, - /* instruction JALR, encoding '.................000.....1100111' */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction C.ADDI4SPN, encoding '000...........00' */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW, encoding '010...........00' */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW, encoding '110...........00' */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI, encoding '000...........01' */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP, encoding '0000000000000001' */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL, encoding '001...........01' */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI, encoding '010...........01' */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI, encoding '011...........01' */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP, encoding '011.00010.....01' */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI, encoding '100000........01' */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI, encoding '100001........01' */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI, encoding '100.10........01' */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB, encoding '100011...00...01' */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR, encoding '100011...01...01' */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR, encoding '100011...10...01' */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND, encoding '100011...11...01' */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J, encoding '101...........01' */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ, encoding '110...........01' */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ, encoding '111...........01' */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI, encoding '0000..........10' */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP, encoding '010...........10' */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV, encoding '1000..........10' */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR, encoding '1000.....0000010' */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD, encoding '1001..........10' */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR, encoding '1001.....0000010' */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK, encoding '1001000000000010' */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP, encoding '110...........10' */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII, encoding '0000000000000000' */ - {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 0); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.constant(imm, 32U), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 0); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 1: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AUIPC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 1); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 1); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 2: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 2); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 2); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 3: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BEQ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 3); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 3); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 4: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BNE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 4); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 4); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 5: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 5); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 5); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 6: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 6); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SGE, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 6); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 7: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 7); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 7); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 8: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGEU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 8); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_UGE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 8); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 9: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 9); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 9); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 10: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 10); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 10); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 11: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 11); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 11); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 12: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LBU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 12); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 12); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 13: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 13); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 13); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 14: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 14); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 8)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 14); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 15: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 15); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 16)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 15); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 16: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 16); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 16); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 17: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 17); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 17); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 18: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 18); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 18); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 19: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTIU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 19); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - int32_t full_imm_val = imm; - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.constant(full_imm_val, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 19); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 20: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 20); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 20); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 21: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 21); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 21); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 22: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 22); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 22); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 23: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 23); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 23); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 24: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 24); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 25: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 25); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 26: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 26); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 26); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 27: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.sub( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 27); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 28: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 28); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 29: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 29); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 30: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, - true)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 30); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 31: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 31); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 32: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 32); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 33: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 33); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 34: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 34); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 35: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 35); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 36: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 36); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(0, 64U), - tu.trunc(tu.l_or( - tu.shl( - tu.constant(pred, 32U), - tu.constant(4, 32U)), - tu.constant(succ, 32U)), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 36); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 37: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_I_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 37); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence_i"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(1, 64U), - tu.trunc(tu.constant(imm, 32U), 32)); - tu.close_scope(); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 37); - gen_trap_check(tu); - return std::make_tuple(FLUSH); - } - - /* instruction 38: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ECALL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 38); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ecall"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 11); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 38); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 39: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 39); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ebreak"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 39); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 40: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("URET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 40); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "uret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 0); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 40); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 41: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 41); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 1); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 41); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 42: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 42); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "mret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 42); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 43: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("WFI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 43); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "wfi"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_wait(tu, 1); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 43); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 44: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SFENCE_VMA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 44); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sfence.vma"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(2, 64U), - tu.trunc(tu.constant(rs1, 32U), 32)); - tu.write_mem( - traits::FENCE, - tu.constant(3, 64U), - tu.trunc(tu.constant(rs2, 32U), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 44); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 45: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 45); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto rs_val_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - auto csr_val_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); - tu.store(csr_val_val, rd + traits::X0); - } else { - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 45); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 46: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRS_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - xrd_val, - xrs1_val), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 46); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 47: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - xrd_val, - tu.l_not(xrs1_val)), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 47); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 48: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRWI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 48); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), rd + traits::X0); - } - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.ext( - tu.constant(zimm, 32U), - 32, - true), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 48); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 49: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRSI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - res_val, - tu.ext( - tu.constant(zimm, 32U), - 32, - true)), 32)); - } - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 49); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 50: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRCI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - res_val, - tu.l_not(tu.ext( - tu.constant(zimm, 32U), - 32, - true))), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 50); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 51: MUL */ - compile_ret_t __mul(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MUL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 51); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - res_val, - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 51); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 52: MULH */ - compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MULH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 52); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - false)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 52); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 53: MULHSU */ - compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MULHSU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 53); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 53); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 54: MULHU */ - compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MULHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 54); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 54); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 55: DIV */ - compile_ret_t __div(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DIV_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 55); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - uint32_t M1_val = - 1; - uint8_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.constant(MMIN_val, 32U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs2 + traits::X0, 0), - tu.constant(M1_val, 32U)))); - tu.store(tu.constant(MMIN_val, 32U), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.sdiv( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 32U)), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 55); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 56: DIVU */ - compile_ret_t __divu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DIVU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 56); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - tu.store(tu.udiv( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 32U)), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 56); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 57: REM */ - compile_ret_t __rem(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("REM_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 57); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - uint32_t M1_val = - 1; - uint32_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.constant(MMIN_val, 32U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs2 + traits::X0, 0), - tu.constant(M1_val, 32U)))); - tu.store(tu.constant(0, 32U), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.srem( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.load(rs1 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 57); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 58: REMU */ - compile_ret_t __remu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("REMU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 58); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - tu.store(tu.urem( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.load(rs1 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 58); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 59: LR.W */ - compile_ret_t __lr_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LR_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 59); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); - tu.write_mem( - traits::RES, - offs_val, - tu.trunc(tu.ext( - tu.neg(tu.constant(1, 8U)), - 32, - false), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 59); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 60: SC.W */ - compile_ret_t __sc_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SC_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 60); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.read_mem(traits::RES, offs_val, 32), 32); - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - res1_val, - tu.constant(0, 32U))); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - res1_val, - tu.ext( - tu.constant(0, 32U), - 32, - true)), - tu.constant(0, 32U), - tu.constant(1, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 60); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 61: AMOSWAP.W */ - compile_ret_t __amoswap_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOSWAP_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 61); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); - } - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 61); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 62: AMOADD.W */ - compile_ret_t __amoadd_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOADD_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 62); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.add( - res1_val, - tu.load(rs2 + traits::X0, 0)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 62); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 63: AMOXOR.W */ - compile_ret_t __amoxor_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOXOR_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 63); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_xor( - res1_val, - tu.load(rs2 + traits::X0, 0)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 63); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 64: AMOAND.W */ - compile_ret_t __amoand_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOAND_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 64); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_and( - res1_val, - tu.load(rs2 + traits::X0, 0)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 64); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 65: AMOOR.W */ - compile_ret_t __amoor_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOOR_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 65); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_or( - res1_val, - tu.load(rs2 + traits::X0, 0)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 65); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 66: AMOMIN.W */ - compile_ret_t __amomin_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMIN_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 66); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_SGT, - tu.ext( - res1_val, - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.load(rs2 + traits::X0, 0), - res1_val), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 66); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 67: AMOMAX.W */ - compile_ret_t __amomax_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMAX_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 67); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - res1_val, - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.load(rs2 + traits::X0, 0), - res1_val), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 67); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 68: AMOMINU.W */ - compile_ret_t __amominu_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMINU_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 68); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_UGT, - res1_val, - tu.load(rs2 + traits::X0, 0)), - tu.load(rs2 + traits::X0, 0), - res1_val), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 68); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 69: AMOMAXU.W */ - compile_ret_t __amomaxu_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMAXU_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 69); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), 32); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - res1_val, - tu.load(rs2 + traits::X0, 0)), - tu.load(rs2 + traits::X0, 0), - res1_val), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 69); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 70: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 70); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto new_pc_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.l_and( - new_pc_val, - tu.l_not(tu.constant(0x1, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 70); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 71: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI4SPN_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 71); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(imm, 32U)), rd + 8 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 71); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 72: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 72); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + 8 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 72); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 73: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 73); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + 8 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 73); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 74: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 74); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rs1 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 74); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 75: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_NOP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 75); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.nop"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.close_scope(); - /* TODO: describe operations for C.NOP ! */ - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 75); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 76: C.JAL */ - compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 76); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - cur_pc_val, - tu.constant(2, 32U)), 1 + traits::X0); - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 76); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 77: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 77); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.constant(imm, 32U), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 77); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 78: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 78); - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); - } - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.constant(imm, 32U), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 78); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 79: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI16SP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 79); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(2 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 2 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 79); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 80: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 80); - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.lshr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 32U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 80); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 81: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 81); - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.ashr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 32U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 81); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 82: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 82); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.l_and( - tu.ext( - tu.load(rs1_idx_val + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 82); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 83: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 83); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.sub( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 83); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 84: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 84); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_xor( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 84); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 85: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 85); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_or( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 85); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 86: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 86); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_and( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 86); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 87: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_J_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 87); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 87); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 88: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BEQZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 88); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 32U)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(2, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 88); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 89: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BNEZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 89); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 32U)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(2, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 89); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 90: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 90); - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rs1 == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rs1 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 90); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 91: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 91); - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 91); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 92: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_MV_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 92); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.load(rs2 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 92); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 93: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 93); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 32); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 93); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 94: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 94); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.load(rd + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 94); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 95: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 95); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - cur_pc_val, - tu.constant(2, 32U)), 1 + traits::X0); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 32); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 95); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 96: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 96); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.ebreak"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 96); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 97: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 97); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 97); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 98: DII */ - compile_ret_t __dii(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DII_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 98); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "dii"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 2); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 98); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, tu_builder& tu) { - vm_impl::gen_sync(tu, iss::PRE_SYNC, instr_descr.size()); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - gen_raise_trap(tu, 0, 2); // illegal instruction trap - vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size()); - vm_impl::gen_trap_check(tu); - return BRANCH; - } -}; - -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 -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, tu); -} - -template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { - tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); -} - -template void vm_impl::gen_leave_trap(tu_builder& tu, unsigned lvl) { - tu("leave_trap(core_ptr, {});", lvl); - tu.store(tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN),traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); -} - -template void vm_impl::gen_wait(tu_builder& tu, unsigned type) { -} - -template void vm_impl::gen_trap_behavior(tu_builder& tu) { - tu("trap_entry:"); - tu("enter_trap(core_ptr, *trap_state, *pc);"); - tu.store(tu.constant(std::numeric_limits::max(),32),traits::LAST_BRANCH); - tu("return *next_pc;"); -} - -} // namespace mnrv32 - -template <> -std::unique_ptr create(arch::rv32imac *core, unsigned short port, bool dump) { - auto ret = new rv32imac::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} -} // namespace iss diff --git a/src/vm/tcc/vm_rv64gc.cpp b/src/vm/tcc/vm_rv64gc.cpp deleted file mode 100644 index 11ff9d1..0000000 --- a/src/vm/tcc/vm_rv64gc.cpp +++ /dev/null @@ -1,8989 +0,0 @@ -/******************************************************************************* - * Copyright (C) 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 -#include -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace tcc { -namespace rv64gc { -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::tcc::vm_base { -public: - using super = typename iss::tcc::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 tu_builder = typename super::tu_builder; - - 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 (vm_base::tgt_adapter == nullptr) - vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm_base::tgt_adapter; - } - -protected: - using vm_base::get_reg_ptr; - - using this_class = vm_impl; - using compile_ret_t = std::tuple; - using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&); - - inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - void setup_module(std::string m) override { - super::setup_module(m); - } - - compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, tu_builder&) override; - - void gen_trap_behavior(tu_builder& tu) override; - - void gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(tu_builder& tu, unsigned lvl); - - void gen_wait(tu_builder& tu, unsigned type); - - inline void gen_trap_check(tu_builder& tu) { - tu("if(*trap_state!=0) goto trap_entry;"); - } - - inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) { - switch(reg_num){ - case traits::NEXT_PC: - tu("*next_pc = {:#x};", pc.val); - break; - case traits::PC: - tu("*pc = {:#x};", pc.val); - break; - default: - if(!tu.defined_regs[reg_num]){ - tu("reg_t* reg{:02d} = (reg_t*){:#x};", reg_num, reinterpret_cast(get_reg_ptr(reg_num))); - tu.defined_regs[reg_num]=true; - } - tu("*reg{:02d} = {:#x};", reg_num, pc.val); - } - } - - // 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; - } - -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, encoding '.........................0110111' */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC, encoding '.........................0010111' */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL, encoding '.........................1101111' */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR, encoding '.................000.....1100111' */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ, encoding '.................000.....1100011' */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE, encoding '.................001.....1100011' */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT, encoding '.................100.....1100011' */ - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE, encoding '.................101.....1100011' */ - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU, encoding '.................110.....1100011' */ - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU, encoding '.................111.....1100011' */ - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB, encoding '.................000.....0000011' */ - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH, encoding '.................001.....0000011' */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW, encoding '.................010.....0000011' */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU, encoding '.................100.....0000011' */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU, encoding '.................101.....0000011' */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB, encoding '.................000.....0100011' */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH, encoding '.................001.....0100011' */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW, encoding '.................010.....0100011' */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI, encoding '.................000.....0010011' */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI, encoding '.................010.....0010011' */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU, encoding '.................011.....0010011' */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI, encoding '.................100.....0010011' */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI, encoding '.................110.....0010011' */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI, encoding '.................111.....0010011' */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI, encoding '000000...........001.....0010011' */ - {32, 0b00000000000000000001000000010011, 0b11111100000000000111000001111111, &this_class::__slli}, - /* instruction SRLI, encoding '000000...........101.....0010011' */ - {32, 0b00000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srli}, - /* instruction SRAI, encoding '010000...........101.....0010011' */ - {32, 0b01000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srai}, - /* instruction ADD, encoding '0000000..........000.....0110011' */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB, encoding '0100000..........000.....0110011' */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL, encoding '0000000..........001.....0110011' */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT, encoding '0000000..........010.....0110011' */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU, encoding '0000000..........011.....0110011' */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR, encoding '0000000..........100.....0110011' */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL, encoding '0000000..........101.....0110011' */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA, encoding '0100000..........101.....0110011' */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR, encoding '0000000..........110.....0110011' */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND, encoding '0000000..........111.....0110011' */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE, encoding '0000.............000.....0001111' */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I, encoding '.................001.....0001111' */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL, encoding '00000000000000000000000001110011' */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK, encoding '00000000000100000000000001110011' */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET, encoding '00000000001000000000000001110011' */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET, encoding '00010000001000000000000001110011' */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET, encoding '00110000001000000000000001110011' */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI, encoding '00010000010100000000000001110011' */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA, encoding '0001001..........000000001110011' */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW, encoding '.................001.....1110011' */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS, encoding '.................010.....1110011' */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC, encoding '.................011.....1110011' */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI, encoding '.................101.....1110011' */ - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI, encoding '.................110.....1110011' */ - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI, encoding '.................111.....1110011' */ - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction LWU, encoding '.................110.....0000011' */ - {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, - /* instruction LD, encoding '.................011.....0000011' */ - {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, &this_class::__ld}, - /* instruction SD, encoding '.................011.....0100011' */ - {32, 0b00000000000000000011000000100011, 0b00000000000000000111000001111111, &this_class::__sd}, - /* instruction ADDIW, encoding '.................000.....0011011' */ - {32, 0b00000000000000000000000000011011, 0b00000000000000000111000001111111, &this_class::__addiw}, - /* instruction SLLIW, encoding '0000000..........001.....0011011' */ - {32, 0b00000000000000000001000000011011, 0b11111110000000000111000001111111, &this_class::__slliw}, - /* instruction SRLIW, encoding '0000000..........101.....0011011' */ - {32, 0b00000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__srliw}, - /* instruction SRAIW, encoding '0100000..........101.....0011011' */ - {32, 0b01000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__sraiw}, - /* instruction ADDW, encoding '0000000..........000.....0111011' */ - {32, 0b00000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__addw}, - /* instruction SUBW, encoding '0100000..........000.....0111011' */ - {32, 0b01000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__subw}, - /* instruction SLLW, encoding '0000000..........001.....0111011' */ - {32, 0b00000000000000000001000000111011, 0b11111110000000000111000001111111, &this_class::__sllw}, - /* instruction SRLW, encoding '0000000..........101.....0111011' */ - {32, 0b00000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__srlw}, - /* instruction SRAW, encoding '0100000..........101.....0111011' */ - {32, 0b01000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__sraw}, - /* instruction MUL, encoding '0000001..........000.....0110011' */ - {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH, encoding '0000001..........001.....0110011' */ - {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU, encoding '0000001..........010.....0110011' */ - {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU, encoding '0000001..........011.....0110011' */ - {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV, encoding '0000001..........100.....0110011' */ - {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU, encoding '0000001..........101.....0110011' */ - {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM, encoding '0000001..........110.....0110011' */ - {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU, encoding '0000001..........111.....0110011' */ - {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction MULW, encoding '0000001..........000.....0111011' */ - {32, 0b00000010000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__mulw}, - /* instruction DIVW, encoding '0000001..........100.....0111011' */ - {32, 0b00000010000000000100000000111011, 0b11111110000000000111000001111111, &this_class::__divw}, - /* instruction DIVUW, encoding '0000001..........101.....0111011' */ - {32, 0b00000010000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__divuw}, - /* instruction REMW, encoding '0000001..........110.....0111011' */ - {32, 0b00000010000000000110000000111011, 0b11111110000000000111000001111111, &this_class::__remw}, - /* instruction REMUW, encoding '0000001..........111.....0111011' */ - {32, 0b00000010000000000111000000111011, 0b11111110000000000111000001111111, &this_class::__remuw}, - /* instruction LR.W, encoding '00010..00000.....010.....0101111' */ - {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lr_w}, - /* instruction SC.W, encoding '00011............010.....0101111' */ - {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__sc_w}, - /* instruction AMOSWAP.W, encoding '00001............010.....0101111' */ - {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_w}, - /* instruction AMOADD.W, encoding '00000............010.....0101111' */ - {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_w}, - /* instruction AMOXOR.W, encoding '00100............010.....0101111' */ - {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_w}, - /* instruction AMOAND.W, encoding '01100............010.....0101111' */ - {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_w}, - /* instruction AMOOR.W, encoding '01000............010.....0101111' */ - {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_w}, - /* instruction AMOMIN.W, encoding '10000............010.....0101111' */ - {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_w}, - /* instruction AMOMAX.W, encoding '10100............010.....0101111' */ - {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_w}, - /* instruction AMOMINU.W, encoding '11000............010.....0101111' */ - {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_w}, - /* instruction AMOMAXU.W, encoding '11100............010.....0101111' */ - {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_w}, - /* instruction LR.D, encoding '00010..00000.....011.....0101111' */ - {32, 0b00010000000000000011000000101111, 0b11111001111100000111000001111111, &this_class::__lr_d}, - /* instruction SC.D, encoding '00011............011.....0101111' */ - {32, 0b00011000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__sc_d}, - /* instruction AMOSWAP.D, encoding '00001............011.....0101111' */ - {32, 0b00001000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_d}, - /* instruction AMOADD.D, encoding '00000............011.....0101111' */ - {32, 0b00000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_d}, - /* instruction AMOXOR.D, encoding '00100............011.....0101111' */ - {32, 0b00100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_d}, - /* instruction AMOAND.D, encoding '01100............011.....0101111' */ - {32, 0b01100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_d}, - /* instruction AMOOR.D, encoding '01000............011.....0101111' */ - {32, 0b01000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_d}, - /* instruction AMOMIN.D, encoding '10000............011.....0101111' */ - {32, 0b10000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_d}, - /* instruction AMOMAX.D, encoding '10100............011.....0101111' */ - {32, 0b10100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_d}, - /* instruction AMOMINU.D, encoding '11000............011.....0101111' */ - {32, 0b11000000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_d}, - /* instruction AMOMAXU.D, encoding '11100............011.....0101111' */ - {32, 0b11100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_d}, - /* instruction FLW, encoding '.................010.....0000111' */ - {32, 0b00000000000000000010000000000111, 0b00000000000000000111000001111111, &this_class::__flw}, - /* instruction FSW, encoding '.................010.....0100111' */ - {32, 0b00000000000000000010000000100111, 0b00000000000000000111000001111111, &this_class::__fsw}, - /* instruction FMADD.S, encoding '.....00..................1000011' */ - {32, 0b00000000000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_s}, - /* instruction FMSUB.S, encoding '.....00..................1000111' */ - {32, 0b00000000000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_s}, - /* instruction FNMADD.S, encoding '.....00..................1001111' */ - {32, 0b00000000000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_s}, - /* instruction FNMSUB.S, encoding '.....00..................1001011' */ - {32, 0b00000000000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_s}, - /* instruction FADD.S, encoding '0000000..................1010011' */ - {32, 0b00000000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_s}, - /* instruction FSUB.S, encoding '0000100..................1010011' */ - {32, 0b00001000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_s}, - /* instruction FMUL.S, encoding '0001000..................1010011' */ - {32, 0b00010000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_s}, - /* instruction FDIV.S, encoding '0001100..................1010011' */ - {32, 0b00011000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_s}, - /* instruction FSQRT.S, encoding '010110000000.............1010011' */ - {32, 0b01011000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_s}, - /* instruction FSGNJ.S, encoding '0010000..........000.....1010011' */ - {32, 0b00100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_s}, - /* instruction FSGNJN.S, encoding '0010000..........001.....1010011' */ - {32, 0b00100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_s}, - /* instruction FSGNJX.S, encoding '0010000..........010.....1010011' */ - {32, 0b00100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_s}, - /* instruction FMIN.S, encoding '0010100..........000.....1010011' */ - {32, 0b00101000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_s}, - /* instruction FMAX.S, encoding '0010100..........001.....1010011' */ - {32, 0b00101000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_s}, - /* instruction FCVT.W.S, encoding '110000000000.............1010011' */ - {32, 0b11000000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_s}, - /* instruction FCVT.WU.S, encoding '110000000001.............1010011' */ - {32, 0b11000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_s}, - /* instruction FEQ.S, encoding '1010000..........010.....1010011' */ - {32, 0b10100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_s}, - /* instruction FLT.S, encoding '1010000..........001.....1010011' */ - {32, 0b10100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_s}, - /* instruction FLE.S, encoding '1010000..........000.....1010011' */ - {32, 0b10100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_s}, - /* instruction FCLASS.S, encoding '111000000000.....001.....1010011' */ - {32, 0b11100000000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_s}, - /* instruction FCVT.S.W, encoding '110100000000.............1010011' */ - {32, 0b11010000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_w}, - /* instruction FCVT.S.WU, encoding '110100000001.............1010011' */ - {32, 0b11010000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_wu}, - /* instruction FMV.X.W, encoding '111000000000.....000.....1010011' */ - {32, 0b11100000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_w}, - /* instruction FMV.W.X, encoding '111100000000.....000.....1010011' */ - {32, 0b11110000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_w_x}, - /* instruction FCVT.L.S, encoding '110000000010.............1010011' */ - {32, 0b11000000001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_l_s}, - /* instruction FCVT.LU.S, encoding '110000000011.............1010011' */ - {32, 0b11000000001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_lu_s}, - /* instruction FCVT.S.L, encoding '110100000010.............1010011' */ - {32, 0b11010000001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_l}, - /* instruction FCVT.S.LU, encoding '110100000011.............1010011' */ - {32, 0b11010000001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_lu}, - /* instruction FLD, encoding '.................011.....0000111' */ - {32, 0b00000000000000000011000000000111, 0b00000000000000000111000001111111, &this_class::__fld}, - /* instruction FSD, encoding '.................011.....0100111' */ - {32, 0b00000000000000000011000000100111, 0b00000000000000000111000001111111, &this_class::__fsd}, - /* instruction FMADD.D, encoding '.....01..................1000011' */ - {32, 0b00000010000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_d}, - /* instruction FMSUB.D, encoding '.....01..................1000111' */ - {32, 0b00000010000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_d}, - /* instruction FNMADD.D, encoding '.....01..................1001111' */ - {32, 0b00000010000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_d}, - /* instruction FNMSUB.D, encoding '.....01..................1001011' */ - {32, 0b00000010000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_d}, - /* instruction FADD.D, encoding '0000001..................1010011' */ - {32, 0b00000010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_d}, - /* instruction FSUB.D, encoding '0000101..................1010011' */ - {32, 0b00001010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_d}, - /* instruction FMUL.D, encoding '0001001..................1010011' */ - {32, 0b00010010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_d}, - /* instruction FDIV.D, encoding '0001101..................1010011' */ - {32, 0b00011010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_d}, - /* instruction FSQRT.D, encoding '010110100000.............1010011' */ - {32, 0b01011010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_d}, - /* instruction FSGNJ.D, encoding '0010001..........000.....1010011' */ - {32, 0b00100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_d}, - /* instruction FSGNJN.D, encoding '0010001..........001.....1010011' */ - {32, 0b00100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_d}, - /* instruction FSGNJX.D, encoding '0010001..........010.....1010011' */ - {32, 0b00100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_d}, - /* instruction FMIN.D, encoding '0010101..........000.....1010011' */ - {32, 0b00101010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_d}, - /* instruction FMAX.D, encoding '0010101..........001.....1010011' */ - {32, 0b00101010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_d}, - /* instruction FCVT.S.D, encoding '010000000001.............1010011' */ - {32, 0b01000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_d}, - /* instruction FCVT.D.S, encoding '010000100000.............1010011' */ - {32, 0b01000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_s}, - /* instruction FEQ.D, encoding '1010001..........010.....1010011' */ - {32, 0b10100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_d}, - /* instruction FLT.D, encoding '1010001..........001.....1010011' */ - {32, 0b10100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_d}, - /* instruction FLE.D, encoding '1010001..........000.....1010011' */ - {32, 0b10100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_d}, - /* instruction FCLASS.D, encoding '111000100000.....001.....1010011' */ - {32, 0b11100010000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_d}, - /* instruction FCVT.W.D, encoding '110000100000.............1010011' */ - {32, 0b11000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_d}, - /* instruction FCVT.WU.D, encoding '110000100001.............1010011' */ - {32, 0b11000010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_d}, - /* instruction FCVT.D.W, encoding '110100100000.............1010011' */ - {32, 0b11010010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_w}, - /* instruction FCVT.D.WU, encoding '110100100001.............1010011' */ - {32, 0b11010010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_wu}, - /* instruction FCVT.L.D, encoding '110000100010.............1010011' */ - {32, 0b11000010001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_l_d}, - /* instruction FCVT.LU.D, encoding '110000100011.............1010011' */ - {32, 0b11000010001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_lu_d}, - /* instruction FCVT.D.L, encoding '110100100010.............1010011' */ - {32, 0b11010010001000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_l}, - /* instruction FCVT.D.LU, encoding '110100100011.............1010011' */ - {32, 0b11010010001100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_lu}, - /* instruction FMV.X.D, encoding '111000100000.....000.....1010011' */ - {32, 0b11100010000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_d}, - /* instruction FMV.D.X, encoding '111100100000.....000.....1010011' */ - {32, 0b11110010000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_d_x}, - /* instruction C.LD, encoding '011...........00' */ - {16, 0b0110000000000000, 0b1110000000000011, &this_class::__c_ld}, - /* instruction C.SD, encoding '111...........00' */ - {16, 0b1110000000000000, 0b1110000000000011, &this_class::__c_sd}, - /* instruction C.LDSP, encoding '011...........10' */ - {16, 0b0110000000000010, 0b1110000000000011, &this_class::__c_ldsp}, - /* instruction C.SDSP, encoding '111...........10' */ - {16, 0b1110000000000010, 0b1110000000000011, &this_class::__c_sdsp}, - /* instruction C.FLD, encoding '001...........00' */ - {16, 0b0010000000000000, 0b1110000000000011, &this_class::__c_fld}, - /* instruction C.FSD, encoding '101...........00' */ - {16, 0b1010000000000000, 0b1110000000000011, &this_class::__c_fsd}, - /* instruction C.FLDSP, encoding '001...........10' */ - {16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_fldsp}, - /* instruction C.FSDSP, encoding '101...........10' */ - {16, 0b1010000000000010, 0b1110000000000011, &this_class::__c_fsdsp}, - /* instruction C.ADDI4SPN, encoding '000...........00' */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW, encoding '010...........00' */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW, encoding '110...........00' */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI, encoding '000...........01' */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP, encoding '0000000000000001' */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.ADDIW, encoding '001...........01' */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_addiw}, - /* instruction C.LI, encoding '010...........01' */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI, encoding '011...........01' */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP, encoding '011.00010.....01' */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI, encoding '100.00........01' */ - {16, 0b1000000000000001, 0b1110110000000011, &this_class::__c_srli}, - /* instruction C.SRAI, encoding '100.01........01' */ - {16, 0b1000010000000001, 0b1110110000000011, &this_class::__c_srai}, - /* instruction C.ANDI, encoding '100.10........01' */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB, encoding '100011...00...01' */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR, encoding '100011...01...01' */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR, encoding '100011...10...01' */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND, encoding '100011...11...01' */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J, encoding '101...........01' */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ, encoding '110...........01' */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ, encoding '111...........01' */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI, encoding '000...........10' */ - {16, 0b0000000000000010, 0b1110000000000011, &this_class::__c_slli}, - /* instruction C.LWSP, encoding '010...........10' */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV, encoding '1000..........10' */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR, encoding '1000.....0000010' */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD, encoding '1001..........10' */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR, encoding '1001.....0000010' */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK, encoding '1001000000000010' */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP, encoding '110...........10' */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII, encoding '0000000000000000' */ - {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, - /* instruction C.SUBW, encoding '100111...00...01' */ - {16, 0b1001110000000001, 0b1111110001100011, &this_class::__c_subw}, - /* instruction C.ADDW, encoding '100111...01...01' */ - {16, 0b1001110000100001, 0b1111110001100011, &this_class::__c_addw}, - /* instruction C.SRLI64, encoding '100000...01' */ - {11, 0b10000000001, 0b11111100011, &this_class::__c_srli64}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 0); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.constant(imm, 64U), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 0); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 1: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AUIPC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 1); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 1); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 2: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 2); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 64U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 2); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 3: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 3); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto new_pc_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 64U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.l_and( - new_pc_val, - tu.l_not(tu.constant(0x1, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 3); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 4: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BEQ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 4); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 4); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 5: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BNE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 5); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 5); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 6: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 6); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 6); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 7: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 7); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SGE, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 7); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 8: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 8); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 8); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 9: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGEU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 9); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_UGE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 9); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 10: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 10); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 10); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 11: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 11); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 11); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 12: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 12); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 12); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 13: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LBU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 13); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 64, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 13); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 14: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 14); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 64, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 14); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 15: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 15); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 8)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 15); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 16: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 16); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 16)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 16); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 17: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 17); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 17); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 18: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 18); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 18); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 19: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 19); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), - tu.constant(1, 64U), - tu.constant(0, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 19); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 20: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTIU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 20); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - int64_t full_imm_val = imm; - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.constant(full_imm_val, 64U)), - tu.constant(1, 64U), - tu.constant(0, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 20); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 21: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 21); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 21); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 22: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 22); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 22); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 23: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 23); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 23); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 24: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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,6>(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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 24); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 25: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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,6>(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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 25); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 26: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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,6>(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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 26); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 27: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 27); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 28: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.sub( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 28); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 29: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(64, 64U), - tu.constant(1, 64U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 29); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 30: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), - tu.constant(1, 64U), - tu.constant(0, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 30); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 31: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), - tu.constant(1, 64U), - tu.constant(0, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 31); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 32: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 32); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 33: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(64, 64U), - tu.constant(1, 64U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 33); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 34: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(64, 64U), - tu.constant(1, 64U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 34); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 35: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 35); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 36: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 36); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 37: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(0, 64U), - tu.trunc(tu.l_or( - tu.shl( - tu.constant(pred, 64U), - tu.constant(4, 64U)), - tu.constant(succ, 64U)), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 37); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 38: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_I_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence_i"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(1, 64U), - tu.trunc(tu.constant(imm, 64U), 64)); - tu.close_scope(); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 38); - gen_trap_check(tu); - return std::make_tuple(FLUSH); - } - - /* instruction 39: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ECALL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 39); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ecall"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 11); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 39); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 40: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 40); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ebreak"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 40); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 41: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("URET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 41); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "uret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 0); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 41); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 42: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 42); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 1); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 42); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 43: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 43); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "mret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 43); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 44: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("WFI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 44); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "wfi"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_wait(tu, 1); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 44); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 45: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SFENCE_VMA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sfence.vma"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(2, 64U), - tu.trunc(tu.constant(rs1, 64U), 64)); - tu.write_mem( - traits::FENCE, - tu.constant(3, 64U), - tu.trunc(tu.constant(rs2, 64U), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 45); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 46: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto rs_val_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - if(rd != 0){ - auto csr_val_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 64)); - tu.store(csr_val_val, rd + traits::X0); - } else { - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 64)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 46); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 47: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRS_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - xrd_val, - xrs1_val), 64)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 47); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 48: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - xrd_val, - tu.l_not(xrs1_val)), 64)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 48); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 49: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRWI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), rd + traits::X0); - } - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.ext( - tu.constant(zimm, 64U), - 64, - true), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 49); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 50: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRSI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - res_val, - tu.ext( - tu.constant(zimm, 64U), - 64, - true)), 64)); - } - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 50); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 51: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRCI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - res_val, - tu.l_not(tu.ext( - tu.constant(zimm, 64U), - 64, - true))), 64)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 51); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 52: LWU */ - compile_ret_t __lwu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LWU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 52); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lwu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 52); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 53: LD */ - compile_ret_t __ld(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 53); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "ld"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 53); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 54: SD */ - compile_ret_t __sd(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 54); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sd"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 54); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 55: ADDIW */ - compile_ret_t __addiw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADDIW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 55); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.add( - tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(tu.ext( - res_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 55); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 56: SLLIW */ - compile_ret_t __slliw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLLIW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 56); - 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", "slliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto sh_val_val = tu.assignment(tu.shl( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.constant(shamt, 32U)), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 56); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 57: SRLIW */ - compile_ret_t __srliw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRLIW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 57); - 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", "srliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto sh_val_val = tu.assignment(tu.lshr( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.constant(shamt, 32U)), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 57); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 58: SRAIW */ - compile_ret_t __sraiw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRAIW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 58); - 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", "sraiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto sh_val_val = tu.assignment(tu.ashr( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.constant(shamt, 32U)), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 58); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 59: ADDW */ - compile_ret_t __addw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADDW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 59); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "addw"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.add( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - )), 32); - tu.store(tu.ext( - res_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 59); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 60: SUBW */ - compile_ret_t __subw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SUBW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 60); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "subw"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.sub( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - )), 32); - tu.store(tu.ext( - res_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 60); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 61: SLLW */ - compile_ret_t __sllw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLLW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 61); - 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", "sllw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = tu.assignment(tu.l_and( - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - ), - tu.constant(mask_val, 32U)), 32); - auto sh_val_val = tu.assignment(tu.shl( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - count_val), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 61); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 62: SRLW */ - compile_ret_t __srlw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRLW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 62); - 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", "srlw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = tu.assignment(tu.l_and( - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - ), - tu.constant(mask_val, 32U)), 32); - auto sh_val_val = tu.assignment(tu.lshr( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - count_val), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 62); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 63: SRAW */ - compile_ret_t __sraw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRAW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 63); - 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", "sraw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = tu.assignment(tu.l_and( - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - ), - tu.constant(mask_val, 32U)), 32); - auto sh_val_val = tu.assignment(tu.ashr( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - count_val), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 63); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 64: MUL */ - compile_ret_t __mul(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MUL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 64); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 128, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 128, - true)), 128); - tu.store(tu.ext( - res_val, - 64, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 64); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 65: MULH */ - compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MULH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 65); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 128, - false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 128, - false)), 128); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(64, 64U)), - 64, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 65); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 66: MULHSU */ - compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MULHSU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 66); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 128, - false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 128, - true)), 128); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(64, 64U)), - 64, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 66); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 67: MULHU */ - compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MULHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 67); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 128, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 128, - true)), 128); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(64, 64U)), - 64, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 67); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 68: DIV */ - compile_ret_t __div(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DIV_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 68); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 64U))); - uint64_t M1_val = - 1; - uint8_t XLM1_val = 64 - 1; - uint64_t ONE_val = 1; - uint64_t MMIN_val = ONE_val << XLM1_val; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.constant(MMIN_val, 64U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs2 + traits::X0, 0), - tu.constant(M1_val, 64U)))); - tu.store(tu.constant(MMIN_val, 64U), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.sdiv( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 64U)), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 68); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 69: DIVU */ - compile_ret_t __divu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DIVU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 69); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 64U))); - tu.store(tu.udiv( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 64U)), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 69); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 70: REM */ - compile_ret_t __rem(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("REM_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 70); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 64U))); - uint64_t M1_val = - 1; - uint32_t XLM1_val = 64 - 1; - uint64_t ONE_val = 1; - uint64_t MMIN_val = ONE_val << XLM1_val; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.constant(MMIN_val, 64U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs2 + traits::X0, 0), - tu.constant(M1_val, 64U)))); - tu.store(tu.constant(0, 64U), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.srem( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.load(rs1 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 70); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 71: REMU */ - compile_ret_t __remu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("REMU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 71); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 64U))); - tu.store(tu.urem( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.load(rs1 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 71); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 72: MULW */ - compile_ret_t __mulw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MULW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 72); - 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", "mulw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.ext( - tu.mul( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - )), - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 72); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 73: DIVW */ - compile_ret_t __divw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DIVW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 73); - 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", "divw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 64U))); - uint32_t M1_val = - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << 31; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.constant(MMIN_val, 32U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - ), - tu.constant(M1_val, 32U)))); - tu.store(tu.shl( - tu.neg(tu.constant(1, 64U)), - tu.constant(31, 64U)), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.ext( - tu.sdiv( - tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 64, false), - tu.ext( - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - ), - 64, false)), - 64, - false), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 64U)), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 73); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 74: DIVUW */ - compile_ret_t __divuw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DIVUW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 74); - 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", "divuw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - ), - tu.constant(0, 32U))); - tu.store(tu.ext( - tu.udiv( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - )), - 64, - false), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 64U)), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 74); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 75: REMW */ - compile_ret_t __remw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("REMW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 75); - 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", "remw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 64U))); - uint32_t M1_val = - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << 31; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.constant(MMIN_val, 32U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs2 + traits::X0, 0), - tu.constant(M1_val, 64U)))); - tu.store(tu.constant(0, 64U), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.ext( - tu.srem( - tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 64, false), - tu.ext( - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - ), - 64, false)), - 64, - false), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 64, - false), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 75); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 76: REMUW */ - compile_ret_t __remuw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("REMUW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 76); - 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", "remuw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - ), - tu.constant(0, 32U))); - tu.store(tu.ext( - tu.urem( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - )), - 64, - false), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 64, - false), rd + traits::X0); - tu.close_scope(); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 76); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 77: LR.W */ - compile_ret_t __lr_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LR_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 77); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), rd + traits::X0); - tu.write_mem( - traits::RES, - offs_val, - tu.trunc(tu.ext( - tu.neg(tu.constant(1, 8U)), - 32, - false), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 77); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 78: SC.W */ - compile_ret_t __sc_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SC_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 78); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res1_val = tu.assignment(tu.read_mem(traits::RES, offs_val, 32), 32); - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - res1_val, - tu.constant(0, 32U))); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - res1_val, - tu.ext( - tu.constant(0, 64U), - 32, - true)), - tu.constant(0, 64U), - tu.constant(1, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 78); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 79: AMOSWAP.W */ - compile_ret_t __amoswap_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOSWAP_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 79); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), rd + traits::X0); - } - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 79); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 80: AMOADD.W */ - compile_ret_t __amoadd_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOADD_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 80); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), 64); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.add( - res1_val, - tu.load(rs2 + traits::X0, 0)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 80); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 81: AMOXOR.W */ - compile_ret_t __amoxor_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOXOR_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 81); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), 64); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_xor( - res1_val, - tu.load(rs2 + traits::X0, 0)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 81); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 82: AMOAND.W */ - compile_ret_t __amoand_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOAND_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 82); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), 64); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_and( - res1_val, - tu.load(rs2 + traits::X0, 0)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 82); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 83: AMOOR.W */ - compile_ret_t __amoor_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOOR_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 83); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), 64); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_or( - res1_val, - tu.load(rs2 + traits::X0, 0)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 83); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 84: AMOMIN.W */ - compile_ret_t __amomin_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMIN_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 84); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), 64); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_SGT, - tu.ext( - res1_val, - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), - tu.load(rs2 + traits::X0, 0), - res1_val), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 84); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 85: AMOMAX.W */ - compile_ret_t __amomax_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMAX_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 85); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), 64); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - res1_val, - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), - tu.load(rs2 + traits::X0, 0), - res1_val), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 85); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 86: AMOMINU.W */ - compile_ret_t __amominu_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMINU_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 86); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), 64); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_UGT, - res1_val, - tu.load(rs2 + traits::X0, 0)), - tu.load(rs2 + traits::X0, 0), - res1_val), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 86); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 87: AMOMAXU.W */ - compile_ret_t __amomaxu_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMAXU_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 87); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), 64); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - res1_val, - tu.load(rs2 + traits::X0, 0)), - tu.load(rs2 + traits::X0, 0), - res1_val), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 87); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 88: LR.D */ - compile_ret_t __lr_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LR_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 88); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), rd + traits::X0); - tu.write_mem( - traits::RES, - offs_val, - tu.trunc(tu.ext( - tu.neg(tu.constant(1, 8U)), - 64, - false), 64)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 88); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 89: SC.D */ - compile_ret_t __sc_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SC_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 89); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sc.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res_val = tu.assignment(tu.read_mem(traits::RES, offs_val, 8), 64); - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - res_val, - tu.constant(0, 64U))); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 64));if(rd != 0){ - tu.store(tu.constant(0, 64U), rd + traits::X0); - } - tu(" }} else {{"); - if(rd != 0){ - tu.store(tu.constant(1, 64U), rd + traits::X0); - } - tu.close_scope(); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 89); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 90: AMOSWAP.D */ - compile_ret_t __amoswap_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOSWAP_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 90); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoswap.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), rd + traits::X0); - } - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 90); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 91: AMOADD.D */ - compile_ret_t __amoadd_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOADD_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 91); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), 64); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.add( - res_val, - tu.load(rs2 + traits::X0, 0)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 91); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 92: AMOXOR.D */ - compile_ret_t __amoxor_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOXOR_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 92); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoxor.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), 64); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_xor( - res_val, - tu.load(rs2 + traits::X0, 0)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 92); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 93: AMOAND.D */ - compile_ret_t __amoand_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOAND_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 93); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoand.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), 64); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_and( - res_val, - tu.load(rs2 + traits::X0, 0)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 93); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 94: AMOOR.D */ - compile_ret_t __amoor_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOOR_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 94); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoor.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), 64); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.l_or( - res_val, - tu.load(rs2 + traits::X0, 0)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 94); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 95: AMOMIN.D */ - compile_ret_t __amomin_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMIN_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 95); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomin.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), 64); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_SGT, - tu.ext( - res1_val, - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), - tu.load(rs2 + traits::X0, 0), - res1_val), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 95); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 96: AMOMAX.D */ - compile_ret_t __amomax_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMAX_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 96); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomax.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), 64); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - res_val, - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), - tu.load(rs2 + traits::X0, 0), - res_val), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 96); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 97: AMOMINU.D */ - compile_ret_t __amominu_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMINU_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 97); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amominu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), 64); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_UGT, - res_val, - tu.load(rs2 + traits::X0, 0)), - tu.load(rs2 + traits::X0, 0), - res_val), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 97); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 98: AMOMAXU.D */ - compile_ret_t __amomaxu_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AMOMAXU_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 98); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amomaxu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - auto res1_val = tu.assignment(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), 64); - if(rd != 0){ - tu.store(res1_val, rd + traits::X0); - } - auto res2_val = tu.assignment(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - res1_val, - tu.load(rs2 + traits::X0, 0)), - tu.load(rs2 + traits::X0, 0), - res1_val), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(res2_val, 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 98); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 99: FLW */ - compile_ret_t __flw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 99); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}({rs1})", fmt::arg("mnemonic", "flw"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - auto res_val = tu.assignment(tu.read_mem(traits::MEM, offs_val, 32), 32); - if(64 == 32){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 99); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 100: FSW */ - compile_ret_t __fsw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 100); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}({name(rs1)])", fmt::arg("mnemonic", "fsw"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.trunc( - tu.load(rs2 + traits::F0, 0), - 32 - ), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 100); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 101: FMADD.S */ - compile_ret_t __fmadd_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMADD_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 101); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fmadd_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.load(rs3 + traits::F0, 0), - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto frs3_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs3 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fmadd_s", - frs1_val, - frs2_val, - frs3_val, - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 101); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 102: FMSUB.S */ - compile_ret_t __fmsub_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMSUB_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 102); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fmadd_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.load(rs3 + traits::F0, 0), - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto frs3_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs3 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fmadd_s", - frs1_val, - frs2_val, - frs3_val, - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 102); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 103: FNMADD.S */ - compile_ret_t __fnmadd_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FNMADD_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 103); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} name(rd), f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.s"), - fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fmadd_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.load(rs3 + traits::F0, 0), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto frs3_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs3 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fmadd_s", - frs1_val, - frs2_val, - frs3_val, - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 103); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 104: FNMSUB.S */ - compile_ret_t __fnmsub_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FNMSUB_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 104); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fmadd_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.load(rs3 + traits::F0, 0), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto frs3_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs3 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fmadd_s", - frs1_val, - frs2_val, - frs3_val, - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 104); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 105: FADD.S */ - compile_ret_t __fadd_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FADD_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 105); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fadd_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fadd_s", - frs1_val, - frs2_val, - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 105); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 106: FSUB.S */ - compile_ret_t __fsub_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSUB_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 106); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fsub_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fsub_s", - frs1_val, - frs2_val, - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 106); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 107: FMUL.S */ - compile_ret_t __fmul_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMUL_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 107); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fmul_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fmul_s", - frs1_val, - frs2_val, - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 107); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 108: FDIV.S */ - compile_ret_t __fdiv_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FDIV_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 108); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fdiv_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fdiv_s", - frs1_val, - frs2_val, - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 108); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 109: FSQRT.S */ - compile_ret_t __fsqrt_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSQRT_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 109); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fsqrt_s", - tu.load(rs1 + traits::F0, 0), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fsqrt_s", - frs1_val, - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 109); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 110: FSGNJ.S */ - compile_ret_t __fsgnj_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJ_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 110); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.l_or( - tu.l_and( - tu.load(rs1 + traits::F0, 0), - tu.constant(0x7fffffff, 64U)), - tu.l_and( - tu.load(rs2 + traits::F0, 0), - tu.constant(0x80000000, 64U))), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.l_or( - tu.l_and( - frs1_val, - tu.constant(0x7fffffff, 32U)), - tu.l_and( - frs2_val, - tu.constant(0x80000000, 32U))), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 110); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 111: FSGNJN.S */ - compile_ret_t __fsgnjn_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJN_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 111); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.l_or( - tu.l_and( - tu.load(rs1 + traits::F0, 0), - tu.constant(0x7fffffff, 64U)), - tu.l_and( - tu.l_not(tu.load(rs2 + traits::F0, 0)), - tu.constant(0x80000000, 64U))), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.l_or( - tu.l_and( - frs1_val, - tu.constant(0x7fffffff, 32U)), - tu.l_and( - tu.l_not(frs2_val), - tu.constant(0x80000000, 32U))), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 111); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 112: FSGNJX.S */ - compile_ret_t __fsgnjx_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJX_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 112); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.l_xor( - tu.load(rs1 + traits::F0, 0), - tu.l_and( - tu.load(rs2 + traits::F0, 0), - tu.constant(0x80000000, 64U))), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.l_xor( - frs1_val, - tu.l_and( - frs2_val, - tu.constant(0x80000000, 32U))), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 112); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 113: FMIN.S */ - compile_ret_t __fmin_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMIN_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 113); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fsel_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fsel_s", - frs1_val, - frs2_val, - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 113); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 114: FMAX.S */ - compile_ret_t __fmax_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMAX_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 114); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fsel_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), rd + traits::F0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - auto res_val = tu.assignment(tu.callf("fsel_s", - frs1_val, - frs2_val, - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 114); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 115: FCVT.W.S */ - compile_ret_t __fcvt_w_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_W_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 115); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.ext( - tu.callf("fcvt_s", - tu.load(rs1 + traits::F0, 0), - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 64, - false), rd + traits::X0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - tu.store(tu.ext( - tu.callf("fcvt_s", - frs1_val, - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 64, - false), rd + traits::X0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 115); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 116: FCVT.WU.S */ - compile_ret_t __fcvt_wu_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_WU_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 116); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.ext( - tu.callf("fcvt_s", - tu.load(rs1 + traits::F0, 0), - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 64, - false), rd + traits::X0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - tu.store(tu.ext( - tu.callf("fcvt_s", - frs1_val, - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 64, - false), rd + traits::X0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 116); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 117: FEQ.S */ - compile_ret_t __feq_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FEQ_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 117); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.ext( - tu.callf("fcmp_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), - 64, - true), rd + traits::X0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - tu.store(tu.ext( - tu.callf("fcmp_s", - frs1_val, - frs2_val, - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), - 64, - true), rd + traits::X0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 117); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 118: FLT.S */ - compile_ret_t __flt_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLT_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 118); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.ext( - tu.callf("fcmp_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.ext( - tu.constant(2LL, 64U), - 32, - true) - ), - 64, - true), rd + traits::X0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - tu.store(tu.ext( - tu.callf("fcmp_s", - frs1_val, - frs2_val, - tu.ext( - tu.constant(2LL, 64U), - 32, - true) - ), - 64, - true), rd + traits::X0); - } - tu.store(tu.callf("fcmp_s", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 32 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 32 - ), - tu.ext( - tu.constant(2LL, 64U), - 32, - true) - ), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 118); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 119: FLE.S */ - compile_ret_t __fle_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLE_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 119); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.ext( - tu.callf("fcmp_s", - tu.load(rs1 + traits::F0, 0), - tu.load(rs2 + traits::F0, 0), - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), - 64, - true), rd + traits::X0); - } else { - auto frs1_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), 32); - auto frs2_val = tu.assignment(tu.callf("unbox_s", - tu.load(rs2 + traits::F0, 0) - ), 32); - tu.store(tu.ext( - tu.callf("fcmp_s", - frs1_val, - frs2_val, - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), - 64, - true), rd + traits::X0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 119); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 120: FCLASS.S */ - compile_ret_t __fclass_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCLASS_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 120); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.callf("fclass_s", - tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ) - ), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 120); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 121: FCVT.S.W */ - compile_ret_t __fcvt_s_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_S_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 121); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fcvt_s", - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), rd + traits::F0); - } else { - auto res_val = tu.assignment(tu.callf("fcvt_s", - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 121); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 122: FCVT.S.WU */ - compile_ret_t __fcvt_s_wu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_S_WU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 122); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.callf("fcvt_s", - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), rd + traits::F0); - } else { - auto res_val = tu.assignment(tu.callf("fcvt_s", - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 122); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 123: FMV.X.W */ - compile_ret_t __fmv_x_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMV_X_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 123); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fmv.x.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 32 - ), - 64, - false), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 123); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 124: FMV.W.X */ - compile_ret_t __fmv_w_x(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMV_W_X_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 124); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fmv.w.x"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(64 == 32){ - tu.store(tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 124); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 125: FCVT.L.S */ - compile_ret_t __fcvt_l_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_L_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 125); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.l.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fcvt_32_64", - tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 64); - tu.store(tu.ext( - res_val, - 64, - false), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 125); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 126: FCVT.LU.S */ - compile_ret_t __fcvt_lu_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_LU_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 126); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.lu.s"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fcvt_32_64", - tu.callf("unbox_s", - tu.load(rs1 + traits::F0, 0) - ), - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 64); - tu.store(tu.ext( - res_val, - 64, - true), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 126); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 127: FCVT.S.L */ - compile_ret_t __fcvt_s_l(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_S_L_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 127); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.l"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fcvt_64_32", - tu.load(rs1 + traits::X0, 0), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 32); - if(64 == 32){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 127); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 128: FCVT.S.LU */ - compile_ret_t __fcvt_s_lu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_S_LU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 128); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.lu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fcvt_64_32", - tu.load(rs1 + traits::X0, 0), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 32); - if(64 == 32){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 128); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 129: FLD */ - compile_ret_t __fld(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 129); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {imm}({rs1})", fmt::arg("mnemonic", "fld"), - fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - auto res_val = tu.assignment(tu.read_mem(traits::MEM, offs_val, 64), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 129); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 130: FSD */ - compile_ret_t __fsd(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 130); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {imm}({rs1})", fmt::arg("mnemonic", "fsd"), - fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 130); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 131: FMADD.D */ - compile_ret_t __fmadd_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMADD_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 131); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fmadd_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs3 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(0LL, 64U), - 64, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 131); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 132: FMSUB.D */ - compile_ret_t __fmsub_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMSUB_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 132); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fmadd_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs3 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 132); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 133: FNMADD.D */ - compile_ret_t __fnmadd_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FNMADD_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 133); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fmadd_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs3 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 133); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 134: FNMSUB.D */ - compile_ret_t __fnmsub_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FNMSUB_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 134); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rs3 = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fmadd_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs3 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 134); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 135: FADD.D */ - compile_ret_t __fadd_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FADD_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 135); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fadd_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 135); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 136: FSUB.D */ - compile_ret_t __fsub_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSUB_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 136); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fsub_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 136); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 137: FMUL.D */ - compile_ret_t __fmul_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMUL_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 137); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fmul_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 137); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 138: FDIV.D */ - compile_ret_t __fdiv_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FDIV_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 138); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fdiv_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 138); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 139: FSQRT.D */ - compile_ret_t __fsqrt_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSQRT_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 139); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fsqrt_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.constant(rm, 8U), - tu.constant(7, 8U)), - tu.constant(rm, 8U), - tu.trunc( - tu.load(traits::FCSR, 0), - 8 - )) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 139); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 140: FSGNJ.D */ - compile_ret_t __fsgnj_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJ_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 140); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - auto res_val = tu.assignment(tu.l_or( - tu.l_and( - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.constant(MSK2_val, 64U)), - tu.l_and( - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.constant(MSK1_val, 64U))), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 140); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 141: FSGNJN.D */ - compile_ret_t __fsgnjn_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJN_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 141); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - uint64_t MSK2_val = MSK1_val - 1; - auto res_val = tu.assignment(tu.l_or( - tu.l_and( - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.constant(MSK2_val, 64U)), - tu.l_and( - tu.l_not(tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - )), - tu.constant(MSK1_val, 64U))), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 141); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 142: FSGNJX.D */ - compile_ret_t __fsgnjx_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FSGNJX_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 142); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - uint64_t ONE_val = 1; - uint64_t MSK1_val = ONE_val << 63; - auto res_val = tu.assignment(tu.l_xor( - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.l_and( - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.constant(MSK1_val, 64U))), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 142); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 143: FMIN.D */ - compile_ret_t __fmin_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMIN_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 143); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fsel_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 143); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 144: FMAX.D */ - compile_ret_t __fmax_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMAX_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 144); - 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} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fsel_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 144); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 145: FCVT.S.D */ - compile_ret_t __fcvt_s_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_S_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 145); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.s.d"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fconv_d2f", - tu.load(rs1 + traits::F0, 0), - tu.constant(rm, 8U) - ), 32); - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(32, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 145); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 146: FCVT.D.S */ - compile_ret_t __fcvt_d_s(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_D_S_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 146); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.d.s"), - fmt::arg("rd", rd), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fconv_f2d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 32 - ), - tu.constant(rm, 8U) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 146); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 147: FEQ.D */ - compile_ret_t __feq_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FEQ_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 147); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcmp_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(0LL, 64U), - 32, - true) - ), - 64, - true), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 147); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 148: FLT.D */ - compile_ret_t __flt_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLT_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 148); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcmp_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(2LL, 64U), - 32, - true) - ), - 64, - true), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 148); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 149: FLE.D */ - compile_ret_t __fle_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FLE_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 149); - 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}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcmp_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(1LL, 64U), - 32, - true) - ), - 64, - true), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 149); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 150: FCLASS.D */ - compile_ret_t __fclass_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCLASS_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 150); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.callf("fclass_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ) - ), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 150); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 151: FCVT.W.D */ - compile_ret_t __fcvt_w_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_W_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 151); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcvt_64_32", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 64, - false), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 151); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 152: FCVT.WU.D */ - compile_ret_t __fcvt_wu_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_WU_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 152); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcvt_64_32", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 64, - false), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 152); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 153: FCVT.D.W */ - compile_ret_t __fcvt_d_w(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_D_W_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 153); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.w"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fcvt_32_64", - tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 64, - false), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 153); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 154: FCVT.D.WU */ - compile_ret_t __fcvt_d_wu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_D_WU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 154); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.wu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fcvt_32_64", - tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 64, - true), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 154); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 155: FCVT.L.D */ - compile_ret_t __fcvt_l_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_L_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 155); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.l.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcvt_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(0LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 64, - false), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 155); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 156: FCVT.LU.D */ - compile_ret_t __fcvt_lu_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_LU_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 156); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.lu.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.callf("fcvt_d", - tu.trunc( - tu.load(rs1 + traits::F0, 0), - 64 - ), - tu.ext( - tu.constant(1LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), - 64, - false), rd + traits::X0); - auto flags_val = tu.assignment(tu.callf("fget_flags" - ), 32); - auto FCSR_val_v = tu.assignment("FCSR_val", tu.add( - tu.l_and( - tu.load(traits::FCSR, 0), - tu.l_not(tu.constant(0x1f, 32U))), - flags_val), 32); - tu.store(FCSR_val_v, traits::FCSR); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 156); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 157: FCVT.D.L */ - compile_ret_t __fcvt_d_l(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_D_L_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 157); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.l"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fcvt_d", - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - false), - tu.ext( - tu.constant(2LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 157); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 158: FCVT.D.LU */ - compile_ret_t __fcvt_d_lu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FCVT_D_LU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 158); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rm = ((bit_sub<12,3>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.d.lu"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.callf("fcvt_d", - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), - tu.ext( - tu.constant(3LL, 64U), - 32, - true), - tu.constant(rm, 8U) - ), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 158); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 159: FMV.X.D */ - compile_ret_t __fmv_x_d(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMV_X_D_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 159); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fmv.x.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.load(rs1 + traits::F0, 0), - 64, - false), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 159); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 160: FMV.D.X */ - compile_ret_t __fmv_d_x(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FMV_D_X_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 160); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fmv.d.x"), - fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.store(tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), rd + traits::F0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 160); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 161: C.LD */ - compile_ret_t __c_ld(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 161); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm},({rs1})", fmt::arg("mnemonic", "c.ld"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), rd + 8 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 161); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 162: C.SD */ - compile_ret_t __c_sd(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 162); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm},({rs1})", fmt::arg("mnemonic", "c.sd"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + 8 + traits::X0, 0), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 162); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 163: C.LDSP */ - compile_ret_t __c_ldsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LDSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 163); - uint16_t uimm = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm}(sp)", fmt::arg("mnemonic", "c.ldsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 163); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 164: C.SDSP */ - compile_ret_t __c_sdsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SDSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 164); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint16_t uimm = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm}(sp)", fmt::arg("mnemonic", "c.sdsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 164); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 165: C.FLD */ - compile_ret_t __c_fld(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FLD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 165); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rd}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fld"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - auto res_val = tu.assignment(tu.read_mem(traits::MEM, offs_val, 64), 64); - if(64 == 64){ - tu.store(res_val, rd + 8 + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - res_val), rd + 8 + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 165); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 166: C.FSD */ - compile_ret_t __c_fsd(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FSD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 166); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f(8+{rs2}), {uimm}({rs1})", fmt::arg("mnemonic", "c.fsd"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.trunc( - tu.load(rs2 + 8 + traits::F0, 0), - 64 - ), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 166); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 167: C.FLDSP */ - compile_ret_t __c_fldsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FLDSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 167); - uint16_t uimm = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rd}, {uimm}(x2)", fmt::arg("mnemonic", "c.fldsp"), - fmt::arg("rd", rd), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - auto res_val = tu.assignment(tu.read_mem(traits::MEM, offs_val, 64), 64); - if(64 == 64){ - tu.store(res_val, rd + traits::F0); - } else { - uint64_t upper_val = - 1; - tu.store(tu.l_or( - tu.shl( - tu.constant(upper_val, 64U), - tu.constant(64, 64U)), - tu.ext( - res_val, - 64, - true)), rd + traits::F0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 167); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 168: C.FSDSP */ - compile_ret_t __c_fsdsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_FSDSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 168); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint16_t uimm = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} f{rs2}, {uimm}(x2), ", fmt::arg("mnemonic", "c.fsdsp"), - fmt::arg("rs2", rs2), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.trunc( - tu.load(rs2 + traits::F0, 0), - 64 - ), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 168); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 169: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI4SPN_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 169); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(imm, 64U)), rd + 8 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 169); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 170: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 170); - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), rd + 8 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 170); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 171: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 171); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + 8 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 171); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 172: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 172); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), rs1 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 172); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 173: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_NOP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 173); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.nop"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.close_scope(); - /* TODO: describe operations for C.NOP ! */ - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 173); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 174: C.ADDIW */ - compile_ret_t __c_addiw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDIW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 174); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addiw"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rs1 != 0){ - auto res_val = tu.assignment(tu.add( - tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(tu.ext( - res_val, - 64, - false), rs1 + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 174); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 175: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 175); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.constant(imm, 64U), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 175); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 176: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 176); - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); - } - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.constant(imm, 64U), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 176); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 177: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI16SP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 177); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(2 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 2 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 177); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 178: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 178); - uint8_t shamt = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.lshr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 64U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 178); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 179: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 179); - uint8_t shamt = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.ashr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 64U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 179); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 180: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 180); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.l_and( - tu.ext( - tu.load(rs1_idx_val + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), rs1_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 180); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 181: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 181); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.sub( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 181); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 182: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 182); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_xor( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 182); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 183: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 183); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_or( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 183); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 184: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 184); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_and( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 184); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 185: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_J_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 185); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 185); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 186: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BEQZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 186); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 64U)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(2, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 186); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 187: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BNEZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 187); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 64U)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(2, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 187); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 188: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 188); - uint8_t shamt = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - if(rs1 == 0){ - this->gen_raise_trap(tu, 0, 2); - } - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 64U)), rs1 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 188); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 189: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 189); - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 189); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 190: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_MV_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 190); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.load(rs2 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 190); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 191: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 191); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 64); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 191); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 192: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 192); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - tu.load(rd + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 192); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 193: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 193); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - tu.store(tu.add( - cur_pc_val, - tu.constant(2, 64U)), 1 + traits::X0); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 64); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 193); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 194: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 194); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.ebreak"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 194); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 195: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 195); - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 195); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 196: DII */ - compile_ret_t __dii(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("DII_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 196); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "dii"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 2); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 196); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 197: C.SUBW */ - compile_ret_t __c_subw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SUBW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 197); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.subw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto res_val = tu.assignment(tu.sub( - tu.trunc( - tu.load(rd + 8 + traits::X0, 0), - 32 - ), - tu.trunc( - tu.load(rs2 + 8 + traits::X0, 0), - 32 - )), 32); - tu.store(tu.ext( - res_val, - 64, - false), rd + 8 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 197); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 198: C.ADDW */ - compile_ret_t __c_addw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 198); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rd}, {rs2}", fmt::arg("mnemonic", "c.addw"), - fmt::arg("rd", name(8+rd)), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; - tu.open_scope(); - auto res_val = tu.assignment(tu.add( - tu.trunc( - tu.load(rd + 8 + traits::X0, 0), - 32 - ), - tu.trunc( - tu.load(rs2 + 8 + traits::X0, 0), - 32 - )), 32); - tu.store(tu.ext( - res_val, - 64, - false), rd + 8 + traits::X0); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 198); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 199: C.SRLI64 */ - compile_ret_t __c_srli64(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, tu_builder& tu) { - vm_impl::gen_sync(tu, iss::PRE_SYNC, instr_descr.size()); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - gen_raise_trap(tu, 0, 2); // illegal instruction trap - vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size()); - vm_impl::gen_trap_check(tu); - return BRANCH; - } -}; - -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 -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, tu); -} - -template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { - tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); -} - -template void vm_impl::gen_leave_trap(tu_builder& tu, unsigned lvl) { - tu("leave_trap(core_ptr, {});", lvl); - tu.store(tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN),traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); -} - -template void vm_impl::gen_wait(tu_builder& tu, unsigned type) { -} - -template void vm_impl::gen_trap_behavior(tu_builder& tu) { - tu("trap_entry:"); - tu("enter_trap(core_ptr, *trap_state, *pc);"); - tu.store(tu.constant(std::numeric_limits::max(),32),traits::LAST_BRANCH); - tu("return *next_pc;"); -} - -} // namespace mnrv32 - -template <> -std::unique_ptr create(arch::rv64gc *core, unsigned short port, bool dump) { - auto ret = new rv64gc::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} -} // namespace iss diff --git a/src/vm/tcc/vm_rv64i.cpp b/src/vm/tcc/vm_rv64i.cpp deleted file mode 100644 index 4080a49..0000000 --- a/src/vm/tcc/vm_rv64i.cpp +++ /dev/null @@ -1,2548 +0,0 @@ -/******************************************************************************* - * Copyright (C) 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 -#include -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace tcc { -namespace rv64i { -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::tcc::vm_base { -public: - using super = typename iss::tcc::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 tu_builder = typename super::tu_builder; - - 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 (vm_base::tgt_adapter == nullptr) - vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm_base::tgt_adapter; - } - -protected: - using vm_base::get_reg_ptr; - - using this_class = vm_impl; - using compile_ret_t = std::tuple; - using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&); - - inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - void setup_module(std::string m) override { - super::setup_module(m); - } - - compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, tu_builder&) override; - - void gen_trap_behavior(tu_builder& tu) override; - - void gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(tu_builder& tu, unsigned lvl); - - void gen_wait(tu_builder& tu, unsigned type); - - inline void gen_trap_check(tu_builder& tu) { - tu("if(*trap_state!=0) goto trap_entry;"); - } - - inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) { - switch(reg_num){ - case traits::NEXT_PC: - tu("*next_pc = {:#x};", pc.val); - break; - case traits::PC: - tu("*pc = {:#x};", pc.val); - break; - default: - if(!tu.defined_regs[reg_num]){ - tu("reg_t* reg{:02d} = (reg_t*){:#x};", reg_num, reinterpret_cast(get_reg_ptr(reg_num))); - tu.defined_regs[reg_num]=true; - } - tu("*reg{:02d} = {:#x};", reg_num, pc.val); - } - } - - // 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; - } - -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, encoding '.........................0110111' */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC, encoding '.........................0010111' */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL, encoding '.........................1101111' */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR, encoding '.................000.....1100111' */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ, encoding '.................000.....1100011' */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE, encoding '.................001.....1100011' */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT, encoding '.................100.....1100011' */ - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE, encoding '.................101.....1100011' */ - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU, encoding '.................110.....1100011' */ - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU, encoding '.................111.....1100011' */ - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB, encoding '.................000.....0000011' */ - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH, encoding '.................001.....0000011' */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW, encoding '.................010.....0000011' */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU, encoding '.................100.....0000011' */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU, encoding '.................101.....0000011' */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB, encoding '.................000.....0100011' */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH, encoding '.................001.....0100011' */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW, encoding '.................010.....0100011' */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI, encoding '.................000.....0010011' */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI, encoding '.................010.....0010011' */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU, encoding '.................011.....0010011' */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI, encoding '.................100.....0010011' */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI, encoding '.................110.....0010011' */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI, encoding '.................111.....0010011' */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction ADD, encoding '0000000..........000.....0110011' */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB, encoding '0100000..........000.....0110011' */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL, encoding '0000000..........001.....0110011' */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT, encoding '0000000..........010.....0110011' */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU, encoding '0000000..........011.....0110011' */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR, encoding '0000000..........100.....0110011' */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL, encoding '0000000..........101.....0110011' */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA, encoding '0100000..........101.....0110011' */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR, encoding '0000000..........110.....0110011' */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND, encoding '0000000..........111.....0110011' */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE, encoding '0000.............000.....0001111' */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I, encoding '.................001.....0001111' */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL, encoding '00000000000000000000000001110011' */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK, encoding '00000000000100000000000001110011' */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET, encoding '00000000001000000000000001110011' */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET, encoding '00010000001000000000000001110011' */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET, encoding '00110000001000000000000001110011' */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI, encoding '00010000010100000000000001110011' */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA, encoding '0001001..........000000001110011' */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW, encoding '.................001.....1110011' */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS, encoding '.................010.....1110011' */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC, encoding '.................011.....1110011' */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI, encoding '.................101.....1110011' */ - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI, encoding '.................110.....1110011' */ - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI, encoding '.................111.....1110011' */ - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction LWU, encoding '.................110.....0000011' */ - {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, - /* instruction LD, encoding '.................011.....0000011' */ - {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, &this_class::__ld}, - /* instruction SD, encoding '.................011.....0100011' */ - {32, 0b00000000000000000011000000100011, 0b00000000000000000111000001111111, &this_class::__sd}, - /* instruction SLLI, encoding '000000...........001.....0010011' */ - {32, 0b00000000000000000001000000010011, 0b11111100000000000111000001111111, &this_class::__slli}, - /* instruction SRLI, encoding '000000...........101.....0010011' */ - {32, 0b00000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srli}, - /* instruction SRAI, encoding '010000...........101.....0010011' */ - {32, 0b01000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srai}, - /* instruction ADDIW, encoding '.................000.....0011011' */ - {32, 0b00000000000000000000000000011011, 0b00000000000000000111000001111111, &this_class::__addiw}, - /* instruction SLLIW, encoding '0000000..........001.....0011011' */ - {32, 0b00000000000000000001000000011011, 0b11111110000000000111000001111111, &this_class::__slliw}, - /* instruction SRLIW, encoding '0000000..........101.....0011011' */ - {32, 0b00000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__srliw}, - /* instruction SRAIW, encoding '0100000..........101.....0011011' */ - {32, 0b01000000000000000101000000011011, 0b11111110000000000111000001111111, &this_class::__sraiw}, - /* instruction ADDW, encoding '0000000..........000.....0111011' */ - {32, 0b00000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__addw}, - /* instruction SUBW, encoding '0100000..........000.....0111011' */ - {32, 0b01000000000000000000000000111011, 0b11111110000000000111000001111111, &this_class::__subw}, - /* instruction SLLW, encoding '0000000..........001.....0111011' */ - {32, 0b00000000000000000001000000111011, 0b11111110000000000111000001111111, &this_class::__sllw}, - /* instruction SRLW, encoding '0000000..........101.....0111011' */ - {32, 0b00000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__srlw}, - /* instruction SRAW, encoding '0100000..........101.....0111011' */ - {32, 0b01000000000000000101000000111011, 0b11111110000000000111000001111111, &this_class::__sraw}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 0); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.constant(imm, 64U), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 0); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 1: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AUIPC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 1); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 1); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 2: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 2); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 64U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 2); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 3: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 3); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto new_pc_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - auto align_val = tu.assignment(tu.l_and( - new_pc_val, - tu.constant(0x2, 64U)), 64); - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - align_val, - tu.constant(0, 64U))); - this->gen_raise_trap(tu, 0, 0); - tu(" }} else {{"); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 64U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.l_and( - new_pc_val, - tu.l_not(tu.constant(0x1, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32U), traits::LAST_BRANCH); - tu.close_scope(); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 3); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 4: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BEQ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 4); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 4); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 5: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BNE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 5); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 5); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 6: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 6); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 6); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 7: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 7); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SGE, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 7); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 8: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 8); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 8); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 9: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGEU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 9); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_UGE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 64, false), - tu.constant(imm, 64U)), - tu.add( - cur_pc_val, - tu.constant(4, 64U))), 64); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 64U, true), tu.constant(pc.val, 64U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(is_cont_v, traits::LAST_BRANCH); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 9); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 10: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 10); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 10); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 11: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 11); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 11); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 12: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 12); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 12); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 13: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LBU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 13); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 64, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 13); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 14: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 14); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 64, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 14); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 15: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 15); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 8)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 15); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 16: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 16); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 16)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 16); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 17: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 17); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 17); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 18: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 18); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 18); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 19: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 19); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), - tu.constant(1, 64U), - tu.constant(0, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 19); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 20: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTIU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 20); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - int64_t full_imm_val = imm; - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.constant(full_imm_val, 64U)), - tu.constant(1, 64U), - tu.constant(0, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 20); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 21: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 21); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 21); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 22: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 22); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 22); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 23: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 23); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 23); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 24: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 24); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 24); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 25: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 25); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.sub( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 25); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 26: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 26); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(64, 64U), - tu.constant(1, 64U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 26); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 27: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, false)), - tu.constant(1, 64U), - tu.constant(0, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 27); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 28: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), - tu.constant(1, 64U), - tu.constant(0, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 28); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 29: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 29); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 30: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(64, 64U), - tu.constant(1, 64U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 30); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 31: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(64, 64U), - tu.constant(1, 64U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 31); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 32: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 32); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 33: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, 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", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 33); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 34: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 34); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(0, 64U), - tu.trunc(tu.l_or( - tu.shl( - tu.constant(pred, 64U), - tu.constant(4, 64U)), - tu.constant(succ, 64U)), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 34); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 35: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_I_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 35); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence_i"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(1, 64U), - tu.trunc(tu.constant(imm, 64U), 64)); - tu.close_scope(); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 35); - gen_trap_check(tu); - return std::make_tuple(FLUSH); - } - - /* instruction 36: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ECALL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 36); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ecall"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 11); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 36); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 37: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 37); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ebreak"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 37); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 38: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("URET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 38); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "uret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 0); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 38); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 39: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 39); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 1); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 39); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 40: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 40); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "mret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 40); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 41: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("WFI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 41); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "wfi"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_wait(tu, 1); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 41); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 42: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SFENCE_VMA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 42); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sfence.vma"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(2, 64U), - tu.trunc(tu.constant(rs1, 64U), 64)); - tu.write_mem( - traits::FENCE, - tu.constant(3, 64U), - tu.trunc(tu.constant(rs2, 64U), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 42); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 43: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 43); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto rs_val_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - if(rd != 0){ - auto csr_val_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 64)); - tu.store(csr_val_val, rd + traits::X0); - } else { - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 64)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 43); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 44: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRS_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 44); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - xrd_val, - xrs1_val), 64)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 44); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 45: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 45); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - 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))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 64); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - xrd_val, - tu.l_not(xrs1_val)), 64)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 45); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 46: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRWI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 46); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), rd + traits::X0); - } - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.ext( - tu.constant(zimm, 64U), - 64, - true), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 46); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 47: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRSI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 47); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - res_val, - tu.ext( - tu.constant(zimm, 64U), - 64, - true)), 64)); - } - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 47); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 48: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRCI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 48); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - 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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - res_val, - tu.l_not(tu.ext( - tu.constant(zimm, 64U), - 64, - true))), 64)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 48); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 49: LWU */ - compile_ret_t __lwu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LWU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 49); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lwu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 64, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 49); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 50: LD */ - compile_ret_t __ld(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 50); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "ld"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 64), - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 50); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 51: SD */ - compile_ret_t __sd(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 51); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sd"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, false), - tu.constant(imm, 64U)), 64); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 64)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 51); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 52: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 52); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,6>(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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 52); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 53: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 53); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,6>(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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 53); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 54: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 54); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,6>(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)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 64U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 54); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 55: ADDIW */ - compile_ret_t __addiw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADDIW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 55); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.add( - tu.ext( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(tu.ext( - res_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 55); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 56: SLLIW */ - compile_ret_t __slliw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLLIW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 56); - 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", "slliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto sh_val_val = tu.assignment(tu.shl( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.constant(shamt, 32U)), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 56); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 57: SRLIW */ - compile_ret_t __srliw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRLIW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 57); - 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", "srliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto sh_val_val = tu.assignment(tu.lshr( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.constant(shamt, 32U)), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 57); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 58: SRAIW */ - compile_ret_t __sraiw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRAIW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 58); - 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", "sraiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto sh_val_val = tu.assignment(tu.ashr( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.constant(shamt, 32U)), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 58); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 59: ADDW */ - compile_ret_t __addw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADDW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 59); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "addw"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.add( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - )), 32); - tu.store(tu.ext( - res_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 59); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 60: SUBW */ - compile_ret_t __subw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SUBW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 60); - 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 */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "subw"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.sub( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - )), 32); - tu.store(tu.ext( - res_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 60); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 61: SLLW */ - compile_ret_t __sllw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLLW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 61); - 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", "sllw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = tu.assignment(tu.l_and( - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - ), - tu.constant(mask_val, 32U)), 32); - auto sh_val_val = tu.assignment(tu.shl( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - count_val), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 61); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 62: SRLW */ - compile_ret_t __srlw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRLW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 62); - 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", "srlw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = tu.assignment(tu.l_and( - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - ), - tu.constant(mask_val, 32U)), 32); - auto sh_val_val = tu.assignment(tu.lshr( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - count_val), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 62); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 63: SRAW */ - compile_ret_t __sraw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRAW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 63); - 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", "sraw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - uint32_t mask_val = 0x1f; - auto count_val = tu.assignment(tu.l_and( - tu.trunc( - tu.load(rs2 + traits::X0, 0), - 32 - ), - tu.constant(mask_val, 32U)), 32); - auto sh_val_val = tu.assignment(tu.ashr( - tu.trunc( - tu.load(rs1 + traits::X0, 0), - 32 - ), - count_val), 32); - tu.store(tu.ext( - sh_val_val, - 64, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 63); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, tu_builder& tu) { - vm_impl::gen_sync(tu, iss::PRE_SYNC, instr_descr.size()); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - gen_raise_trap(tu, 0, 2); // illegal instruction trap - vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size()); - vm_impl::gen_trap_check(tu); - return BRANCH; - } -}; - -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 -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, tu); -} - -template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { - tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); -} - -template void vm_impl::gen_leave_trap(tu_builder& tu, unsigned lvl) { - tu("leave_trap(core_ptr, {});", lvl); - tu.store(tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN),traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); -} - -template void vm_impl::gen_wait(tu_builder& tu, unsigned type) { -} - -template void vm_impl::gen_trap_behavior(tu_builder& tu) { - tu("trap_entry:"); - tu("enter_trap(core_ptr, *trap_state, *pc);"); - tu.store(tu.constant(std::numeric_limits::max(),32),traits::LAST_BRANCH); - tu("return *next_pc;"); -} - -} // namespace mnrv32 - -template <> -std::unique_ptr create(arch::rv64i *core, unsigned short port, bool dump) { - auto ret = new rv64i::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} -} // namespace iss diff --git a/src/vm/tcc/vm_tgf01.cpp b/src/vm/tcc/vm_tgf01.cpp index 02996cc..3ba3109 100644 --- a/src/vm/tcc/vm_tgf01.cpp +++ b/src/vm/tcc/vm_tgf01.cpp @@ -31,7 +31,7 @@ *******************************************************************************/ #include -#include +#include #include #include #include diff --git a/src/vm/tcc/vm_tgf02.cpp b/src/vm/tcc/vm_tgf02.cpp index 7813c5c..66428b8 100644 --- a/src/vm/tcc/vm_tgf02.cpp +++ b/src/vm/tcc/vm_tgf02.cpp @@ -31,7 +31,7 @@ *******************************************************************************/ #include -#include +#include #include #include #include