diff --git a/CMakeLists.txt b/CMakeLists.txt index 13c15d3..c0e72ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,19 +44,28 @@ 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/rv32gc.cpp src/iss/rv32imac.cpp - #src/iss/rv64i.cpp - #src/iss/rv64gc.cpp + src/iss/rv64i.cpp + src/iss/rv64gc.cpp src/iss/mnrv32.cpp - src/vm/llvm/fp_functions.cpp + src/vm/fp_functions.cpp + 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_rv32gc.cpp + src/vm/llvm/vm_rv32imac.cpp + src/vm/llvm/vm_rv64i.cpp + src/vm/llvm/vm_rv64gc.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/plugin/instruction_count.cpp src/plugin/cycle_estimate.cpp) diff --git a/gen_input/RVF.core_desc b/gen_input/RVF.core_desc index 5134b87..f45fcb5 100644 --- a/gen_input/RVF.core_desc +++ b/gen_input/RVF.core_desc @@ -376,7 +376,7 @@ InsructionSet RV64F extends RV32F{ FCVT.S.L { // 64bit signed int to to fp encoding: b1101000 | b00010 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; args_disass:"f{rd}, x{rs1}"; - val res[32] <= fdispatch_fcvt_64_32(X[rs1], zext(2, 32)); + val res[32] <= fdispatch_fcvt_64_32(X[rs1], zext(2, 32), rm{8}); if(FLEN==32) F[rd] <= res; else { // NaN boxing @@ -387,7 +387,7 @@ InsructionSet RV64F extends RV32F{ FCVT.S.LU { // 64bit unsigned int to to fp encoding: b1101000 | b00011 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; args_disass:"f{rd}, x{rs1}"; - val res[32] <=fdispatch_fcvt_64_32(X[rs1], zext(3,32)); + val res[32] <=fdispatch_fcvt_64_32(X[rs1], zext(3,32), rm{8}); if(FLEN==32) F[rd] <= res; else { // NaN boxing diff --git a/gen_input/minres_rv.core_desc b/gen_input/minres_rv.core_desc index 14ddd6f..70302c8 100644 --- a/gen_input/minres_rv.core_desc +++ b/gen_input/minres_rv.core_desc @@ -17,7 +17,7 @@ Core MNRV32 provides RV32I, RV32IC { PGMASK := 0xfff; //PGSIZE-1 } } -/* + Core RV32IMAC provides RV32I, RV32M, RV32A, RV32IC { constants { XLEN:=32; @@ -67,4 +67,4 @@ Core RV64GC provides RV64I, RV64M, RV64A, RV64F, RV64D, RV64IC, RV32FC, RV32DC { PGMASK := 0xfff; //PGSIZE-1 } } -*/ + diff --git a/gen_input/templates/interp/incl-CORENAME.h.gtl b/gen_input/templates/interp/incl-CORENAME.h.gtl index 139d39d..0a5b99f 100644 --- a/gen_input/templates/interp/incl-CORENAME.h.gtl +++ b/gen_input/templates/interp/incl-CORENAME.h.gtl @@ -172,6 +172,8 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { 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<${coreDef.name.toLowerCase()}>::MEM || addr.type == iss::address_type::PHYSICAL || addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { @@ -204,7 +206,7 @@ protected: std::array addr_mode; - bool interrupt_sim=false; + uint64_t interrupt_sim=0; <% def fcsr = allRegs.find {it.name=='FCSR'} if(fcsr != null) {%> diff --git a/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl index 35a3ca7..85dd233 100644 --- a/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/interp/vm-vm_CORENAME.cpp.gtl @@ -30,6 +30,7 @@ * *******************************************************************************/ +#include "../fp_functions.h" #include #include #include diff --git a/gen_input/templates/llvm/incl-CORENAME.h.gtl b/gen_input/templates/llvm/incl-CORENAME.h.gtl index 139d39d..0a5b99f 100644 --- a/gen_input/templates/llvm/incl-CORENAME.h.gtl +++ b/gen_input/templates/llvm/incl-CORENAME.h.gtl @@ -172,6 +172,8 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { 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<${coreDef.name.toLowerCase()}>::MEM || addr.type == iss::address_type::PHYSICAL || addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { @@ -204,7 +206,7 @@ protected: std::array addr_mode; - bool interrupt_sim=false; + uint64_t interrupt_sim=0; <% def fcsr = allRegs.find {it.name=='FCSR'} if(fcsr != null) {%> diff --git a/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl index e041cb4..34b618d 100644 --- a/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl @@ -57,7 +57,7 @@ using namespace ::llvm; using namespace iss::arch; using namespace iss::debugger; -template class vm_impl : public vm::llvm::vm_base { +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; diff --git a/incl/iss/arch/rv32gc.h b/incl/iss/arch/rv32gc.h index 649a4c5..36ebf25 100644 --- a/incl/iss/arch/rv32gc.h +++ b/incl/iss/arch/rv32gc.h @@ -215,6 +215,8 @@ struct rv32gc: public arch_if { 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) { @@ -304,7 +306,7 @@ protected: std::array addr_mode; - bool interrupt_sim=false; + uint64_t interrupt_sim=0; uint32_t get_fcsr(){return reg.FCSR;} void set_fcsr(uint32_t val){reg.FCSR = val;} diff --git a/incl/iss/arch/rv32imac.h b/incl/iss/arch/rv32imac.h index d187084..0504d79 100644 --- a/incl/iss/arch/rv32imac.h +++ b/incl/iss/arch/rv32imac.h @@ -182,6 +182,8 @@ struct rv32imac: public arch_if { 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) { @@ -238,7 +240,7 @@ protected: std::array addr_mode; - bool interrupt_sim=false; + uint64_t interrupt_sim=0; uint32_t get_fcsr(){return 0;} void set_fcsr(uint32_t val){} diff --git a/incl/iss/arch/rv64gc.h b/incl/iss/arch/rv64gc.h index b10843d..83a23ba 100644 --- a/incl/iss/arch/rv64gc.h +++ b/incl/iss/arch/rv64gc.h @@ -215,6 +215,8 @@ struct rv64gc: public arch_if { 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) { @@ -304,7 +306,7 @@ protected: std::array addr_mode; - bool interrupt_sim=false; + uint64_t interrupt_sim=0; uint32_t get_fcsr(){return reg.FCSR;} void set_fcsr(uint32_t val){reg.FCSR = val;} diff --git a/incl/iss/arch/rv64i.h b/incl/iss/arch/rv64i.h index 2f6c2bf..e13b0c4 100644 --- a/incl/iss/arch/rv64i.h +++ b/incl/iss/arch/rv64i.h @@ -182,6 +182,8 @@ struct rv64i: public arch_if { 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) { @@ -238,7 +240,7 @@ protected: std::array addr_mode; - bool interrupt_sim=false; + uint64_t interrupt_sim=0; uint32_t get_fcsr(){return 0;} void set_fcsr(uint32_t val){} diff --git a/src/main.cpp b/src/main.cpp index fc63ae3..c122f8f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,6 +36,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -44,6 +48,21 @@ namespace po = boost::program_options; +using cpu_ptr = std::unique_ptr; +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(); + if(backend == "interp") + return {cpu_ptr{lcpu}, vm_ptr{iss::interp::create(lcpu, gdb_port)}}; + if(backend == "llvm") + return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}}; + if(backend == "tcc") + return {cpu_ptr{lcpu}, vm_ptr{iss::tcc::create(lcpu, gdb_port)}}; + return {nullptr, nullptr}; +} + int main(int argc, char *argv[]) { /* * Define and parse the program options @@ -104,17 +123,23 @@ int main(int argc, char *argv[]) { iss::init_jit_debug(argc, argv); bool dump = clim.count("dump-ir"); // instantiate the simulator - std::unique_ptr vm{nullptr}; - std::unique_ptr cpu{nullptr}; + vm_ptr vm{nullptr}; + cpu_ptr cpu{nullptr}; std::string isa_opt(clim["isa"].as()); - iss::arch::mnrv32* lcpu = new iss::arch::riscv_hart_msu_vp(); - if(clim["backend"].as() == "interp") - vm = iss::interp::create(lcpu, clim["gdb-port"].as()); - if(clim["backend"].as() == "llvm") - vm = iss::llvm::create(lcpu, clim["gdb-port"].as()); - if(clim["backend"].as() == "tcc") - vm = iss::tcc::create(lcpu, clim["gdb-port"].as()); - cpu.reset(lcpu); + 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()); + } else { + LOG(ERROR) << "Illegal argument value for '--isa': " << clim["isa"].as() << std::endl; + return 127; + } if (clim.count("plugin")) { for (std::string opt_val : clim["plugin"].as>()) { std::string plugin_name{opt_val}; diff --git a/src/vm/llvm/fp_functions.cpp b/src/vm/fp_functions.cpp similarity index 78% rename from src/vm/llvm/fp_functions.cpp rename to src/vm/fp_functions.cpp index ce5bc66..991a459 100644 --- a/src/vm/llvm/fp_functions.cpp +++ b/src/vm/fp_functions.cpp @@ -32,8 +32,7 @@ // eyck@minres.com - initial API and implementation //////////////////////////////////////////////////////////////////////////////// -#include -#include +#include "fp_functions.h" extern "C" { #include @@ -43,71 +42,6 @@ extern "C" { #include -namespace iss { -namespace llvm { -namespace fp_impl { - -using namespace std; -using namespace ::llvm; - -#define INT_TYPE(L) Type::getIntNTy(mod->getContext(), L) -#define FLOAT_TYPE Type::getFloatTy(mod->getContext()) -#define DOUBLE_TYPE Type::getDoubleTy(mod->getContext()) -#define VOID_TYPE Type::getVoidTy(mod->getContext()) -#define THIS_PTR_TYPE Type::getIntNPtrTy(mod->getContext(), 8) -#define FDECLL(NAME, RET, ...) \ - Function *NAME##_func = CurrentModule->getFunction(#NAME); \ - if (!NAME##_func) { \ - std::vector NAME##_args{__VA_ARGS__}; \ - FunctionType *NAME##_type = FunctionType::get(RET, NAME##_args, false); \ - NAME##_func = Function::Create(NAME##_type, GlobalValue::ExternalLinkage, #NAME, CurrentModule); \ - NAME##_func->setCallingConv(CallingConv::C); \ - } - -#define FDECL(NAME, RET, ...) \ - std::vector NAME##_args{__VA_ARGS__}; \ - FunctionType *NAME##_type = FunctionType::get(RET, NAME##_args, false); \ - mod->getOrInsertFunction(#NAME, NAME##_type); - - -void add_fp_functions_2_module(Module *mod, uint32_t flen, uint32_t xlen) { - if(flen){ - FDECL(fget_flags, INT_TYPE(32)); - FDECL(fadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); - FDECL(fsub_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); - FDECL(fmul_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); - FDECL(fdiv_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); - FDECL(fsqrt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); - FDECL(fcmp_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); - FDECL(fcvt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); - FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); - FDECL(fsel_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); - FDECL(fclass_s, INT_TYPE(32), INT_TYPE(32)); - FDECL(fcvt_32_64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); - FDECL(fcvt_64_32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); - if(flen>32){ - FDECL(fconv_d2f, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8)); - FDECL(fconv_f2d, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); - FDECL(fadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); - FDECL(fsub_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); - FDECL(fmul_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); - FDECL(fdiv_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); - FDECL(fsqrt_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); - FDECL(fcmp_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); - FDECL(fcvt_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); - FDECL(fmadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); - FDECL(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); - FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64)); - FDECL(unbox_s, INT_TYPE(32), INT_TYPE(64)); - - } - } -} - -} -} -} - using this_t = uint8_t *; const uint8_t rmm_map[] = { softfloat_round_near_even /*RNE*/, diff --git a/src/vm/fp_functions.h b/src/vm/fp_functions.h new file mode 100644 index 0000000..fe03f7b --- /dev/null +++ b/src/vm/fp_functions.h @@ -0,0 +1,68 @@ +//////////////////////////////////////////////////////////////////////////////// +// 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. +// +// Contributors: +// eyck@minres.com - initial API and implementation +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _VM_FP_FUNCTIONS_H_ +#define _VM_FP_FUNCTIONS_H_ + +#include + +extern "C" { +uint32_t fget_flags(); +uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode); +uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode); +uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode); +uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode); +uint32_t fsqrt_s(uint32_t v1, uint8_t mode); +uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) ; +uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode); +uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode); +uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op); +uint32_t fclass_s( uint32_t v1 ); +uint32_t fconv_d2f(uint64_t v1, uint8_t mode); +uint64_t fconv_f2d(uint32_t v1, uint8_t mode); +uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode); +uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode); +uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode); +uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode); +uint64_t fsqrt_d(uint64_t v1, uint8_t mode); +uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op); +uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode); +uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode); +uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op) ; +uint64_t fclass_d(uint64_t v1 ); +uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode); +uint32_t fcvt_64_32(uint64_t v1, uint32_t op, uint8_t mode); +uint32_t unbox_s(uint64_t v); +} +#endif /* RISCV_SRC_VM_FP_FUNCTIONS_H_ */ diff --git a/src/vm/interp/vm_mnrv32.cpp b/src/vm/interp/vm_mnrv32.cpp index f0cf95c..f37e6eb 100644 --- a/src/vm/interp/vm_mnrv32.cpp +++ b/src/vm/interp/vm_mnrv32.cpp @@ -30,6 +30,7 @@ * *******************************************************************************/ +#include "../fp_functions.h" #include #include #include diff --git a/src/vm/interp/vm_rv32gc.cpp b/src/vm/interp/vm_rv32gc.cpp new file mode 100644 index 0000000..2131227 --- /dev/null +++ b/src/vm/interp/vm_rv32gc.cpp @@ -0,0 +1,6839 @@ +/******************************************************************************* + * 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 new file mode 100644 index 0000000..5d4a379 --- /dev/null +++ b/src/vm/interp/vm_rv32imac.cpp @@ -0,0 +1,3793 @@ +/******************************************************************************* + * 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 new file mode 100644 index 0000000..4e404f8 --- /dev/null +++ b/src/vm/interp/vm_rv64gc.cpp @@ -0,0 +1,8694 @@ +/******************************************************************************* + * 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_rv64i.cpp new file mode 100644 index 0000000..3a65771 --- /dev/null +++ b/src/vm/interp/vm_rv64i.cpp @@ -0,0 +1,2518 @@ +/******************************************************************************* + * 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 rv64i { +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, 0b11111100000000000111000001111111, &this_class::__slli}, + /* instruction SRLI */ + {32, 0b00000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srli}, + /* instruction SRAI */ + {32, 0b01000000000000000101000000010011, 0b11111100000000000111000001111111, &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 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)); + auto align_val = (new_pc_val & 0x2); + { + if((align_val != 0)) { + raise_trap(0, 0); + } + else { + 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,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)); + this->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)<<(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,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)); + this->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))>>(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,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)); + this->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))>>(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; + } + + /**************************************************************************** + * 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::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 interp +} // namespace iss diff --git a/src/vm/llvm/fp_impl.cpp b/src/vm/llvm/fp_impl.cpp new file mode 100644 index 0000000..c181904 --- /dev/null +++ b/src/vm/llvm/fp_impl.cpp @@ -0,0 +1,109 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017, 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. +// +// Contributors: +// eyck@minres.com - initial API and implementation +//////////////////////////////////////////////////////////////////////////////// + +#include +#include + +extern "C" { +#include +#include "internals.h" +#include "specialize.h" +} + +#include + +namespace iss { +namespace llvm { +namespace fp_impl { + +using namespace std; +using namespace ::llvm; + +#define INT_TYPE(L) Type::getIntNTy(mod->getContext(), L) +#define FLOAT_TYPE Type::getFloatTy(mod->getContext()) +#define DOUBLE_TYPE Type::getDoubleTy(mod->getContext()) +#define VOID_TYPE Type::getVoidTy(mod->getContext()) +#define THIS_PTR_TYPE Type::getIntNPtrTy(mod->getContext(), 8) +#define FDECLL(NAME, RET, ...) \ + Function *NAME##_func = CurrentModule->getFunction(#NAME); \ + if (!NAME##_func) { \ + std::vector NAME##_args{__VA_ARGS__}; \ + FunctionType *NAME##_type = FunctionType::get(RET, NAME##_args, false); \ + NAME##_func = Function::Create(NAME##_type, GlobalValue::ExternalLinkage, #NAME, CurrentModule); \ + NAME##_func->setCallingConv(CallingConv::C); \ + } + +#define FDECL(NAME, RET, ...) \ + std::vector NAME##_args{__VA_ARGS__}; \ + FunctionType *NAME##_type = FunctionType::get(RET, NAME##_args, false); \ + mod->getOrInsertFunction(#NAME, NAME##_type); + + +void add_fp_functions_2_module(Module *mod, uint32_t flen, uint32_t xlen) { + if(flen){ + FDECL(fget_flags, INT_TYPE(32)); + FDECL(fadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fsub_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fmul_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fdiv_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fsqrt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fcmp_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); + FDECL(fcvt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fsel_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); + FDECL(fclass_s, INT_TYPE(32), INT_TYPE(32)); + FDECL(fcvt_32_64, INT_TYPE(64), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fcvt_64_32, INT_TYPE(32), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); + if(flen>32){ + FDECL(fconv_d2f, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8)); + FDECL(fconv_f2d, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); + FDECL(fadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); + FDECL(fsub_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); + FDECL(fmul_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); + FDECL(fdiv_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); + FDECL(fsqrt_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(8)); + FDECL(fcmp_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); + FDECL(fcvt_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); + FDECL(fmadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8)); + FDECL(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32)); + FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64)); + FDECL(unbox_s, INT_TYPE(32), INT_TYPE(64)); + + } + } +} + +} +} +} diff --git a/src/vm/llvm/vm_mnrv32.cpp b/src/vm/llvm/vm_mnrv32.cpp index 428b618..3d23272 100644 --- a/src/vm/llvm/vm_mnrv32.cpp +++ b/src/vm/llvm/vm_mnrv32.cpp @@ -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}, @@ -293,6 +293,62 @@ private: {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, /* instruction CSRRCI */ {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, + /* instruction C.ADDI4SPN */ + {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, + /* instruction C.LW */ + {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, + /* instruction C.SW */ + {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, + /* instruction C.ADDI */ + {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, + /* instruction C.NOP */ + {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, + /* instruction C.JAL */ + {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, + /* instruction C.LI */ + {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, + /* instruction C.LUI */ + {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, + /* instruction C.ADDI16SP */ + {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, + /* instruction C.SRLI */ + {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, + /* instruction C.SRAI */ + {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, + /* instruction C.ANDI */ + {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, + /* instruction C.SUB */ + {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, + /* instruction C.XOR */ + {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, + /* instruction C.OR */ + {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, + /* instruction C.AND */ + {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, + /* instruction C.J */ + {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, + /* instruction C.BEQZ */ + {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, + /* instruction C.BNEZ */ + {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, + /* instruction C.SLLI */ + {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, + /* instruction C.LWSP */ + {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, + /* instruction C.MV */ + {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, + /* instruction C.JR */ + {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, + /* instruction C.ADD */ + {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, + /* instruction C.JALR */ + {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, + /* instruction C.EBREAK */ + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, + /* instruction C.SWSP */ + {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, + /* instruction DII */ + {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, }}; /* instruction definitions */ @@ -443,43 +499,17 @@ private: this->gen_reg_load(rs1 + traits::X0, 0), 32, true), this->gen_const(32U, imm)); - Value* align_val = this->builder.CreateAnd( - new_pc_val, - 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); - 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, - align_val, - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - this->gen_raise_trap(0, 0); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - 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->builder.CreateBr(bbnext); - bb=bbnext; + 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); } - this->builder.SetInsertPoint(bb); + 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); @@ -2456,6 +2486,1021 @@ private: 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 ****************************************************************************/ diff --git a/src/vm/llvm/vm_rv32gc.cpp b/src/vm/llvm/vm_rv32gc.cpp index 8d51c7d..03b1fec 100644 --- a/src/vm/llvm/vm_rv32gc.cpp +++ b/src/vm/llvm/vm_rv32gc.cpp @@ -49,19 +49,17 @@ namespace iss { namespace llvm { namespace fp_impl { -void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); -} +void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); } namespace rv32gc { +using namespace ::llvm; using namespace iss::arch; -using namespace llvm; using namespace iss::debugger; -using namespace iss::vm::llvm; -template class vm_impl : public vm_base { +template class vm_impl : public iss::llvm::vm_base { public: - using super = typename iss::vm::llvm::vm_base; + 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; @@ -191,138 +189,14 @@ private: const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* 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.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 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 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 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 */ @@ -419,6 +293,44 @@ 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 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 */ @@ -471,3146 +383,138 @@ private: {32, 0b11100000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_w}, /* instruction FMV.W.X */ {32, 0b11110000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_w_x}, - /* 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 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 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: JALR */ - std::tuple __jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JALR"); - - this->gen_sync(PRE_SYNC, 0); - - 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)); - Value* align_val = this->builder.CreateAnd( - new_pc_val, - 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); - 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, - align_val, - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - this->gen_raise_trap(0, 0); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - 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->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - this->gen_sync(POST_SYNC, 0); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 1: 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, 1); - - 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, 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: 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, 2); - - 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, 2); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 3: 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, 3); - - 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, 3); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 4: 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, 4); - - 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, 4); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 5: 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, 5); - - 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, 5); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 6: 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, 6); - - 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, 6); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 7: 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, 7); - - 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, 7); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 8: 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, 8); - - 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, 8); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 9: 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, 9); - - 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, 9); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 10: 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, 10); - - 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, 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: 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, 11); - - 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, 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: 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, 12); - - 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, 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: 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, 13); - - 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, 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: 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, 14); - - 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, 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: 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, 15); - - 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, 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: 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, 16); - - 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, 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: 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, 17); - - 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, 17); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 18: 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, 18); - - 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, 18); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 19: 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, 19); - - 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, 19); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 20: 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, 20); - - 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, 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: 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, 21); - - 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, 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: 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, 22); - - 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, 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: 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, 23); - - 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, 23); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 24: 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, 24); - - 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, 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: 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, 25); - - 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, 25); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 26: 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, 26); - - 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, 26); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 27: 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, 27); - - 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, 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: DII */ - std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DII"); - - this->gen_sync(PRE_SYNC, 28); - - 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_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: 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, 29); - - 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, 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: 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, 30); - - 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, 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: 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, 31); - - 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, 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: 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, 32); - - 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, 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: 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, 33); - - 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, 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: 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, 34); - - 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, 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: 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, 35); - - 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, 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: 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, 36); - - 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, 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: FLD */ - std::tuple __fld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLD"); - - this->gen_sync(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} 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, 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: FSD */ - std::tuple __fsd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSD"); - - this->gen_sync(PRE_SYNC, 38); - - 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, 38); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 39: 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, 39); - - 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, 39); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 40: 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, 40); - - 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, 40); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 41: 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, 41); - - 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, 41); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 42: 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, 42); - - 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, 42); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 43: 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, 43); - - 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, 43); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 44: 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, 44); - - 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, 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: 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, 45); - - 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, 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: 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, 46); - - 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, 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: 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, 47); - - 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, 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: 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, 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} 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, 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: 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, 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} 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, 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: 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, 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} 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, 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: 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, 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} 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, 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: 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, 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} 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, 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: 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, 53); - - 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, 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: 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, 54); - - 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, 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: 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, 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}, 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, 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: 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, 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}, 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, 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: 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, 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}, 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, 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: 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, 58); - - 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, 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: 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, 59); - - 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, 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: 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, 60); - - 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, 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: 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, 61); - - 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, 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: 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, 62); - - 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, 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: LUI */ + /* instruction 0: LUI */ std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LUI"); - this->gen_sync(PRE_SYNC, 63); + this->gen_sync(PRE_SYNC, 0); uint8_t rd = ((bit_sub<7,5>(instr))); int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); @@ -3635,17 +539,17 @@ private: 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); + 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 64: AUIPC */ + /* instruction 1: AUIPC */ std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("AUIPC"); - this->gen_sync(PRE_SYNC, 64); + this->gen_sync(PRE_SYNC, 1); uint8_t rd = ((bit_sub<7,5>(instr))); int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); @@ -3674,17 +578,17 @@ private: 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); + 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 65: JAL */ + /* instruction 2: JAL */ std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("JAL"); - this->gen_sync(PRE_SYNC, 65); + 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)); @@ -3718,16 +622,62 @@ 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, 65); + this->gen_sync(POST_SYNC, 2); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 66: BEQ */ + /* 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, 66); + 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))); @@ -3765,16 +715,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, 66); + this->gen_sync(POST_SYNC, 4); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 67: BNE */ + /* instruction 5: BNE */ std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("BNE"); - this->gen_sync(PRE_SYNC, 67); + 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))); @@ -3812,16 +762,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, 67); + this->gen_sync(POST_SYNC, 5); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 68: BLT */ + /* instruction 6: BLT */ std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("BLT"); - this->gen_sync(PRE_SYNC, 68); + 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))); @@ -3863,16 +813,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, 68); + this->gen_sync(POST_SYNC, 6); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 69: BGE */ + /* instruction 7: BGE */ std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("BGE"); - this->gen_sync(PRE_SYNC, 69); + 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))); @@ -3914,16 +864,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, 69); + this->gen_sync(POST_SYNC, 7); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 70: BLTU */ + /* instruction 8: BLTU */ std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("BLTU"); - this->gen_sync(PRE_SYNC, 70); + 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))); @@ -3961,16 +911,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, 70); + this->gen_sync(POST_SYNC, 8); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 71: BGEU */ + /* instruction 9: BGEU */ std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("BGEU"); - this->gen_sync(PRE_SYNC, 71); + 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))); @@ -4008,16 +958,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, 71); + this->gen_sync(POST_SYNC, 9); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 72: LB */ + /* instruction 10: LB */ std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LB"); - this->gen_sync(PRE_SYNC, 72); + this->gen_sync(PRE_SYNC, 10); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4051,17 +1001,17 @@ private: 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); + 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 73: LH */ + /* instruction 11: LH */ std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LH"); - this->gen_sync(PRE_SYNC, 73); + this->gen_sync(PRE_SYNC, 11); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4095,17 +1045,17 @@ private: 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); + 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 74: LW */ + /* instruction 12: LW */ std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LW"); - this->gen_sync(PRE_SYNC, 74); + this->gen_sync(PRE_SYNC, 12); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4139,17 +1089,17 @@ private: 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, 74); + 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 75: LBU */ + /* instruction 13: LBU */ std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LBU"); - this->gen_sync(PRE_SYNC, 75); + this->gen_sync(PRE_SYNC, 13); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4183,17 +1133,17 @@ private: 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); + 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 76: LHU */ + /* instruction 14: LHU */ std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LHU"); - this->gen_sync(PRE_SYNC, 76); + this->gen_sync(PRE_SYNC, 14); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4227,17 +1177,17 @@ private: 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, 76); + 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 77: SB */ + /* instruction 15: SB */ std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SB"); - this->gen_sync(PRE_SYNC, 77); + 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))); @@ -4269,17 +1219,17 @@ private: offs_val, this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 77); + 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 78: SH */ + /* instruction 16: SH */ std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SH"); - this->gen_sync(PRE_SYNC, 78); + 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))); @@ -4311,17 +1261,17 @@ private: offs_val, this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(16))); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 78); + 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 79: SW */ + /* instruction 17: SW */ std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SW"); - this->gen_sync(PRE_SYNC, 79); + 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))); @@ -4353,17 +1303,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, 79); + 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 80: ADDI */ + /* instruction 18: ADDI */ std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("ADDI"); - this->gen_sync(PRE_SYNC, 80); + this->gen_sync(PRE_SYNC, 18); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4393,17 +1343,17 @@ private: 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, 80); + 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 81: SLTI */ + /* instruction 19: SLTI */ std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLTI"); - this->gen_sync(PRE_SYNC, 81); + this->gen_sync(PRE_SYNC, 19); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4438,17 +1388,17 @@ private: 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, 81); + 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 82: SLTIU */ + /* instruction 20: SLTIU */ std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLTIU"); - this->gen_sync(PRE_SYNC, 82); + this->gen_sync(PRE_SYNC, 20); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4482,17 +1432,17 @@ private: 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, 82); + 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 83: XORI */ + /* instruction 21: XORI */ std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("XORI"); - this->gen_sync(PRE_SYNC, 83); + this->gen_sync(PRE_SYNC, 21); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4522,17 +1472,17 @@ private: 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, 83); + 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 84: ORI */ + /* instruction 22: ORI */ std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("ORI"); - this->gen_sync(PRE_SYNC, 84); + this->gen_sync(PRE_SYNC, 22); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4562,17 +1512,17 @@ private: 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, 84); + 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 85: ANDI */ + /* instruction 23: ANDI */ std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("ANDI"); - this->gen_sync(PRE_SYNC, 85); + this->gen_sync(PRE_SYNC, 23); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4602,17 +1552,17 @@ private: 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, 85); + 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 86: SLLI */ + /* instruction 24: SLLI */ std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLLI"); - this->gen_sync(PRE_SYNC, 86); + this->gen_sync(PRE_SYNC, 24); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4644,17 +1594,17 @@ private: } } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 86); + 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 87: SRLI */ + /* instruction 25: SRLI */ std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SRLI"); - this->gen_sync(PRE_SYNC, 87); + this->gen_sync(PRE_SYNC, 25); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4686,17 +1636,17 @@ private: } } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 87); + 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 88: SRAI */ + /* instruction 26: SRAI */ std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SRAI"); - this->gen_sync(PRE_SYNC, 88); + this->gen_sync(PRE_SYNC, 26); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4728,17 +1678,17 @@ private: } } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 88); + 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 89: ADD */ + /* instruction 27: ADD */ std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("ADD"); - this->gen_sync(PRE_SYNC, 89); + this->gen_sync(PRE_SYNC, 27); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4766,17 +1716,17 @@ private: 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, 89); + 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 90: SUB */ + /* instruction 28: SUB */ std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SUB"); - this->gen_sync(PRE_SYNC, 90); + this->gen_sync(PRE_SYNC, 28); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4804,17 +1754,17 @@ private: 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, 90); + 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 91: SLL */ + /* instruction 29: SLL */ std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLL"); - this->gen_sync(PRE_SYNC, 91); + this->gen_sync(PRE_SYNC, 29); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4846,17 +1796,17 @@ private: 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, 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 92: SLT */ + /* instruction 30: SLT */ std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLT"); - this->gen_sync(PRE_SYNC, 92); + this->gen_sync(PRE_SYNC, 30); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4893,17 +1843,17 @@ private: 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, 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 93: SLTU */ + /* instruction 31: SLTU */ std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLTU"); - this->gen_sync(PRE_SYNC, 93); + this->gen_sync(PRE_SYNC, 31); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4942,17 +1892,17 @@ private: 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, 93); + 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 94: XOR */ + /* instruction 32: XOR */ std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("XOR"); - this->gen_sync(PRE_SYNC, 94); + this->gen_sync(PRE_SYNC, 32); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4980,17 +1930,17 @@ private: 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, 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 95: SRL */ + /* instruction 33: SRL */ std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SRL"); - this->gen_sync(PRE_SYNC, 95); + this->gen_sync(PRE_SYNC, 33); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5022,17 +1972,17 @@ private: 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); + 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 96: SRA */ + /* instruction 34: SRA */ std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SRA"); - this->gen_sync(PRE_SYNC, 96); + this->gen_sync(PRE_SYNC, 34); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5064,17 +2014,17 @@ private: 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, 96); + 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 97: OR */ + /* instruction 35: OR */ std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("OR"); - this->gen_sync(PRE_SYNC, 97); + this->gen_sync(PRE_SYNC, 35); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5102,17 +2052,17 @@ private: 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, 97); + 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 98: AND */ + /* instruction 36: AND */ std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("AND"); - this->gen_sync(PRE_SYNC, 98); + this->gen_sync(PRE_SYNC, 36); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5140,17 +2090,17 @@ private: 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, 98); + 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 99: FENCE */ + /* instruction 37: FENCE */ std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("FENCE"); - this->gen_sync(PRE_SYNC, 99); + this->gen_sync(PRE_SYNC, 37); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5179,17 +2129,17 @@ private: 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, 99); + 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 100: FENCE_I */ + /* 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, 100); + this->gen_sync(PRE_SYNC, 38); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5214,16 +2164,16 @@ private: 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, 100); + this->gen_sync(POST_SYNC, 38); this->gen_trap_check(this->leave_blk); return std::make_tuple(FLUSH, nullptr); } - /* instruction 101: ECALL */ + /* instruction 39: ECALL */ std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("ECALL"); - this->gen_sync(PRE_SYNC, 101); + this->gen_sync(PRE_SYNC, 39); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -5239,16 +2189,16 @@ private: pc=pc+4; this->gen_raise_trap(0, 11); - this->gen_sync(POST_SYNC, 101); + this->gen_sync(POST_SYNC, 39); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 102: EBREAK */ + /* instruction 40: EBREAK */ std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("EBREAK"); - this->gen_sync(PRE_SYNC, 102); + this->gen_sync(PRE_SYNC, 40); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -5264,16 +2214,16 @@ private: pc=pc+4; this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 102); + this->gen_sync(POST_SYNC, 40); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 103: URET */ + /* instruction 41: URET */ std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("URET"); - this->gen_sync(PRE_SYNC, 103); + this->gen_sync(PRE_SYNC, 41); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -5289,16 +2239,16 @@ private: pc=pc+4; this->gen_leave_trap(0); - this->gen_sync(POST_SYNC, 103); + this->gen_sync(POST_SYNC, 41); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 104: SRET */ + /* instruction 42: SRET */ std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SRET"); - this->gen_sync(PRE_SYNC, 104); + this->gen_sync(PRE_SYNC, 42); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -5314,16 +2264,16 @@ private: pc=pc+4; this->gen_leave_trap(1); - this->gen_sync(POST_SYNC, 104); + this->gen_sync(POST_SYNC, 42); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 105: MRET */ + /* instruction 43: MRET */ std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("MRET"); - this->gen_sync(PRE_SYNC, 105); + this->gen_sync(PRE_SYNC, 43); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -5339,16 +2289,16 @@ private: pc=pc+4; this->gen_leave_trap(3); - this->gen_sync(POST_SYNC, 105); + this->gen_sync(POST_SYNC, 43); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 106: WFI */ + /* instruction 44: WFI */ std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("WFI"); - this->gen_sync(PRE_SYNC, 106); + this->gen_sync(PRE_SYNC, 44); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -5365,17 +2315,17 @@ private: this->gen_wait(1); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 106); + 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 107: SFENCE.VMA */ + /* 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, 107); + this->gen_sync(PRE_SYNC, 45); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -5403,17 +2353,17 @@ private: 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, 107); + 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 108: CSRRW */ + /* instruction 46: CSRRW */ std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRW"); - this->gen_sync(PRE_SYNC, 108); + this->gen_sync(PRE_SYNC, 46); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5452,17 +2402,17 @@ private: this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 108); + 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 109: CSRRS */ + /* instruction 47: CSRRS */ std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRS"); - this->gen_sync(PRE_SYNC, 109); + this->gen_sync(PRE_SYNC, 47); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5499,17 +2449,17 @@ private: this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 109); + 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 110: CSRRC */ + /* instruction 48: CSRRC */ std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRC"); - this->gen_sync(PRE_SYNC, 110); + this->gen_sync(PRE_SYNC, 48); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5546,17 +2496,17 @@ private: this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 110); + 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 111: CSRRWI */ + /* instruction 49: CSRRWI */ std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRWI"); - this->gen_sync(PRE_SYNC, 111); + this->gen_sync(PRE_SYNC, 49); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); @@ -5590,17 +2540,17 @@ private: 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, 111); + 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 112: CSRRSI */ + /* instruction 50: CSRRSI */ std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRSI"); - this->gen_sync(PRE_SYNC, 112); + this->gen_sync(PRE_SYNC, 50); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); @@ -5639,17 +2589,17 @@ private: 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, 112); + 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 113: CSRRCI */ + /* instruction 51: CSRRCI */ std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRCI"); - this->gen_sync(PRE_SYNC, 113); + this->gen_sync(PRE_SYNC, 51); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); @@ -5688,17 +2638,1141 @@ private: this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 113); + 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 114: FLW */ + /* 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, 114); + this->gen_sync(PRE_SYNC, 71); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5741,17 +3815,17 @@ private: 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); + 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 115: FSW */ + /* instruction 72: FSW */ std::tuple __fsw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("FSW"); - this->gen_sync(PRE_SYNC, 115); + 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))); @@ -5786,17 +3860,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, 115); + 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 116: FMADD.S */ + /* 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, 116); + this->gen_sync(PRE_SYNC, 73); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -5891,17 +3965,17 @@ private: 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); + 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 117: FMSUB.S */ + /* 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, 117); + this->gen_sync(PRE_SYNC, 74); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -5996,17 +4070,17 @@ private: 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); + 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 118: FNMADD.S */ + /* 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, 118); + this->gen_sync(PRE_SYNC, 75); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -6101,17 +4175,17 @@ private: 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); + 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 119: FNMSUB.S */ + /* 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, 119); + this->gen_sync(PRE_SYNC, 76); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -6206,17 +4280,17 @@ private: 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); + 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 120: FADD.S */ + /* 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, 120); + this->gen_sync(PRE_SYNC, 77); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -6297,17 +4371,17 @@ private: 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); + 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 121: FSUB.S */ + /* 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, 121); + this->gen_sync(PRE_SYNC, 78); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -6388,17 +4462,17 @@ private: 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, 121); + 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 122: FMUL.S */ + /* 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, 122); + this->gen_sync(PRE_SYNC, 79); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -6479,17 +4553,17 @@ private: 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, 122); + 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 123: FDIV.S */ + /* 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, 123); + this->gen_sync(PRE_SYNC, 80); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -6570,17 +4644,17 @@ private: 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, 123); + 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 124: FSQRT.S */ + /* 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, 124); + this->gen_sync(PRE_SYNC, 81); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -6655,17 +4729,17 @@ private: 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, 124); + 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 125: FSGNJ.S */ + /* 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, 125); + this->gen_sync(PRE_SYNC, 82); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -6721,17 +4795,17 @@ private: 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, 125); + 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 126: FSGNJN.S */ + /* 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, 126); + this->gen_sync(PRE_SYNC, 83); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -6787,17 +4861,17 @@ private: 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, 126); + 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 127: FSGNJX.S */ + /* 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, 127); + this->gen_sync(PRE_SYNC, 84); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -6849,17 +4923,17 @@ private: 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); + 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 128: FMIN.S */ + /* 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, 128); + this->gen_sync(PRE_SYNC, 85); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -6925,17 +4999,17 @@ private: 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, 128); + 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 129: FMAX.S */ + /* 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, 129); + this->gen_sync(PRE_SYNC, 86); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -7001,17 +5075,17 @@ private: 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, 129); + 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 130: FCVT.W.S */ + /* 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, 130); + this->gen_sync(PRE_SYNC, 87); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -7071,17 +5145,17 @@ private: 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, 130); + 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 131: FCVT.WU.S */ + /* 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, 131); + this->gen_sync(PRE_SYNC, 88); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -7141,17 +5215,17 @@ private: 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); + 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 132: FEQ.S */ + /* 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, 132); + this->gen_sync(PRE_SYNC, 89); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -7214,17 +5288,17 @@ private: 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); + 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 133: FLT.S */ + /* 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, 133); + this->gen_sync(PRE_SYNC, 90); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -7302,17 +5376,17 @@ private: 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); + 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 134: FLE.S */ + /* 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, 134); + this->gen_sync(PRE_SYNC, 91); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -7375,17 +5449,17 @@ private: 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); + 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 135: FCLASS.S */ + /* 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, 135); + this->gen_sync(PRE_SYNC, 92); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -7412,17 +5486,17 @@ private: }); 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, 135); + 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 136: FCVT.S.W */ + /* 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, 136); + this->gen_sync(PRE_SYNC, 93); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -7480,17 +5554,17 @@ private: 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, 136); + 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 137: FCVT.S.WU */ + /* 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, 137); + this->gen_sync(PRE_SYNC, 94); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rm = ((bit_sub<12,3>(instr))); @@ -7548,17 +5622,17 @@ private: 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, 137); + 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 138: FMV.X.W */ + /* 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, 138); + this->gen_sync(PRE_SYNC, 95); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -7587,17 +5661,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, 138); + 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 139: FMV.W.X */ + /* 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, 139); + this->gen_sync(PRE_SYNC, 96); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -7639,27 +5713,26 @@ private: 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, 139); + 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 140: LR.W */ - std::tuple __lr_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LR.W"); + /* instruction 97: FLD */ + std::tuple __fld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FLD"); - this->gen_sync(PRE_SYNC, 140); + this->gen_sync(PRE_SYNC, 97); 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))); + 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}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); + "{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), @@ -7671,45 +5744,45 @@ private: 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))); + 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, 140); + 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 141: SC.W */ - std::tuple __sc_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SC.W"); + /* instruction 98: FSD */ + std::tuple __fsd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FSD"); - this->gen_sync(PRE_SYNC, 141); + this->gen_sync(PRE_SYNC, 98); - uint8_t rd = ((bit_sub<7,5>(instr))); + 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))); - 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))); + "{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), @@ -7721,91 +5794,2313 @@ private: 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, 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: 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, 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))); - 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); + 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(MEMtmp1_val,this->get_type(32))); + 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 */ @@ -7813,22 +8108,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 143: AMOADD.W */ - std::tuple __amoadd_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOADD.W"); + /* 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))); - 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)); + "{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), @@ -7838,25 +8130,16 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); - Value* res1_val = this->gen_ext( + 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); - 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->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 */ @@ -7864,22 +8147,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 144: AMOXOR.W */ - std::tuple __amoxor_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOXOR.W"); + /* 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))); - 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)); + "{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), @@ -7889,25 +8169,10 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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))); + 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 */ @@ -7915,22 +8180,18 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 145: AMOAND.W */ - std::tuple __amoand_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOAND.W"); + /* 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 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))); + 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} {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)); + "{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), @@ -7940,48 +8201,29 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); + 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); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 146: AMOOR.W */ - std::tuple __amoor_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOOR.W"); + /* 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))); - 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)); + "{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), @@ -7991,25 +8233,12 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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, + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_reg_load(rd + traits::X0, 0), 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->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 */ @@ -8017,22 +8246,18 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 147: AMOMIN.W */ - std::tuple __amomin_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMIN.W"); + /* 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 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))); + 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} {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)); + "{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), @@ -8042,117 +8267,58 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); + 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); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 148: AMOMAX.W */ - std::tuple __amomax_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAX.W"); + /* 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); - 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.CreateGlobalStringPtr("c.ebreak"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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_raise_trap(0, 3); 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); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 149: AMOMINU.W */ - std::tuple __amominu_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMINU.W"); + /* 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 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))); + 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} {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)); + "{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), @@ -8162,30 +8328,16 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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; + 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(MEMtmp1_val,this->get_type(32))); + 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 */ @@ -8193,76 +8345,45 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 150: AMOMAXU.W */ - std::tuple __amomaxu_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAXU.W"); + /* 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); - 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.CreateGlobalStringPtr("dii"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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_raise_trap(0, 2); 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); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 151: MUL */ - std::tuple __mul(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MUL"); + /* 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<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -8272,23 +8393,26 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - if(rd != 0){ - Value* res_val = this->builder.CreateMul( + 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( - this->gen_reg_load(rs1 + traits::X0, 0), - 128, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 128, + res_val, + 64, false)); - Value* Xtmp0_val = this->gen_ext( - res_val, - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), 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); @@ -8297,20 +8421,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 152: MULH */ - std::tuple __mulh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULH"); + /* 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 rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -8320,26 +8444,19 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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 */ @@ -8347,20 +8464,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 153: MULHSU */ - std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULHSU"); + /* 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))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t 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))); + "{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), @@ -8370,25 +8486,26 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - if(rd != 0){ - Value* res_val = this->builder.CreateMul( + 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( - 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); + 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); @@ -8397,20 +8514,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 154: MULHU */ - std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULHU"); + /* 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 rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -8420,26 +8536,19 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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 */ @@ -8447,20 +8556,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 155: DIV */ - std::tuple __div(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIV"); + /* 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<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -8470,74 +8579,23 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); + 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); @@ -8546,20 +8604,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 156: DIVU */ - std::tuple __divu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIVU"); + /* 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 rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -8569,38 +8627,19 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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 */ @@ -8608,20 +8647,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 157: REM */ - std::tuple __rem(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REM"); + /* 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))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t 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))); + "{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), @@ -8631,74 +8669,26 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); + 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); @@ -8707,20 +8697,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 158: REMU */ - std::tuple __remu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REMU"); + /* 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 rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -8730,38 +8719,19 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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 */ @@ -8891,5 +8861,5 @@ std::unique_ptr create(arch::rv32gc *core, unsigned short p 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_rv32imac.cpp b/src/vm/llvm/vm_rv32imac.cpp index 4a2eed7..3b17cde 100644 --- a/src/vm/llvm/vm_rv32imac.cpp +++ b/src/vm/llvm/vm_rv32imac.cpp @@ -49,19 +49,17 @@ namespace iss { namespace llvm { namespace fp_impl { -void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); -} +void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); } namespace rv32imac { +using namespace ::llvm; using namespace iss::arch; -using namespace llvm; using namespace iss::debugger; -using namespace iss::vm::llvm; -template class vm_impl : public vm_base { +template class vm_impl : public iss::llvm::vm_base { public: - using super = typename iss::vm::llvm::vm_base; + 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; @@ -191,108 +189,14 @@ private: const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* 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 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 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 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 */ @@ -389,14 +293,225 @@ 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 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: JALR */ + /* 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, 0); + this->gen_sync(PRE_SYNC, 3); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -422,179 +537,36 @@ private: this->gen_reg_load(rs1 + traits::X0, 0), 32, true), this->gen_const(32U, imm)); - Value* align_val = this->builder.CreateAnd( - new_pc_val, - 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); - 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, - align_val, - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - this->gen_raise_trap(0, 0); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - 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->builder.CreateBr(bbnext); - bb=bbnext; + 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); } - this->builder.SetInsertPoint(bb); - this->gen_sync(POST_SYNC, 0); + 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 1: 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, 1); - - 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, 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: 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, 2); - - 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, 2); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 3: 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, 3); - - 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, 3); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 4: C.ADDI */ - std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI"); + /* 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); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); + 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}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + "{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), @@ -604,60 +576,44 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, 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_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); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 5: C.NOP */ - std::tuple __c_nop(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.NOP"); + /* 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); - 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, 5); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 6: 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, 6); - - 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)); + 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} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); + "{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), @@ -667,17 +623,73 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - 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( + 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, - 32, true), - this->gen_const(32U, imm)); + 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); @@ -686,19 +698,20 @@ private: return std::make_tuple(BRANCH, nullptr); } - /* instruction 7: C.LI */ - std::tuple __c_li(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LI"); + /* 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); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); + 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} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + "{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), @@ -708,33 +721,48 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - 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); + 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); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 8: C.LUI */ - std::tuple __c_lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LUI"); + /* 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); - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); + 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} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + "{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), @@ -744,35 +772,44 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - 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); + 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); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 9: C.ADDI16SP */ - std::tuple __c_addi16sp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI16SP"); + /* 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<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)); + 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} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); + "{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), @@ -782,34 +819,44 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - 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); + 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); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 10: C.SRLI */ - std::tuple __c_srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRLI"); + /* 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 shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); + 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} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + "{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), @@ -819,13 +866,20 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - 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); + 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 */ @@ -833,19 +887,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 11: C.SRAI */ - std::tuple __c_srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRAI"); + /* 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 shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); + 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} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + "{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), @@ -855,13 +910,20 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - 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); + 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 */ @@ -869,19 +931,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 12: C.ANDI */ - std::tuple __c_andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ANDI"); + /* 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); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); + 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} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + "{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), @@ -891,15 +954,20 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateAnd( + Value* offs_val = this->builder.CreateAdd( this->gen_ext( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_reg_load(rs1 + traits::X0, 0), 32, true), this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); + 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 */ @@ -907,19 +975,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 13: C.SUB */ - std::tuple __c_sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SUB"); + /* 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 rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); + 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}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{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), @@ -929,13 +998,20 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - 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); + 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 */ @@ -943,19 +1019,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 14: C.XOR */ - std::tuple __c_xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.XOR"); + /* 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 rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); + 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}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{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), @@ -965,13 +1042,20 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - 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); + 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 */ @@ -979,19 +1063,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 15: C.OR */ - std::tuple __c_or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.OR"); + /* 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); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); + 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} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{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), @@ -1001,13 +1086,18 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - 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); + 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 */ @@ -1015,19 +1105,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 16: C.AND */ - std::tuple __c_and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.AND"); + /* 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); - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); + 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} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + "{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), @@ -1037,13 +1128,18 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - 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); + 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 */ @@ -1051,18 +1147,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 17: C.J */ - std::tuple __c_j(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.J"); + /* 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<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)); + 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} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); + "{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), @@ -1072,430 +1170,39 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; + pc=pc+4; - Value* PC_val = this->builder.CreateAdd( + Value* offs_val = this->builder.CreateAdd( this->gen_ext( - cur_pc_val, + this->gen_reg_load(rs1 + traits::X0, 0), 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, 17); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 18: 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, 18); - - 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, 18); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 19: 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, 19); - - 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, 19); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 20: 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, 20); - - 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, 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: 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, 21); - - 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, 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: 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, 22); - - 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, 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: 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, 23); - - 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, 23); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 24: 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, 24); - - 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, 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: 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, 25); - - 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, 25); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 26: 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, 26); - - 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, 26); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 27: 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, 27); - - 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, 27); + 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 28: DII */ - std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DII"); + /* instruction 18: ADDI */ + std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADDI"); - this->gen_sync(PRE_SYNC, 28); - - 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_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: 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, 29); + this->gen_sync(PRE_SYNC, 18); 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))); + 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}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); + "{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), @@ -1508,43 +1215,368 @@ private: 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); + 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); - 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, 29); + 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 30: SC.W */ - std::tuple __sc_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SC.W"); + /* instruction 19: SLTI */ + std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTI"); - this->gen_sync(PRE_SYNC, 30); + 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))); - 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"), + "{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, @@ -1557,43 +1589,138 @@ private: 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( + 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_NE, - res1_val, + ICmpInst::ICMP_SLT, this->gen_ext( - this->gen_const(32U, 0), - 32, - false)), - this->gen_const(32U, 0), + 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(Xtmp1_val, get_reg_ptr(rd + traits::X0), 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, 30); @@ -1602,22 +1729,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 31: AMOSWAP.W */ - std::tuple __amoswap_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOSWAP.W"); + /* 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))); - 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)); + "{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), @@ -1629,19 +1754,23 @@ private: 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); + 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); } - 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, 31); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -1649,22 +1778,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 32: AMOADD.W */ - std::tuple __amoadd_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOADD.W"); + /* 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))); - 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)); + "{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), @@ -1676,23 +1803,12 @@ private: 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; + 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); } - 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, 32); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -1700,22 +1816,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 33: AMOXOR.W */ - std::tuple __amoxor_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOXOR.W"); + /* 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))); - 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)); + "{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), @@ -1727,23 +1841,16 @@ private: 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; + 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); } - 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, 33); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -1751,22 +1858,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 34: AMOAND.W */ - std::tuple __amoand_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOAND.W"); + /* 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))); - 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)); + "{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), @@ -1778,23 +1883,16 @@ private: 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; + 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); } - 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, 34); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -1802,22 +1900,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 35: AMOOR.W */ - std::tuple __amoor_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOOR.W"); + /* 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))); - 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)); + "{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), @@ -1829,23 +1925,12 @@ private: 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; + 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); } - 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, 35); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -1853,22 +1938,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 36: AMOMIN.W */ - std::tuple __amomin_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMIN.W"); + /* 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))); - 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)); + "{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), @@ -1880,32 +1963,12 @@ private: 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; + 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); } - 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, 36); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -1913,26 +1976,22 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 37: AMOMAX.W */ - std::tuple __amomax_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAX.W"); + /* 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 rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {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.CreateGlobalStringPtr("fence"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -1940,32 +1999,15 @@ private: 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; + 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::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); + 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 */ @@ -1973,26 +2015,21 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 38: AMOMINU.W */ - std::tuple __amominu_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMINU.W"); + /* 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))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - uint8_t rl = ((bit_sub<25,1>(instr))); - uint8_t aq = ((bit_sub<26,1>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {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.CreateGlobalStringPtr("fence_i"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -2000,51 +2037,222 @@ private: 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; + Value* FENCEtmp0_val = this->gen_const(32U, imm); this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(32))); + 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); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(FLUSH, nullptr); } - /* instruction 39: AMOMAXU.W */ - std::tuple __amomaxu_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOMAXU.W"); + /* 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); - uint8_t rd = ((bit_sub<7,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("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))); - 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 */ + 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}, {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)); + "{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), @@ -2056,40 +2264,271 @@ private: 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); + Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); if(rd != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + 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))); } - 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, 39); + 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 40: MUL */ + /* 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, 40); + this->gen_sync(PRE_SYNC, 52); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -2127,17 +2566,17 @@ private: 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, 40); + 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 41: MULH */ + /* instruction 53: MULH */ std::tuple __mulh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("MULH"); - this->gen_sync(PRE_SYNC, 41); + this->gen_sync(PRE_SYNC, 53); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -2177,17 +2616,17 @@ private: 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, 41); + 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 42: MULHSU */ + /* instruction 54: MULHSU */ std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("MULHSU"); - this->gen_sync(PRE_SYNC, 42); + this->gen_sync(PRE_SYNC, 54); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -2227,17 +2666,17 @@ private: 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, 42); + 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 43: MULHU */ + /* instruction 55: MULHU */ std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("MULHU"); - this->gen_sync(PRE_SYNC, 43); + this->gen_sync(PRE_SYNC, 55); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -2277,17 +2716,17 @@ private: 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, 43); + 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 44: DIV */ + /* instruction 56: DIV */ std::tuple __div(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("DIV"); - this->gen_sync(PRE_SYNC, 44); + this->gen_sync(PRE_SYNC, 56); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -2376,17 +2815,17 @@ private: this->builder.SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 44); + 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 45: DIVU */ + /* instruction 57: DIVU */ std::tuple __divu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("DIVU"); - this->gen_sync(PRE_SYNC, 45); + this->gen_sync(PRE_SYNC, 57); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -2438,17 +2877,17 @@ private: this->builder.SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 45); + 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 46: REM */ + /* instruction 58: REM */ std::tuple __rem(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("REM"); - this->gen_sync(PRE_SYNC, 46); + this->gen_sync(PRE_SYNC, 58); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -2537,17 +2976,17 @@ private: this->builder.SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 46); + 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 47: REMU */ + /* instruction 59: REMU */ std::tuple __remu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("REMU"); - this->gen_sync(PRE_SYNC, 47); + this->gen_sync(PRE_SYNC, 59); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -2599,565 +3038,27 @@ private: this->builder.SetInsertPoint(bb); } 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: LUI */ - std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LUI"); - - this->gen_sync(PRE_SYNC, 48); - - 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, 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: AUIPC */ - std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AUIPC"); - - this->gen_sync(PRE_SYNC, 49); - - 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, 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: JAL */ - std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JAL"); - - this->gen_sync(PRE_SYNC, 50); - - 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, 50); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 51: BEQ */ - std::tuple __beq(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BEQ"); - - this->gen_sync(PRE_SYNC, 51); - - 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, 51); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 52: BNE */ - std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BNE"); - - this->gen_sync(PRE_SYNC, 52); - - 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, 52); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 53: BLT */ - std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLT"); - - this->gen_sync(PRE_SYNC, 53); - - 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, 53); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 54: BGE */ - std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGE"); - - this->gen_sync(PRE_SYNC, 54); - - 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, 54); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 55: BLTU */ - std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLTU"); - - this->gen_sync(PRE_SYNC, 55); - - 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, 55); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 56: BGEU */ - std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGEU"); - - this->gen_sync(PRE_SYNC, 56); - - 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, 56); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 57: LB */ - std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LB"); - - this->gen_sync(PRE_SYNC, 57); - - 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, 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: LH */ - std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LH"); - - this->gen_sync(PRE_SYNC, 58); - - 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, 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: LW */ - std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LW"); - - this->gen_sync(PRE_SYNC, 59); - - 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, 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: LBU */ - std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LBU"); + /* 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))); - int16_t imm = signextend((bit_sub<20,12>(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}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + "{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), @@ -3169,17 +3070,21 @@ private: 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* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), + this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, - false); + 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); @@ -3188,20 +3093,22 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 61: LHU */ - std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LHU"); + /* 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))); - int16_t imm = signextend((bit_sub<20,12>(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}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + "{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), @@ -3213,17 +3120,43 @@ private: 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* 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* 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); + 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); @@ -3232,20 +3165,22 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 62: SB */ - std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SB"); + /* 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); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 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))); + 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} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + "{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), @@ -3257,16 +3192,19 @@ private: 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); + 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(MEMtmp0_val,this->get_type(8))); + 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 */ @@ -3274,20 +3212,22 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 63: SH */ - std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SH"); + /* 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); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 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))); + 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} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + "{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), @@ -3299,16 +3239,23 @@ private: 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); + 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(MEMtmp0_val,this->get_type(16))); + 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 */ @@ -3316,20 +3263,22 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 64: SW */ - std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SW"); + /* 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); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 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))); + 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} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + "{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), @@ -3341,16 +3290,23 @@ private: 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); + 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(MEMtmp0_val,this->get_type(32))); + 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 */ @@ -3358,20 +3314,22 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 65: ADDI */ - std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDI"); + /* 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))); - int16_t imm = signextend((bit_sub<20,12>(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}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + "{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), @@ -3383,14 +3341,23 @@ private: 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 = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); + 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 */ @@ -3398,20 +3365,22 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 66: SLTI */ - std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTI"); + /* 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))); - int16_t imm = signextend((bit_sub<20,12>(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}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + "{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), @@ -3423,19 +3392,23 @@ private: 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 = 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); + 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 */ @@ -3443,20 +3416,22 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 67: SLTIU */ - std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTIU"); + /* 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))); - int16_t imm = signextend((bit_sub<20,12>(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}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + "{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), @@ -3468,18 +3443,32 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - int32_t full_imm_val = imm; + 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 = 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); + 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 */ @@ -3487,20 +3476,22 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 68: XORI */ - std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XORI"); + /* 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))); - int16_t imm = signextend((bit_sub<20,12>(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}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + "{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), @@ -3512,14 +3503,32 @@ private: 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 = this->builder.CreateXor( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); + 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 */ @@ -3527,20 +3536,22 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 69: ORI */ - std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ORI"); + /* 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))); - int16_t imm = signextend((bit_sub<20,12>(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}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + "{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), @@ -3552,14 +3563,28 @@ private: 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 = this->builder.CreateOr( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); + 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 */ @@ -3567,20 +3592,22 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 70: ANDI */ - std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ANDI"); + /* 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))); - int16_t imm = signextend((bit_sub<20,12>(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}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + "{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), @@ -3592,14 +3619,28 @@ private: 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 = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); + 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 */ @@ -3607,20 +3648,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 71: SLLI */ - std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLI"); + /* instruction 71: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); + 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}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + "{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), @@ -3630,18 +3670,15 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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, 71); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3649,20 +3686,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 72: SRLI */ - std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLI"); + /* instruction 72: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); + 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}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + "{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), @@ -3672,18 +3709,16 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } - } + 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, 72); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3691,20 +3726,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 73: SRAI */ - std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAI"); + /* instruction 73: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + "{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), @@ -3714,18 +3749,16 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } - } + 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, 73); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3733,20 +3766,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 74: ADD */ - std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADD"); + /* instruction 74: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -3756,14 +3788,14 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_ext( 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); - } + 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, 74); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3771,37 +3803,26 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 75: SUB */ - std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SUB"); + /* instruction 75: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t 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.CreateGlobalStringPtr("c.nop"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + /* TODO: describe operations for C.NOP ! */ 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 */ @@ -3809,20 +3830,18 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 76: SLL */ - std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLL"); + /* instruction 76: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -3832,39 +3851,38 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); + 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, 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); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 77: SLT */ - std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLT"); + /* instruction 77: 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); + int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 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", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -3874,23 +3892,13 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); + 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, 77); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3898,20 +3906,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 78: SLTU */ - std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTU"); + /* instruction 78: 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); + int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 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))); 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))); + "{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), @@ -3921,25 +3928,16 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); + 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, 78); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3947,20 +3945,18 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 79: XOR */ - std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XOR"); + /* instruction 79: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -3970,14 +3966,14 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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, 79); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3985,20 +3981,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 80: SRL */ - std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRL"); + /* instruction 80: 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); - 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 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -4008,18 +4003,13 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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, 80); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4027,20 +4017,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 81: SRA */ - std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRA"); + /* instruction 81: 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); - 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 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -4050,18 +4039,13 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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, 81); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4069,20 +4053,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 82: OR */ - std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("OR"); + /* instruction 82: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -4092,14 +4075,15 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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, 82); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4107,20 +4091,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 83: AND */ - std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AND"); + /* instruction 83: 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); - 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 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}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -4130,14 +4113,13 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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, 83); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4145,38 +4127,35 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 84: FENCE */ - std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE"); + /* instruction 84: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); + uint8_t 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("fence"), + 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; + pc=pc+2; - 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))); + 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, 84); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4184,185 +4163,276 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 85: FENCE_I */ - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE_I"); + /* instruction 85: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); + 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("fence_i"), + 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; + pc=pc+2; - 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); + 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, 85); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(FLUSH, nullptr); + bb = BasicBlock::Create(this->mod->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: ECALL */ - std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ECALL"); + /* instruction 86: 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); + 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("ecall"), + 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; + pc=pc+2; - this->gen_raise_trap(0, 11); + 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, 86); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + bb = BasicBlock::Create(this->mod->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: EBREAK */ - std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("EBREAK"); + /* instruction 87: 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); + 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("ebreak"), + 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; + pc=pc+2; - this->gen_raise_trap(0, 3); + 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, 87); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 88: URET */ - std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("URET"); + /* instruction 88: 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); + 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("uret"), + 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; + pc=pc+2; - this->gen_leave_trap(0); + 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, 88); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 89: SRET */ - std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRET"); + /* instruction 89: 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); + 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("sret"), + 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; + pc=pc+2; - this->gen_leave_trap(1); + 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, 89); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 90: MRET */ - std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MRET"); + /* instruction 90: 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); + 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("mret"), + 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; + pc=pc+2; - this->gen_leave_trap(3); + 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, 90); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + bb = BasicBlock::Create(this->mod->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: WFI */ - std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("WFI"); + /* instruction 91: 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); + 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("wfi"), + 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; + pc=pc+2; - this->gen_wait(1); + 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, 91); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4370,37 +4440,32 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 92: SFENCE.VMA */ - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SFENCE.VMA"); + /* instruction 92: 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); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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("sfence.vma"), + 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; + pc=pc+2; - 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))); + 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); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4408,20 +4473,18 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 93: CSRRW */ - std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRW"); + /* instruction 93: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(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} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + "{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), @@ -4431,46 +4494,29 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); + 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); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 94: CSRRS */ - std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRS"); + /* instruction 94: 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); + uint8_t rs2 = ((bit_sub<2,5>(instr))); 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))); + "{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), @@ -4480,23 +4526,12 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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))); - } + 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, 94); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4504,20 +4539,18 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 95: CSRRC */ - std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRC"); + /* instruction 95: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(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} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + "{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), @@ -4527,88 +4560,58 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); + 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, 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); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 96: CSRRWI */ - std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRWI"); + /* instruction 96: 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); - 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.CreateGlobalStringPtr("c.ebreak"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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_raise_trap(0, 3); 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); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 97: CSRRSI */ - std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRSI"); + /* instruction 97: 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); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); + 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} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + "{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), @@ -4618,25 +4621,16 @@ private: } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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, 97); bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4644,53 +4638,29 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 98: CSRRCI */ - std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRCI"); + /* instruction 98: DII */ + std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("DII"); this->gen_sync(PRE_SYNC, 98); - 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.CreateGlobalStringPtr("dii"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; + pc=pc+2; - 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_raise_trap(0, 2); 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); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); } /**************************************************************************** @@ -4815,5 +4785,5 @@ std::unique_ptr create(arch::rv32imac *core, unsigned sho 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 index d47c791..90f5867 100644 --- a/src/vm/llvm/vm_rv64gc.cpp +++ b/src/vm/llvm/vm_rv64gc.cpp @@ -49,19 +49,17 @@ namespace iss { namespace llvm { namespace fp_impl { -void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); -} +void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); } namespace rv64gc { +using namespace ::llvm; using namespace iss::arch; -using namespace llvm; using namespace iss::debugger; -using namespace iss::vm::llvm; -template class vm_impl : public vm_base { +template class vm_impl : public iss::llvm::vm_base { public: - using super = typename iss::vm::llvm::vm_base; + 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; @@ -191,94 +189,264 @@ private: 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 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, 0b1110110000000011, &this_class::__c_srli}, - /* instruction C.SRAI */ - {16, 0b1000010000000001, 0b1110110000000011, &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, 0b1110000000000011, &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.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 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.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 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 */ @@ -343,3952 +511,100 @@ private: {32, 0b11100010000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_d}, /* instruction FMV.D.X */ {32, 0b11110010000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_d_x}, - /* 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 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, 0b11111100000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111100000000000111000001111111, &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 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 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 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 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 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: JALR */ - std::tuple __jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JALR"); - - this->gen_sync(PRE_SYNC, 0); - - 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)); - Value* align_val = this->builder.CreateAnd( - new_pc_val, - this->gen_const(64U, 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); - 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, - align_val, - this->gen_const(64U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - this->gen_raise_trap(0, 0); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - 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->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - this->gen_sync(POST_SYNC, 0); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 1: 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, 1); - - 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, 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: 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, 2); - - 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, 2); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 3: 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, 3); - - 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, 3); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 4: 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, 4); - - 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, 4); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 5: 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, 5); - - 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, 5); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 6: 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, 6); - - 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, 6); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 7: 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, 7); - - 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, 7); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 8: 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, 8); - - 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, 8); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 9: 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, 9); - - 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, 9); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 10: 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, 10); - - 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)); - std::vector args { - this->core_ptr, - this->gen_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, 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: 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, 11); - - 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)); - std::vector args { - this->core_ptr, - this->gen_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, 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: 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, 12); - - 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, 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: 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, 13); - - 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, 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: 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, 14); - - 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, 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: 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, 15); - - 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, 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: 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, 16); - - 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, 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: 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, 17); - - 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, 17); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 18: 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, 18); - - 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, 18); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 19: 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, 19); - - 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, 19); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 20: 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, 20); - - 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)); - std::vector args { - this->core_ptr, - this->gen_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, 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: 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, 21); - - 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, 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: 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, 22); - - 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, 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: 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, 23); - - 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, 23); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 24: 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, 24); - - 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, 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: 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, 25); - - 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, 25); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 26: 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, 26); - - 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, 26); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 27: 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, 27); - - 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, 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: DII */ - std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DII"); - - this->gen_sync(PRE_SYNC, 28); - - 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_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: 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, 29); - - 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, 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: 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, 30); - - 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, 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: 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, 31); - - 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, 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: 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, 32); - - 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, 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: 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, 33); - - 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, 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: 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, 34); - - 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, 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: 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, 35); - - 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, 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: 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, 36); - - 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, 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: 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, 37); - - 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, 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: 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, 38); - - 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, 38); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 39: 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, 39); - - 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, 39); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 40: 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, 40); - - 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, 40); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 41: 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, 41); - - 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, 41); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 42: 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, 42); - - 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, 42); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 43: 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, 43); - - 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, 43); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 44: FLD */ - std::tuple __fld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLD"); - - this->gen_sync(PRE_SYNC, 44); - - 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, 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: FSD */ - std::tuple __fsd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSD"); - - this->gen_sync(PRE_SYNC, 45); - - 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, 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: 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, 46); - - 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, 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: 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, 47); - - 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, 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: 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, 48); - - 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, 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: 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, 49); - - 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, 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: 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, 50); - - 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, 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: 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, 51); - - 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, 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: 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, 52); - - 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, 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: 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, 53); - - 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, 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: 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, 54); - - 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, 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: 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, 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} 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, 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: 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, 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} 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, 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: 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, 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} 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, 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: 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, 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} 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, 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: 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, 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} 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, 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: 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, 60); - - 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, 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: 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, 61); - - 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, 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: 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, 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}, 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, 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: 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, 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}, 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, 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: 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, 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}, 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, 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: 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, 65); - - 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, 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: 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, 66); - - 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, 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: 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, 67); - - 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, 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: 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, 68); - - 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, 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: 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, 69); - - 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, 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: 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, 70); - - 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, 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: 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, 71); - - 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, 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: 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, 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))); - 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, 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: 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, 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))); - 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, 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: 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, 74); - - 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, 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: 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, 75); - - 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, 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: LUI */ + /* instruction 0: LUI */ std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LUI"); - this->gen_sync(PRE_SYNC, 76); + this->gen_sync(PRE_SYNC, 0); uint8_t rd = ((bit_sub<7,5>(instr))); int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); @@ -4313,17 +629,17 @@ private: 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, 76); + 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 77: AUIPC */ + /* instruction 1: AUIPC */ std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("AUIPC"); - this->gen_sync(PRE_SYNC, 77); + this->gen_sync(PRE_SYNC, 1); uint8_t rd = ((bit_sub<7,5>(instr))); int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); @@ -4352,17 +668,17 @@ private: 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, 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 78: JAL */ + /* instruction 2: JAL */ std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("JAL"); - this->gen_sync(PRE_SYNC, 78); + 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)); @@ -4396,16 +712,62 @@ 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(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, 78); + this->gen_sync(POST_SYNC, 2); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 79: BEQ */ + /* 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, 79); + 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))); @@ -4443,16 +805,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(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, 79); + this->gen_sync(POST_SYNC, 4); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 80: BNE */ + /* instruction 5: BNE */ std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("BNE"); - this->gen_sync(PRE_SYNC, 80); + 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))); @@ -4490,16 +852,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(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, 80); + this->gen_sync(POST_SYNC, 5); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 81: BLT */ + /* instruction 6: BLT */ std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("BLT"); - this->gen_sync(PRE_SYNC, 81); + 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))); @@ -4541,16 +903,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(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, 81); + this->gen_sync(POST_SYNC, 6); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 82: BGE */ + /* instruction 7: BGE */ std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("BGE"); - this->gen_sync(PRE_SYNC, 82); + 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))); @@ -4592,16 +954,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(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, 82); + this->gen_sync(POST_SYNC, 7); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 83: BLTU */ + /* instruction 8: BLTU */ std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("BLTU"); - this->gen_sync(PRE_SYNC, 83); + 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))); @@ -4639,16 +1001,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(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, 83); + this->gen_sync(POST_SYNC, 8); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 84: BGEU */ + /* instruction 9: BGEU */ std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("BGEU"); - this->gen_sync(PRE_SYNC, 84); + 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))); @@ -4686,16 +1048,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(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, 84); + this->gen_sync(POST_SYNC, 9); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 85: LB */ + /* instruction 10: LB */ std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LB"); - this->gen_sync(PRE_SYNC, 85); + this->gen_sync(PRE_SYNC, 10); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4729,17 +1091,17 @@ private: 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, 85); + 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 86: LH */ + /* instruction 11: LH */ std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LH"); - this->gen_sync(PRE_SYNC, 86); + this->gen_sync(PRE_SYNC, 11); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4773,17 +1135,17 @@ private: 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, 86); + 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 87: LW */ + /* instruction 12: LW */ std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LW"); - this->gen_sync(PRE_SYNC, 87); + this->gen_sync(PRE_SYNC, 12); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4817,17 +1179,17 @@ private: 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, 87); + 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 88: LBU */ + /* instruction 13: LBU */ std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LBU"); - this->gen_sync(PRE_SYNC, 88); + this->gen_sync(PRE_SYNC, 13); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4861,17 +1223,17 @@ private: 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, 88); + 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 89: LHU */ + /* instruction 14: LHU */ std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("LHU"); - this->gen_sync(PRE_SYNC, 89); + this->gen_sync(PRE_SYNC, 14); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -4905,17 +1267,17 @@ private: 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, 89); + 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 90: SB */ + /* instruction 15: SB */ std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SB"); - this->gen_sync(PRE_SYNC, 90); + 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))); @@ -4947,17 +1309,17 @@ private: offs_val, this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 90); + 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 91: SH */ + /* instruction 16: SH */ std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SH"); - this->gen_sync(PRE_SYNC, 91); + 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))); @@ -4989,17 +1351,17 @@ private: offs_val, this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(16))); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 91); + 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 92: SW */ + /* instruction 17: SW */ std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SW"); - this->gen_sync(PRE_SYNC, 92); + 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))); @@ -5031,17 +1393,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, 92); + 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 93: ADDI */ + /* instruction 18: ADDI */ std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("ADDI"); - this->gen_sync(PRE_SYNC, 93); + this->gen_sync(PRE_SYNC, 18); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5071,17 +1433,17 @@ private: 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, 93); + 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 94: SLTI */ + /* instruction 19: SLTI */ std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLTI"); - this->gen_sync(PRE_SYNC, 94); + this->gen_sync(PRE_SYNC, 19); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5116,17 +1478,17 @@ private: 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, 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 95: SLTIU */ + /* instruction 20: SLTIU */ std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLTIU"); - this->gen_sync(PRE_SYNC, 95); + this->gen_sync(PRE_SYNC, 20); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5160,17 +1522,17 @@ private: 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); + 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 96: XORI */ + /* instruction 21: XORI */ std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("XORI"); - this->gen_sync(PRE_SYNC, 96); + this->gen_sync(PRE_SYNC, 21); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5200,17 +1562,17 @@ private: 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, 96); + 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 97: ORI */ + /* instruction 22: ORI */ std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("ORI"); - this->gen_sync(PRE_SYNC, 97); + this->gen_sync(PRE_SYNC, 22); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5240,17 +1602,17 @@ private: 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, 97); + 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 98: ANDI */ + /* instruction 23: ANDI */ std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("ANDI"); - this->gen_sync(PRE_SYNC, 98); + this->gen_sync(PRE_SYNC, 23); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5280,21 +1642,21 @@ private: 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, 98); + 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 99: SLLI */ + /* instruction 24: SLLI */ std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLLI"); - this->gen_sync(PRE_SYNC, 99); + 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,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( @@ -5311,28 +1673,32 @@ private: 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->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(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, 99); + 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 100: SRLI */ + /* instruction 25: SRLI */ std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SRLI"); - this->gen_sync(PRE_SYNC, 100); + 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,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( @@ -5349,28 +1715,32 @@ private: 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->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(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, 100); + 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 101: SRAI */ + /* instruction 26: SRAI */ std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SRAI"); - this->gen_sync(PRE_SYNC, 101); + 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,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( @@ -5387,24 +1757,28 @@ private: 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->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(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, 101); + 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 102: ADD */ + /* instruction 27: ADD */ std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("ADD"); - this->gen_sync(PRE_SYNC, 102); + this->gen_sync(PRE_SYNC, 27); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5432,17 +1806,17 @@ private: 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, 102); + 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 103: SUB */ + /* instruction 28: SUB */ std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SUB"); - this->gen_sync(PRE_SYNC, 103); + this->gen_sync(PRE_SYNC, 28); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5470,17 +1844,17 @@ private: 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, 103); + 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 104: SLL */ + /* instruction 29: SLL */ std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLL"); - this->gen_sync(PRE_SYNC, 104); + this->gen_sync(PRE_SYNC, 29); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5512,17 +1886,17 @@ private: 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, 104); + 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 105: SLT */ + /* instruction 30: SLT */ std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLT"); - this->gen_sync(PRE_SYNC, 105); + this->gen_sync(PRE_SYNC, 30); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5559,17 +1933,17 @@ private: 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, 105); + 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 106: SLTU */ + /* instruction 31: SLTU */ std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SLTU"); - this->gen_sync(PRE_SYNC, 106); + this->gen_sync(PRE_SYNC, 31); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5608,17 +1982,17 @@ private: 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, 106); + 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 107: XOR */ + /* instruction 32: XOR */ std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("XOR"); - this->gen_sync(PRE_SYNC, 107); + this->gen_sync(PRE_SYNC, 32); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5646,17 +2020,17 @@ private: 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, 107); + 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 108: SRL */ + /* instruction 33: SRL */ std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SRL"); - this->gen_sync(PRE_SYNC, 108); + this->gen_sync(PRE_SYNC, 33); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5688,17 +2062,17 @@ private: 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, 108); + 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 109: SRA */ + /* instruction 34: SRA */ std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SRA"); - this->gen_sync(PRE_SYNC, 109); + this->gen_sync(PRE_SYNC, 34); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5730,17 +2104,17 @@ private: 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, 109); + 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 110: OR */ + /* instruction 35: OR */ std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("OR"); - this->gen_sync(PRE_SYNC, 110); + this->gen_sync(PRE_SYNC, 35); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5768,17 +2142,17 @@ private: 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, 110); + 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 111: AND */ + /* instruction 36: AND */ std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("AND"); - this->gen_sync(PRE_SYNC, 111); + this->gen_sync(PRE_SYNC, 36); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5806,17 +2180,17 @@ private: 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, 111); + 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 112: FENCE */ + /* instruction 37: FENCE */ std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("FENCE"); - this->gen_sync(PRE_SYNC, 112); + this->gen_sync(PRE_SYNC, 37); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5845,17 +2219,17 @@ private: 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, 112); + 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 113: FENCE_I */ + /* 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, 113); + this->gen_sync(PRE_SYNC, 38); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -5880,16 +2254,16 @@ private: 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, 113); + this->gen_sync(POST_SYNC, 38); this->gen_trap_check(this->leave_blk); return std::make_tuple(FLUSH, nullptr); } - /* instruction 114: ECALL */ + /* instruction 39: ECALL */ std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("ECALL"); - this->gen_sync(PRE_SYNC, 114); + this->gen_sync(PRE_SYNC, 39); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -5905,16 +2279,16 @@ private: pc=pc+4; this->gen_raise_trap(0, 11); - this->gen_sync(POST_SYNC, 114); + this->gen_sync(POST_SYNC, 39); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 115: EBREAK */ + /* instruction 40: EBREAK */ std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("EBREAK"); - this->gen_sync(PRE_SYNC, 115); + this->gen_sync(PRE_SYNC, 40); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -5930,16 +2304,16 @@ private: pc=pc+4; this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 115); + this->gen_sync(POST_SYNC, 40); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 116: URET */ + /* instruction 41: URET */ std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("URET"); - this->gen_sync(PRE_SYNC, 116); + this->gen_sync(PRE_SYNC, 41); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -5955,16 +2329,16 @@ private: pc=pc+4; this->gen_leave_trap(0); - this->gen_sync(POST_SYNC, 116); + this->gen_sync(POST_SYNC, 41); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 117: SRET */ + /* instruction 42: SRET */ std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("SRET"); - this->gen_sync(PRE_SYNC, 117); + this->gen_sync(PRE_SYNC, 42); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -5980,16 +2354,16 @@ private: pc=pc+4; this->gen_leave_trap(1); - this->gen_sync(POST_SYNC, 117); + this->gen_sync(POST_SYNC, 42); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 118: MRET */ + /* instruction 43: MRET */ std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("MRET"); - this->gen_sync(PRE_SYNC, 118); + this->gen_sync(PRE_SYNC, 43); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -6005,16 +2379,16 @@ private: pc=pc+4; this->gen_leave_trap(3); - this->gen_sync(POST_SYNC, 118); + this->gen_sync(POST_SYNC, 43); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); } - /* instruction 119: WFI */ + /* instruction 44: WFI */ std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("WFI"); - this->gen_sync(PRE_SYNC, 119); + this->gen_sync(PRE_SYNC, 44); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -6031,17 +2405,17 @@ private: this->gen_wait(1); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 119); + 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 120: SFENCE.VMA */ + /* 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, 120); + this->gen_sync(PRE_SYNC, 45); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -6069,17 +2443,17 @@ private: 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, 120); + 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 121: CSRRW */ + /* instruction 46: CSRRW */ std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRW"); - this->gen_sync(PRE_SYNC, 121); + this->gen_sync(PRE_SYNC, 46); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -6118,17 +2492,17 @@ private: this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(64))); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 121); + 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 122: CSRRS */ + /* instruction 47: CSRRS */ std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRS"); - this->gen_sync(PRE_SYNC, 122); + this->gen_sync(PRE_SYNC, 47); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -6165,17 +2539,17 @@ private: this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 122); + 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 123: CSRRC */ + /* instruction 48: CSRRC */ std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRC"); - this->gen_sync(PRE_SYNC, 123); + this->gen_sync(PRE_SYNC, 48); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -6212,17 +2586,17 @@ private: this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 123); + 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 124: CSRRWI */ + /* instruction 49: CSRRWI */ std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRWI"); - this->gen_sync(PRE_SYNC, 124); + this->gen_sync(PRE_SYNC, 49); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); @@ -6256,17 +2630,17 @@ private: 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, 124); + 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 125: CSRRSI */ + /* instruction 50: CSRRSI */ std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRSI"); - this->gen_sync(PRE_SYNC, 125); + this->gen_sync(PRE_SYNC, 50); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); @@ -6305,17 +2679,17 @@ private: 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, 125); + 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 126: CSRRCI */ + /* instruction 51: CSRRCI */ std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("CSRRCI"); - this->gen_sync(PRE_SYNC, 126); + this->gen_sync(PRE_SYNC, 51); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); @@ -6354,17 +2728,17 @@ private: this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 126); + 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 127: FLW */ - std::tuple __flw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FLW"); + /* instruction 52: LWU */ + std::tuple __lwu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LWU"); - this->gen_sync(PRE_SYNC, 127); + this->gen_sync(PRE_SYNC, 52); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -6372,8 +2746,8 @@ private: 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)); + "{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), @@ -6390,34 +2764,69 @@ private: 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); + 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, 127); + 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 128: FSW */ - std::tuple __fsw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FSW"); + /* instruction 53: LD */ + std::tuple __ld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LD"); - this->gen_sync(PRE_SYNC, 128); + 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))); @@ -6425,8 +2834,8 @@ private: 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)); + "{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), @@ -6443,37 +2852,32 @@ private: 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) - ); + 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->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 128); + 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 129: FMADD.S */ - std::tuple __fmadd_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FMADD.S"); + /* instruction 55: ADDIW */ + std::tuple __addiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADDIW"); - this->gen_sync(PRE_SYNC, 129); + this->gen_sync(PRE_SYNC, 55); 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))); + 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} 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)); + "{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), @@ -6485,2065 +2889,42 @@ private: 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, 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: 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, 130); - - 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, 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: 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, 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} 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, 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: 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, 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} 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, 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: 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, 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))); - 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, 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: 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, 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))); - 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, 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: 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, 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} 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, 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: 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, 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} 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, 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: 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, 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))); - 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, 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: 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, 138); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_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, 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: 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, 139); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_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, 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: 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, 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", "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, 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: 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, 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", "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, 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: 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, 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", "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, 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: 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, 143); - - 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, 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: 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, 144); - - 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, 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: 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, 145); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t 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, 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: 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, 146); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t 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, 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: 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, 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", "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, 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: 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, 148); - - 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, 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: 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, 149); - - 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, 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: 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, 150); - - 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, 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: 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, 151); - - 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, 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: 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, 152); - - 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)), + 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) ), - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + 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, 152); + 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 153: FCVT.L.S */ - std::tuple __fcvt_l_s(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FCVT.L.S"); + /* instruction 56: SLLIW */ + std::tuple __slliw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLLIW"); - 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} 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, 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.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, 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} 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, 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.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, 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} 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) - }); - 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, 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.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, 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} 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) - }); - 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, 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: 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, 157); + this->gen_sync(PRE_SYNC, 56); 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))); + 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}", fmt::arg("mnemonic", "lr.w"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); + "{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), @@ -8556,43 +2937,218 @@ private: pc=pc+4; if(rd != 0){ - Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 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( - this->gen_read_mem(traits::MEM, offs_val, 32/8), + sh_val_val, 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, 157); + 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 158: SC.W */ - std::tuple __sc_w(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SC.W"); + /* instruction 57: SRLIW */ + std::tuple __srliw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRLIW"); - this->gen_sync(PRE_SYNC, 158); + 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))); - 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"), + "{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, @@ -8605,598 +3161,46 @@ private: 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, 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: 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, 159); - - 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, 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: 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, 160); - - 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, 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: 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, 161); - - 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, 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: 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, 162); - - 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, 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: 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, 163); - - 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, 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: 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, 164); - - 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( + uint32_t mask_val = 0x1f; + Value* count_val = this->builder.CreateAnd( + this->builder.CreateTrunc( 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, 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: 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, 165); - - 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, 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: 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, 166); - - 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, 166); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 167: 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, 167); - - 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, 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: 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, 168); - - 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); + 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( - this->gen_read_mem(traits::MEM, offs_val, 64/8), + sh_val_val, 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, 168); + 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 169: SC.D */ - std::tuple __sc_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SC.D"); + /* instruction 62: SRLW */ + std::tuple __srlw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRLW"); - this->gen_sync(PRE_SYNC, 169); + 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}", fmt::arg("mnemonic", "sc.d"), + "{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, @@ -9209,112 +3213,47 @@ private: 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, 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: 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, 170); - - 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){ + 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( - this->gen_read_mem(traits::MEM, offs_val, 64/8), + sh_val_val, 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, 170); + 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 171: AMOADD.D */ - std::tuple __amoadd_d(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AMOADD.D"); + /* instruction 63: SRAW */ + std::tuple __sraw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRAW"); - this->gen_sync(PRE_SYNC, 171); + 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.d"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + "{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), @@ -9326,420 +3265,38 @@ private: 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, 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: 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, 172); - - 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, 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: 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, 173); - - 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, 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: 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, 174); - - 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, 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: 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, 175); - - 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( + uint32_t mask_val = 0x1f; + Value* count_val = this->builder.CreateAnd( + this->builder.CreateTrunc( 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, 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: 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, 176); - - 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-> 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); } - 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, 176); + 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 177: 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, 177); - - 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, 177); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 178: 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, 178); - - 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, 178); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 179: MUL */ + /* instruction 64: MUL */ std::tuple __mul(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("MUL"); - this->gen_sync(PRE_SYNC, 179); + this->gen_sync(PRE_SYNC, 64); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -9777,17 +3334,17 @@ private: 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, 179); + 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 180: MULH */ + /* instruction 65: MULH */ std::tuple __mulh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("MULH"); - this->gen_sync(PRE_SYNC, 180); + this->gen_sync(PRE_SYNC, 65); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -9827,17 +3384,17 @@ private: 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, 180); + 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 181: MULHSU */ + /* instruction 66: MULHSU */ std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("MULHSU"); - this->gen_sync(PRE_SYNC, 181); + this->gen_sync(PRE_SYNC, 66); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -9877,17 +3434,17 @@ private: 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); + 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 182: MULHU */ + /* instruction 67: MULHU */ std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("MULHU"); - this->gen_sync(PRE_SYNC, 182); + this->gen_sync(PRE_SYNC, 67); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -9927,17 +3484,17 @@ private: 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); + 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 183: DIV */ + /* instruction 68: DIV */ std::tuple __div(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("DIV"); - this->gen_sync(PRE_SYNC, 183); + this->gen_sync(PRE_SYNC, 68); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -10026,17 +3583,17 @@ private: this->builder.SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 183); + 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 184: DIVU */ + /* instruction 69: DIVU */ std::tuple __divu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("DIVU"); - this->gen_sync(PRE_SYNC, 184); + this->gen_sync(PRE_SYNC, 69); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -10088,17 +3645,17 @@ private: this->builder.SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 184); + 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 185: REM */ + /* instruction 70: REM */ std::tuple __rem(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("REM"); - this->gen_sync(PRE_SYNC, 185); + this->gen_sync(PRE_SYNC, 70); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -10187,17 +3744,17 @@ private: this->builder.SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 185); + 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 186: REMU */ + /* instruction 71: REMU */ std::tuple __remu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("REMU"); - this->gen_sync(PRE_SYNC, 186); + this->gen_sync(PRE_SYNC, 71); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -10249,17 +3806,17 @@ private: this->builder.SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 186); + 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 187: MULW */ + /* instruction 72: MULW */ std::tuple __mulw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("MULW"); - this->gen_sync(PRE_SYNC, 187); + this->gen_sync(PRE_SYNC, 72); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -10296,17 +3853,17 @@ private: 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, 187); + 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 188: DIVW */ + /* instruction 73: DIVW */ std::tuple __divw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("DIVW"); - this->gen_sync(PRE_SYNC, 188); + this->gen_sync(PRE_SYNC, 73); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -10411,17 +3968,17 @@ private: this->builder.SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 188); + 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 189: DIVUW */ + /* instruction 74: DIVUW */ std::tuple __divuw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("DIVUW"); - this->gen_sync(PRE_SYNC, 189); + this->gen_sync(PRE_SYNC, 74); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -10485,17 +4042,17 @@ private: this->builder.SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 189); + 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 190: REMW */ + /* instruction 75: REMW */ std::tuple __remw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("REMW"); - this->gen_sync(PRE_SYNC, 190); + this->gen_sync(PRE_SYNC, 75); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -10601,17 +4158,17 @@ private: this->builder.SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 190); + 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 191: REMUW */ + /* instruction 76: REMUW */ std::tuple __remuw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("REMUW"); - this->gen_sync(PRE_SYNC, 191); + this->gen_sync(PRE_SYNC, 76); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -10681,26 +4238,27 @@ private: this->builder.SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 191); + 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 192: LWU */ - std::tuple __lwu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LWU"); + /* 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, 192); + this->gen_sync(PRE_SYNC, 77); 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))); + 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}, {imm}({rs1})", fmt::arg("mnemonic", "lwu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + "{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), @@ -10712,39 +4270,164 @@ private: 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* 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, - false); + 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, 192); + 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 193: LD */ - std::tuple __ld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LD"); + /* 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, 193); + this->gen_sync(PRE_SYNC, 80); 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))); + 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}, {imm}({rs1})", fmt::arg("mnemonic", "ld"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + "{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), @@ -10756,11 +4439,562 @@ private: 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* 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), @@ -10768,27 +5002,468 @@ private: 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, 193); + 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 194: SD */ - std::tuple __sd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SD"); + /* 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, 194); + this->gen_sync(PRE_SYNC, 91); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 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))); + 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} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sd"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + "{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), @@ -10805,32 +5480,43 @@ private: 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))); + 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, 194); + 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 195: ADDIW */ - std::tuple __addiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDIW"); + /* instruction 100: FSW */ + std::tuple __fsw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FSW"); - this->gen_sync(PRE_SYNC, 195); + this->gen_sync(PRE_SYNC, 100); - uint8_t rd = ((bit_sub<7,5>(instr))); + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint8_t 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}, {imm}", fmt::arg("mnemonic", "addiw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + "{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), @@ -10842,7 +5528,5237 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - if(rd != 0){ + 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( @@ -10855,29 +10771,28 @@ private: res_val, 64, true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + 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, 195); + 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 196: SLLIW */ - std::tuple __slliw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLIW"); + /* 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, 196); + 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))); - 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)); + "{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), @@ -10887,42 +10802,129 @@ private: } Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; + 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* 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, + 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: SRLIW */ - std::tuple __srliw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLIW"); + /* 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 rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srliw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + "{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), @@ -10932,21 +10934,19 @@ private: } Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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 */ @@ -10954,20 +10954,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 198: SRAIW */ - std::tuple __sraiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAIW"); + /* 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))); - 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)); + "{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), @@ -10977,20 +10976,26 @@ private: } Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; + pc=pc+2; - 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); + 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); @@ -10999,44 +11004,41 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 199: ADDW */ - std::tuple __addw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDW"); + /* 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 rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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("addw"), + 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; + pc=pc+2; - 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); - } + 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 */ @@ -11044,43 +11046,46 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 200: SUBW */ - std::tuple __subw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SUBW"); + /* 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<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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("subw"), + 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; + pc=pc+2; - 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); + 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); @@ -11089,20 +11094,20 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 201: SLLW */ - std::tuple __sllw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLW"); + /* 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 rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sllw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -11112,28 +11117,19 @@ private: } Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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 */ @@ -11141,20 +11137,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 202: SRLW */ - std::tuple __srlw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLW"); + /* 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))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t 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))); + "{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), @@ -11164,27 +11159,26 @@ private: } Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; + pc=pc+2; - 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); + 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); @@ -11193,20 +11187,19 @@ private: return std::make_tuple(CONT, bb); } - /* instruction 203: SRAW */ - std::tuple __sraw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAW"); + /* 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 rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sraw"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + "{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), @@ -11216,28 +11209,19 @@ private: } Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; + pc=pc+2; - 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); - } + 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 */ @@ -11367,5 +11351,5 @@ std::unique_ptr create(arch::rv64gc *core, unsigned short p 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_rv64i.cpp index 961f019..fdc3227 100644 --- a/src/vm/llvm/vm_rv64i.cpp +++ b/src/vm/llvm/vm_rv64i.cpp @@ -49,17 +49,15 @@ namespace iss { namespace llvm { namespace fp_impl { -void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); -} +void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); } namespace rv64i { +using namespace ::llvm; using namespace iss::arch; -using namespace llvm; using namespace iss::debugger; -using namespace iss::llvm; -template class vm_impl : public vm_base { +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; @@ -3150,5 +3148,5 @@ std::unique_ptr create(arch::rv64i *core, unsigned short por if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } - +} // namespace llvm } // namespace iss diff --git a/src/vm/tcc/vm_rv32gc.cpp b/src/vm/tcc/vm_rv32gc.cpp index 85ec52d..7967683 100644 --- a/src/vm/tcc/vm_rv32gc.cpp +++ b/src/vm/tcc/vm_rv32gc.cpp @@ -35,8 +35,9 @@ #include #include #include -#include +#include #include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -47,25 +48,19 @@ #include namespace iss { -namespace vm { -namespace fp_impl { -void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); -} -} - namespace tcc { namespace rv32gc { using namespace iss::arch; using namespace iss::debugger; -using namespace iss::vm::llvm; -template class vm_impl : public vm_base { +template class vm_impl : public iss::tcc::vm_base { public: - using super = typename iss::vm::llvm::vm_base; + 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 addr_t = typename super::addr_t; + using tu_builder = typename super::tu_builder; vm_impl(); @@ -85,45 +80,43 @@ protected: 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, std::ostringstream&); + 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);} - template inline ConstantInt *size(T type) { - return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); - } - - void setup_module(Module* m) override { + void setup_module(std::string m) override { super::setup_module(m); - iss::vm::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)); + 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;"); } - compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, std::ostringstream&) 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); + 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 @@ -137,9 +130,9 @@ protected: std::array lut_00, lut_01, lut_10; std::array lut_11; - std::array qlut; + std::array qlut; - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; + std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], compile_func f) { @@ -191,138 +184,14 @@ private: const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* 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.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 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 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 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 */ @@ -419,6 +288,44 @@ 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 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 */ @@ -471,698 +378,6991 @@ private: {32, 0b11100000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_w}, /* instruction FMV.W.X */ {32, 0b11110000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_w_x}, - /* 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 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 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: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 1: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 2: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 3: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 4: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 5: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 6: C.JAL */ - compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 7: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 8: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 9: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 10: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 11: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 12: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 13: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 14: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 15: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 16: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 17: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 18: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 19: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 20: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 21: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 22: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 23: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 24: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 25: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 26: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 27: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 28: DII */ - compile_ret_t __dii(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 29: C.FLD */ - compile_ret_t __c_fld(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 30: C.FSD */ - compile_ret_t __c_fsd(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 31: C.FLDSP */ - compile_ret_t __c_fldsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 32: C.FSDSP */ - compile_ret_t __c_fsdsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 33: C.FLW */ - compile_ret_t __c_flw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 34: C.FSW */ - compile_ret_t __c_fsw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 35: C.FLWSP */ - compile_ret_t __c_flwsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 36: C.FSWSP */ - compile_ret_t __c_fswsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 37: FLD */ - compile_ret_t __fld(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 38: FSD */ - compile_ret_t __fsd(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 39: FMADD.D */ - compile_ret_t __fmadd_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 40: FMSUB.D */ - compile_ret_t __fmsub_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 41: FNMADD.D */ - compile_ret_t __fnmadd_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 42: FNMSUB.D */ - compile_ret_t __fnmsub_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 43: FADD.D */ - compile_ret_t __fadd_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 44: FSUB.D */ - compile_ret_t __fsub_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 45: FMUL.D */ - compile_ret_t __fmul_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 46: FDIV.D */ - compile_ret_t __fdiv_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 47: FSQRT.D */ - compile_ret_t __fsqrt_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 48: FSGNJ.D */ - compile_ret_t __fsgnj_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 49: FSGNJN.D */ - compile_ret_t __fsgnjn_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 50: FSGNJX.D */ - compile_ret_t __fsgnjx_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 51: FMIN.D */ - compile_ret_t __fmin_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 52: FMAX.D */ - compile_ret_t __fmax_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 53: FCVT.S.D */ - compile_ret_t __fcvt_s_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 54: FCVT.D.S */ - compile_ret_t __fcvt_d_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 55: FEQ.D */ - compile_ret_t __feq_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 56: FLT.D */ - compile_ret_t __flt_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 57: FLE.D */ - compile_ret_t __fle_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 58: FCLASS.D */ - compile_ret_t __fclass_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 59: FCVT.W.D */ - compile_ret_t __fcvt_w_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 60: FCVT.WU.D */ - compile_ret_t __fcvt_wu_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 61: FCVT.D.W */ - compile_ret_t __fcvt_d_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 62: FCVT.D.WU */ - compile_ret_t __fcvt_d_wu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 63: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 64: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 65: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 66: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 67: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 68: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 69: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 70: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 71: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 72: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 73: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 74: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 75: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 76: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 77: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 78: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 79: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 80: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 81: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 82: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 83: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 84: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 85: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 86: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 87: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 88: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 89: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 90: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 91: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 92: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 93: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 94: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 95: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 96: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 97: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 98: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 99: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 100: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 101: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 102: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 103: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 104: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 105: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 106: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 107: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 108: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 109: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 110: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 111: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 112: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 113: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 114: FLW */ - compile_ret_t __flw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 115: FSW */ - compile_ret_t __fsw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 116: FMADD.S */ - compile_ret_t __fmadd_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 117: FMSUB.S */ - compile_ret_t __fmsub_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 118: FNMADD.S */ - compile_ret_t __fnmadd_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 119: FNMSUB.S */ - compile_ret_t __fnmsub_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 120: FADD.S */ - compile_ret_t __fadd_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 121: FSUB.S */ - compile_ret_t __fsub_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 122: FMUL.S */ - compile_ret_t __fmul_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 123: FDIV.S */ - compile_ret_t __fdiv_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 124: FSQRT.S */ - compile_ret_t __fsqrt_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 125: FSGNJ.S */ - compile_ret_t __fsgnj_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 126: FSGNJN.S */ - compile_ret_t __fsgnjn_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 127: FSGNJX.S */ - compile_ret_t __fsgnjx_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 128: FMIN.S */ - compile_ret_t __fmin_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 129: FMAX.S */ - compile_ret_t __fmax_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 130: FCVT.W.S */ - compile_ret_t __fcvt_w_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 131: FCVT.WU.S */ - compile_ret_t __fcvt_wu_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 132: FEQ.S */ - compile_ret_t __feq_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 133: FLT.S */ - compile_ret_t __flt_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 134: FLE.S */ - compile_ret_t __fle_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 135: FCLASS.S */ - compile_ret_t __fclass_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 136: FCVT.S.W */ - compile_ret_t __fcvt_s_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 137: FCVT.S.WU */ - compile_ret_t __fcvt_s_wu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 138: FMV.X.W */ - compile_ret_t __fmv_x_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 139: FMV.W.X */ - compile_ret_t __fmv_w_x(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 140: LR.W */ - compile_ret_t __lr_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 141: SC.W */ - compile_ret_t __sc_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 142: AMOSWAP.W */ - compile_ret_t __amoswap_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 143: AMOADD.W */ - compile_ret_t __amoadd_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 144: AMOXOR.W */ - compile_ret_t __amoxor_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 145: AMOAND.W */ - compile_ret_t __amoand_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 146: AMOOR.W */ - compile_ret_t __amoor_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 147: AMOMIN.W */ - compile_ret_t __amomin_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 148: AMOMAX.W */ - compile_ret_t __amomax_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 149: AMOMINU.W */ - compile_ret_t __amominu_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 150: AMOMAXU.W */ - compile_ret_t __amomaxu_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 151: MUL */ - compile_ret_t __mul(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 152: MULH */ - compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 153: MULHSU */ - compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 154: MULHU */ - compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 155: DIV */ - compile_ret_t __div(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 156: DIVU */ - compile_ret_t __divu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 157: REM */ - compile_ret_t __rem(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 158: REMU */ - compile_ret_t __remu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ + /* 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(imm, 32U), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + cur_pc_val, + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(4, 32U)), 32); + tu.store(Xtmp0_val_v, 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: 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(4, 32U)), 32); + tu.store(Xtmp0_val_v, 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, 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, + 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: 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, + 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: 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), + 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: 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), + 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, 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, + 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: 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, + 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, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 8), + 32, + false), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 16), + 32, + false), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 8), + 32, + true), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 16), + 32, + true), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 8); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 16); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 32); + tu.store(Xtmp0_val_v, 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(); + int32_t full_imm_val = imm; + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_xor( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_or( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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,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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.shl( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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,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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.lshr( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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,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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ashr( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.sub( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_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.constant(1, 32U), + tu.constant(0, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_xor( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_or( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.l_or( + tu.shl( + tu.constant(pred, 32U), + tu.constant(4, 32U)), + tu.constant(succ, 32U)), 32); + tu.write_mem( + traits::FENCE, + tu.constant(0, 64U), + FENCEtmp0_val_v); + 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.constant(imm, 32U), 32); + tu.write_mem( + traits::FENCE, + tu.constant(1, 64U), + FENCEtmp0_val_v); + 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.constant(rs1, 32U), 32); + tu.write_mem( + traits::FENCE, + tu.constant(2, 64U), + FENCEtmp0_val_v); + auto FENCEtmp1_val_v = tu.assignment("FENCEtmp1_val", tu.constant(rs2, 32U), 32); + tu.write_mem( + traits::FENCE, + tu.constant(3, 64U), + FENCEtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto csr_val_val = tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32); + auto CSRtmp0_val_v = tu.assignment("CSRtmp0_val", rs_val_val, 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp0_val_v); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", csr_val_val, 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + } else { + auto CSRtmp2_val_v = tu.assignment("CSRtmp2_val", rs_val_val, 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp2_val_v); + } + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 32); + auto xrs1_val = tu.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", xrd_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(rs1 != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_or( + xrd_val, + xrs1_val), 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 32); + auto xrs1_val = tu.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", xrd_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(rs1 != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_and( + xrd_val, + tu.l_not(xrs1_val)), 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.ext( + tu.constant(zimm, 32U), + 32, + true), 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 32); + if(zimm != 0){ + auto CSRtmp0_val_v = tu.assignment("CSRtmp0_val", tu.l_or( + res_val, + tu.ext( + tu.constant(zimm, 32U), + 32, + true)), 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp0_val_v); + } + if(rd != 0){ + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", res_val, 32); + tu.store(Xtmp1_val_v, 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.read_mem(traits::CSR, tu.constant(csr, 16U), 32); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(zimm != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_and( + res_val, + tu.l_not(tu.ext( + tu.constant(zimm, 32U), + 32, + true))), 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + true), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + true)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 32, + true), 32); + tu.store(Xtmp0_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + false)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.lshr( + res_val, + tu.constant(32, 32U)), + 32, + true), 32); + tu.store(Xtmp0_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + true)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.lshr( + res_val, + tu.constant(32, 32U)), + 32, + true), 32); + tu.store(Xtmp0_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + true), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + true)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.lshr( + res_val, + tu.constant(32, 32U)), + 32, + true), 32); + tu.store(Xtmp0_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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)))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(MMIN_val, 32U), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.sdiv( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 32, false)), 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + tu.close_scope(); + tu(" } else {"); + auto Xtmp2_val_v = tu.assignment("Xtmp2_val", tu.neg(tu.constant(1, 32U)), 32); + tu.store(Xtmp2_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.udiv( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.neg(tu.constant(1, 32U)), 32); + tu.store(Xtmp1_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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)))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(0, 32U), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.srem( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 32, false)), 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + tu.close_scope(); + tu(" } else {"); + auto Xtmp2_val_v = tu.assignment("Xtmp2_val", tu.load(rs1 + traits::X0, 0), 32); + tu.store(Xtmp2_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.urem( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.load(rs1 + traits::X0, 0), 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + tu.close_scope(); + } + 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto REStmp1_val_v = tu.assignment("REStmp1_val", tu.ext( + tu.neg(tu.constant(1, 8U)), + 32, + false), 32); + tu.write_mem( + traits::RES, + offs_val, + REStmp1_val_v); + } + 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.read_mem(traits::RES, offs_val, 32); + tu( " if({}) {{", tu.icmp( + ICmpInst::ICMP_NE, + res1_val, + tu.constant(0, 32U))); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + tu.close_scope(); + if(rd != 0){ + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", 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)), 32); + tu.store(Xtmp1_val_v, 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.add( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_xor( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_and( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_or( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = 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); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = 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); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.choose( + tu.icmp( + ICmpInst::ICMP_UGT, + res1_val, + tu.load(rs2 + traits::X0, 0)), + tu.load(rs2 + traits::X0, 0), + res1_val); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.choose( + tu.icmp( + ICmpInst::ICMP_ULT, + res1_val, + tu.load(rs2 + traits::X0, 0)), + tu.load(rs2 + traits::X0, 0), + res1_val); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 32); + if(64 == 32){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + traits::F0, 0), + 32 + ), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto frs3_val = tu.callf("unbox_s", + tu.load(rs3 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto frs3_val = tu.callf("unbox_s", + tu.load(rs3 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto frs3_val = tu.callf("unbox_s", + tu.load(rs3 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto frs3_val = tu.callf("unbox_s", + tu.load(rs3 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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, 81); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 82: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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))), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = tu.l_or( + tu.l_and( + frs1_val, + tu.constant(0x7fffffff, 32U)), + tu.l_and( + frs2_val, + tu.constant(0x80000000, 32U))); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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))), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = tu.l_or( + tu.l_and( + frs1_val, + tu.constant(0x7fffffff, 32U)), + tu.l_and( + tu.l_not(frs2_val), + tu.constant(0x80000000, 32U))); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", tu.l_xor( + tu.load(rs1 + traits::F0, 0), + tu.l_and( + tu.load(rs2 + traits::F0, 0), + tu.constant(0x80000000, 64U))), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = tu.l_xor( + frs1_val, + tu.l_and( + frs2_val, + tu.constant(0x80000000, 32U))); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", tu.callf("fsel_s", + tu.load(rs1 + traits::F0, 0), + tu.load(rs2 + traits::F0, 0), + tu.ext( + tu.constant(0LL, 64U), + 32, + true) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = tu.callf("fsel_s", + frs1_val, + frs2_val, + tu.ext( + tu.constant(0LL, 64U), + 32, + true) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", tu.callf("fsel_s", + tu.load(rs1 + traits::F0, 0), + tu.load(rs2 + traits::F0, 0), + tu.ext( + tu.constant(1LL, 64U), + 32, + true) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = tu.callf("fsel_s", + frs1_val, + frs2_val, + tu.ext( + tu.constant(1LL, 64U), + 32, + true) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.ext( + tu.callf("fcvt_s", + frs1_val, + tu.ext( + tu.constant(0LL, 64U), + 32, + true), + tu.constant(rm, 8U) + ), + 32, + false), 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.ext( + tu.callf("fcvt_s", + frs1_val, + tu.ext( + tu.constant(1LL, 64U), + 32, + true), + tu.constant(rm, 8U) + ), + 32, + false), 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.ext( + tu.callf("fcmp_s", + frs1_val, + frs2_val, + tu.ext( + tu.constant(0LL, 64U), + 32, + true) + ), + 32, + true), 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.ext( + tu.callf("fcmp_s", + frs1_val, + frs2_val, + tu.ext( + tu.constant(2LL, 64U), + 32, + true) + ), + 32, + true), 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + } + auto Xtmp2_val_v = tu.assignment("Xtmp2_val", 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) + ), 32); + tu.store(Xtmp2_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.ext( + tu.callf("fcmp_s", + frs1_val, + frs2_val, + tu.ext( + tu.constant(1LL, 64U), + 32, + true) + ), + 32, + true), 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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, 91); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 92: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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 Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.callf("fclass_s", + tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ) + ), 32); + tu.store(Xtmp0_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto res_val = 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) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto res_val = 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) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + 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.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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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 Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.trunc( + tu.load(rs1 + traits::F0, 0), + 32 + ), + 32, + false), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", 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)), 64); + tu.store(Ftmp1_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 64); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + traits::F0, 0), + 64 + ), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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))); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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))); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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))); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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, 112); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 113: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.callf("fconv_d2f", + tu.load(rs1 + traits::F0, 0), + tu.constant(rm, 8U) + ); + uint64_t upper_val = - 1; + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp0_val_v, 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.callf("fconv_f2d", + tu.trunc( + tu.load(rs1 + traits::F0, 0), + 32 + ), + tu.constant(rm, 8U) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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 Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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 Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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 Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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 Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.callf("fclass_d", + tu.trunc( + tu.load(rs1 + traits::F0, 0), + 64 + ) + ), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + 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.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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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 Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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.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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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 Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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, 120); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 121: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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.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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.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) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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: 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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.load(2 + traits::X0, 0), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + 8 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(2, 32U)), 32); + tu.store(Xtmp0_val_v, 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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(imm, 32U), 32); + tu.store(Xtmp0_val_v, 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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(imm, 32U), 32); + tu.store(Xtmp0_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + tu.load(2 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.lshr( + tu.load(rs1_idx_val + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ashr( + tu.load(rs1_idx_val + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.ext( + tu.load(rs1_idx_val + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.sub( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_xor( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_or( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.shl( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false), 32); + tu.store(Xtmp0_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.store(Xtmp0_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.load(rd + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(2, 32U)), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 32); + if(64 == 32){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + 8 + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + 8 + traits::F0, 0), + 32 + ), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 32); + if(64 == 32){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + traits::F0, 0), + 32 + ), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 64); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + 8 + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + 8 + traits::F0, 0), + 64 + ), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 64); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + traits::F0, 0), + 64 + ), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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, std::stringstream& os) { - 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); + 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); - 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); + 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; } }; @@ -1189,7 +7389,7 @@ vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) template std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, std::ostringstrem& os) { +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; @@ -1215,53 +7415,31 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, this_block); + return (this->*f)(pc, insn, tu); } -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(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_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(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_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(tu_builder& tu, unsigned type) { } -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(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;"); } -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 +} // namespace mnrv32 template <> std::unique_ptr create(arch::rv32gc *core, unsigned short port, bool dump) { diff --git a/src/vm/tcc/vm_rv32imac.cpp b/src/vm/tcc/vm_rv32imac.cpp index 4bf1041..29dd040 100644 --- a/src/vm/tcc/vm_rv32imac.cpp +++ b/src/vm/tcc/vm_rv32imac.cpp @@ -35,8 +35,9 @@ #include #include #include -#include +#include #include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -47,25 +48,19 @@ #include namespace iss { -namespace vm { -namespace fp_impl { -void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); -} -} - namespace tcc { namespace rv32imac { using namespace iss::arch; using namespace iss::debugger; -using namespace iss::vm::llvm; -template class vm_impl : public vm_base { +template class vm_impl : public iss::tcc::vm_base { public: - using super = typename iss::vm::llvm::vm_base; + 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 addr_t = typename super::addr_t; + using tu_builder = typename super::tu_builder; vm_impl(); @@ -85,45 +80,43 @@ protected: 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, std::ostringstream&); + 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);} - template inline ConstantInt *size(T type) { - return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); - } - - void setup_module(Module* m) override { + void setup_module(std::string m) override { super::setup_module(m); - iss::vm::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)); + 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;"); } - compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, std::ostringstream&) 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); + 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 @@ -137,9 +130,9 @@ protected: std::array lut_00, lut_01, lut_10; std::array lut_11; - std::array qlut; + std::array qlut; - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; + std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], compile_func f) { @@ -191,108 +184,14 @@ private: const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* 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 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 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 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 */ @@ -389,420 +288,3512 @@ 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 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: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 1: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 2: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 3: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 4: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 5: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 6: C.JAL */ - compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 7: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 8: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 9: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 10: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 11: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 12: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 13: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 14: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 15: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 16: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 17: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 18: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 19: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 20: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 21: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 22: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 23: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 24: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 25: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 26: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 27: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 28: DII */ - compile_ret_t __dii(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 29: LR.W */ - compile_ret_t __lr_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 30: SC.W */ - compile_ret_t __sc_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 31: AMOSWAP.W */ - compile_ret_t __amoswap_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 32: AMOADD.W */ - compile_ret_t __amoadd_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 33: AMOXOR.W */ - compile_ret_t __amoxor_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 34: AMOAND.W */ - compile_ret_t __amoand_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 35: AMOOR.W */ - compile_ret_t __amoor_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 36: AMOMIN.W */ - compile_ret_t __amomin_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 37: AMOMAX.W */ - compile_ret_t __amomax_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 38: AMOMINU.W */ - compile_ret_t __amominu_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 39: AMOMAXU.W */ - compile_ret_t __amomaxu_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 40: MUL */ - compile_ret_t __mul(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 41: MULH */ - compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 42: MULHSU */ - compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 43: MULHU */ - compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 44: DIV */ - compile_ret_t __div(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 45: DIVU */ - compile_ret_t __divu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 46: REM */ - compile_ret_t __rem(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 47: REMU */ - compile_ret_t __remu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 48: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 49: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 50: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 51: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 52: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 53: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 54: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 55: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 56: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 57: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 58: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 59: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 60: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 61: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 62: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 63: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 64: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 65: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 66: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 67: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 68: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 69: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 70: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 71: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 72: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 73: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 74: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 75: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 76: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 77: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 78: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 79: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 80: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 81: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 82: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 83: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 84: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 85: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 86: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 87: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 88: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 89: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 90: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 91: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 92: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 93: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 94: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 95: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 96: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 97: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 98: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ + /* 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(imm, 32U), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + cur_pc_val, + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(4, 32U)), 32); + tu.store(Xtmp0_val_v, 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: 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(4, 32U)), 32); + tu.store(Xtmp0_val_v, 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, 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, + 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: 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, + 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: 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), + 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: 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), + 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, 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, + 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: 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, + 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, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 8), + 32, + false), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 16), + 32, + false), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 8), + 32, + true), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 16), + 32, + true), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 8); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 16); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 32); + tu.store(Xtmp0_val_v, 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(); + int32_t full_imm_val = imm; + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_xor( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_or( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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,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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.shl( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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,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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.lshr( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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,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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ashr( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.sub( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_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.constant(1, 32U), + tu.constant(0, 32U)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_xor( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_or( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.l_or( + tu.shl( + tu.constant(pred, 32U), + tu.constant(4, 32U)), + tu.constant(succ, 32U)), 32); + tu.write_mem( + traits::FENCE, + tu.constant(0, 64U), + FENCEtmp0_val_v); + 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.constant(imm, 32U), 32); + tu.write_mem( + traits::FENCE, + tu.constant(1, 64U), + FENCEtmp0_val_v); + 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.constant(rs1, 32U), 32); + tu.write_mem( + traits::FENCE, + tu.constant(2, 64U), + FENCEtmp0_val_v); + auto FENCEtmp1_val_v = tu.assignment("FENCEtmp1_val", tu.constant(rs2, 32U), 32); + tu.write_mem( + traits::FENCE, + tu.constant(3, 64U), + FENCEtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto csr_val_val = tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32); + auto CSRtmp0_val_v = tu.assignment("CSRtmp0_val", rs_val_val, 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp0_val_v); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", csr_val_val, 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + } else { + auto CSRtmp2_val_v = tu.assignment("CSRtmp2_val", rs_val_val, 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp2_val_v); + } + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 32); + auto xrs1_val = tu.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", xrd_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(rs1 != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_or( + xrd_val, + xrs1_val), 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 32); + auto xrs1_val = tu.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", xrd_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(rs1 != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_and( + xrd_val, + tu.l_not(xrs1_val)), 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.ext( + tu.constant(zimm, 32U), + 32, + true), 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 32); + if(zimm != 0){ + auto CSRtmp0_val_v = tu.assignment("CSRtmp0_val", tu.l_or( + res_val, + tu.ext( + tu.constant(zimm, 32U), + 32, + true)), 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp0_val_v); + } + if(rd != 0){ + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", res_val, 32); + tu.store(Xtmp1_val_v, 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.read_mem(traits::CSR, tu.constant(csr, 16U), 32); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(zimm != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_and( + res_val, + tu.l_not(tu.ext( + tu.constant(zimm, 32U), + 32, + true))), 32); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + true), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + true)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 32, + true), 32); + tu.store(Xtmp0_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + false)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.lshr( + res_val, + tu.constant(32, 32U)), + 32, + true), 32); + tu.store(Xtmp0_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + true)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.lshr( + res_val, + tu.constant(32, 32U)), + 32, + true), 32); + tu.store(Xtmp0_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + true), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + true)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.lshr( + res_val, + tu.constant(32, 32U)), + 32, + true), 32); + tu.store(Xtmp0_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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)))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(MMIN_val, 32U), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.sdiv( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 32, false)), 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + tu.close_scope(); + tu(" } else {"); + auto Xtmp2_val_v = tu.assignment("Xtmp2_val", tu.neg(tu.constant(1, 32U)), 32); + tu.store(Xtmp2_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.udiv( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.neg(tu.constant(1, 32U)), 32); + tu.store(Xtmp1_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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)))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(0, 32U), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.srem( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 32, false)), 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + tu.close_scope(); + tu(" } else {"); + auto Xtmp2_val_v = tu.assignment("Xtmp2_val", tu.load(rs1 + traits::X0, 0), 32); + tu.store(Xtmp2_val_v, 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.urem( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.load(rs1 + traits::X0, 0), 32); + tu.store(Xtmp1_val_v, rd + traits::X0); + tu.close_scope(); + } + 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto REStmp1_val_v = tu.assignment("REStmp1_val", tu.ext( + tu.neg(tu.constant(1, 8U)), + 32, + false), 32); + tu.write_mem( + traits::RES, + offs_val, + REStmp1_val_v); + } + 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: 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, 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))); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.read_mem(traits::RES, offs_val, 32); + tu( " if({}) {{", tu.icmp( + ICmpInst::ICMP_NE, + res1_val, + tu.constant(0, 32U))); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + tu.close_scope(); + if(rd != 0){ + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", 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)), 32); + tu.store(Xtmp1_val_v, 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false), 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.add( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_xor( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_and( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_or( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = 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); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = 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); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.choose( + tu.icmp( + ICmpInst::ICMP_UGT, + res1_val, + tu.load(rs2 + traits::X0, 0)), + tu.load(rs2 + traits::X0, 0), + res1_val); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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, 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 32); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.choose( + tu.icmp( + ICmpInst::ICMP_ULT, + res1_val, + tu.load(rs2 + traits::X0, 0)), + tu.load(rs2 + traits::X0, 0), + res1_val); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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: 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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.load(2 + traits::X0, 0), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + 8 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(2, 32U)), 32); + tu.store(Xtmp0_val_v, 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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(imm, 32U), 32); + tu.store(Xtmp0_val_v, 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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(imm, 32U), 32); + tu.store(Xtmp0_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + tu.load(2 + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.lshr( + tu.load(rs1_idx_val + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ashr( + tu.load(rs1_idx_val + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.ext( + tu.load(rs1_idx_val + traits::X0, 0), + 32, false), + tu.constant(imm, 32U)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.sub( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_xor( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_or( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.shl( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 32U)), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 32, + false), 32); + tu.store(Xtmp0_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.store(Xtmp0_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.load(rd + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 32); + tu.store(Xtmp0_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(2, 32U)), 32); + tu.store(Xtmp0_val_v, 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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 32U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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, std::stringstream& os) { - 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); + 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); - 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); + 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; } }; @@ -829,7 +3820,7 @@ vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) template std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, std::ostringstrem& os) { +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; @@ -855,53 +3846,31 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, this_block); + return (this->*f)(pc, insn, tu); } -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(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_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(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_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(tu_builder& tu, unsigned type) { } -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(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;"); } -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 rv32imac +} // namespace mnrv32 template <> std::unique_ptr create(arch::rv32imac *core, unsigned short port, bool dump) { diff --git a/src/vm/tcc/vm_rv64gc.cpp b/src/vm/tcc/vm_rv64gc.cpp index 9dde96e..89131c9 100644 --- a/src/vm/tcc/vm_rv64gc.cpp +++ b/src/vm/tcc/vm_rv64gc.cpp @@ -35,8 +35,9 @@ #include #include #include -#include +#include #include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -47,25 +48,19 @@ #include namespace iss { -namespace vm { -namespace fp_impl { -void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); -} -} - namespace tcc { namespace rv64gc { using namespace iss::arch; using namespace iss::debugger; -using namespace iss::vm::llvm; -template class vm_impl : public vm_base { +template class vm_impl : public iss::tcc::vm_base { public: - using super = typename iss::vm::llvm::vm_base; + 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 addr_t = typename super::addr_t; + using tu_builder = typename super::tu_builder; vm_impl(); @@ -85,45 +80,43 @@ protected: 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, std::ostringstream&); + 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);} - template inline ConstantInt *size(T type) { - return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); - } - - void setup_module(Module* m) override { + void setup_module(std::string m) override { super::setup_module(m); - iss::vm::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)); + 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;"); } - compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, std::ostringstream&) 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); + 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 @@ -137,9 +130,9 @@ protected: std::array lut_00, lut_01, lut_10; std::array lut_11; - std::array qlut; + std::array qlut; - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; + std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], compile_func f) { @@ -191,94 +184,264 @@ private: 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 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, 0b1110110000000011, &this_class::__c_srli}, - /* instruction C.SRAI */ - {16, 0b1000010000000001, 0b1110110000000011, &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, 0b1110000000000011, &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.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 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.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 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 */ @@ -343,1096 +506,8877 @@ private: {32, 0b11100010000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_d}, /* instruction FMV.D.X */ {32, 0b11110010000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_d_x}, - /* 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 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, 0b11111100000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111100000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111100000000000111000001111111, &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 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 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 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 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 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: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 1: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 2: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 3: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 4: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 5: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 6: C.JAL */ - compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 7: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 8: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 9: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 10: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 11: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 12: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 13: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 14: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 15: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 16: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 17: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 18: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 19: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 20: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 21: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 22: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 23: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 24: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 25: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 26: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 27: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 28: DII */ - compile_ret_t __dii(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 29: C.FLD */ - compile_ret_t __c_fld(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 30: C.FSD */ - compile_ret_t __c_fsd(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 31: C.FLDSP */ - compile_ret_t __c_fldsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 32: C.FSDSP */ - compile_ret_t __c_fsdsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 33: C.FLW */ - compile_ret_t __c_flw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 34: C.FSW */ - compile_ret_t __c_fsw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 35: C.FLWSP */ - compile_ret_t __c_flwsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 36: C.FSWSP */ - compile_ret_t __c_fswsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 37: C.LD */ - compile_ret_t __c_ld(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 38: C.SD */ - compile_ret_t __c_sd(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 39: C.SUBW */ - compile_ret_t __c_subw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 40: C.ADDW */ - compile_ret_t __c_addw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 41: C.ADDIW */ - compile_ret_t __c_addiw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 42: C.LDSP */ - compile_ret_t __c_ldsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 43: C.SDSP */ - compile_ret_t __c_sdsp(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 44: FLD */ - compile_ret_t __fld(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 45: FSD */ - compile_ret_t __fsd(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 46: FMADD.D */ - compile_ret_t __fmadd_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 47: FMSUB.D */ - compile_ret_t __fmsub_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 48: FNMADD.D */ - compile_ret_t __fnmadd_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 49: FNMSUB.D */ - compile_ret_t __fnmsub_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 50: FADD.D */ - compile_ret_t __fadd_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 51: FSUB.D */ - compile_ret_t __fsub_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 52: FMUL.D */ - compile_ret_t __fmul_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 53: FDIV.D */ - compile_ret_t __fdiv_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 54: FSQRT.D */ - compile_ret_t __fsqrt_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 55: FSGNJ.D */ - compile_ret_t __fsgnj_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 56: FSGNJN.D */ - compile_ret_t __fsgnjn_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 57: FSGNJX.D */ - compile_ret_t __fsgnjx_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 58: FMIN.D */ - compile_ret_t __fmin_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 59: FMAX.D */ - compile_ret_t __fmax_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 60: FCVT.S.D */ - compile_ret_t __fcvt_s_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 61: FCVT.D.S */ - compile_ret_t __fcvt_d_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 62: FEQ.D */ - compile_ret_t __feq_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 63: FLT.D */ - compile_ret_t __flt_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 64: FLE.D */ - compile_ret_t __fle_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 65: FCLASS.D */ - compile_ret_t __fclass_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 66: FCVT.W.D */ - compile_ret_t __fcvt_w_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 67: FCVT.WU.D */ - compile_ret_t __fcvt_wu_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 68: FCVT.D.W */ - compile_ret_t __fcvt_d_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 69: FCVT.D.WU */ - compile_ret_t __fcvt_d_wu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 70: FCVT.L.D */ - compile_ret_t __fcvt_l_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 71: FCVT.LU.D */ - compile_ret_t __fcvt_lu_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 72: FCVT.D.L */ - compile_ret_t __fcvt_d_l(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 73: FCVT.D.LU */ - compile_ret_t __fcvt_d_lu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 74: FMV.X.D */ - compile_ret_t __fmv_x_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 75: FMV.D.X */ - compile_ret_t __fmv_d_x(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 76: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 77: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 78: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 79: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 80: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 81: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 82: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 83: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 84: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 85: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 86: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 87: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 88: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 89: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 90: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 91: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 92: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 93: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 94: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 95: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 96: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 97: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 98: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 99: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 100: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 101: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 102: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 103: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 104: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 105: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 106: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 107: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 108: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 109: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 110: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 111: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 112: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 113: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 114: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 115: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 116: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 117: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 118: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 119: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 120: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 121: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 122: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 123: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 124: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 125: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 126: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 127: FLW */ - compile_ret_t __flw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 128: FSW */ - compile_ret_t __fsw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 129: FMADD.S */ - compile_ret_t __fmadd_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 130: FMSUB.S */ - compile_ret_t __fmsub_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 131: FNMADD.S */ - compile_ret_t __fnmadd_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 132: FNMSUB.S */ - compile_ret_t __fnmsub_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 133: FADD.S */ - compile_ret_t __fadd_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 134: FSUB.S */ - compile_ret_t __fsub_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 135: FMUL.S */ - compile_ret_t __fmul_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 136: FDIV.S */ - compile_ret_t __fdiv_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 137: FSQRT.S */ - compile_ret_t __fsqrt_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 138: FSGNJ.S */ - compile_ret_t __fsgnj_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 139: FSGNJN.S */ - compile_ret_t __fsgnjn_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 140: FSGNJX.S */ - compile_ret_t __fsgnjx_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 141: FMIN.S */ - compile_ret_t __fmin_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 142: FMAX.S */ - compile_ret_t __fmax_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 143: FCVT.W.S */ - compile_ret_t __fcvt_w_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 144: FCVT.WU.S */ - compile_ret_t __fcvt_wu_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 145: FEQ.S */ - compile_ret_t __feq_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 146: FLT.S */ - compile_ret_t __flt_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 147: FLE.S */ - compile_ret_t __fle_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 148: FCLASS.S */ - compile_ret_t __fclass_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 149: FCVT.S.W */ - compile_ret_t __fcvt_s_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 150: FCVT.S.WU */ - compile_ret_t __fcvt_s_wu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 151: FMV.X.W */ - compile_ret_t __fmv_x_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 152: FMV.W.X */ - compile_ret_t __fmv_w_x(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 153: FCVT.L.S */ - compile_ret_t __fcvt_l_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 154: FCVT.LU.S */ - compile_ret_t __fcvt_lu_s(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 155: FCVT.S.L */ - compile_ret_t __fcvt_s_l(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 156: FCVT.S.LU */ - compile_ret_t __fcvt_s_lu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 157: LR.W */ - compile_ret_t __lr_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 158: SC.W */ - compile_ret_t __sc_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 159: AMOSWAP.W */ - compile_ret_t __amoswap_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 160: AMOADD.W */ - compile_ret_t __amoadd_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 161: AMOXOR.W */ - compile_ret_t __amoxor_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 162: AMOAND.W */ - compile_ret_t __amoand_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 163: AMOOR.W */ - compile_ret_t __amoor_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 164: AMOMIN.W */ - compile_ret_t __amomin_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 165: AMOMAX.W */ - compile_ret_t __amomax_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 166: AMOMINU.W */ - compile_ret_t __amominu_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 167: AMOMAXU.W */ - compile_ret_t __amomaxu_w(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 168: LR.D */ - compile_ret_t __lr_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 169: SC.D */ - compile_ret_t __sc_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 170: AMOSWAP.D */ - compile_ret_t __amoswap_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 171: AMOADD.D */ - compile_ret_t __amoadd_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 172: AMOXOR.D */ - compile_ret_t __amoxor_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 173: AMOAND.D */ - compile_ret_t __amoand_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 174: AMOOR.D */ - compile_ret_t __amoor_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 175: AMOMIN.D */ - compile_ret_t __amomin_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 176: AMOMAX.D */ - compile_ret_t __amomax_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 177: AMOMINU.D */ - compile_ret_t __amominu_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 178: AMOMAXU.D */ - compile_ret_t __amomaxu_d(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 179: MUL */ - compile_ret_t __mul(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 180: MULH */ - compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 181: MULHSU */ - compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 182: MULHU */ - compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 183: DIV */ - compile_ret_t __div(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 184: DIVU */ - compile_ret_t __divu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 185: REM */ - compile_ret_t __rem(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 186: REMU */ - compile_ret_t __remu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 187: MULW */ - compile_ret_t __mulw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 188: DIVW */ - compile_ret_t __divw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 189: DIVUW */ - compile_ret_t __divuw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 190: REMW */ - compile_ret_t __remw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 191: REMUW */ - compile_ret_t __remuw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 192: LWU */ - compile_ret_t __lwu(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 193: LD */ - compile_ret_t __ld(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 194: SD */ - compile_ret_t __sd(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 195: ADDIW */ - compile_ret_t __addiw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 196: SLLIW */ - compile_ret_t __slliw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 197: SRLIW */ - compile_ret_t __srliw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 198: SRAIW */ - compile_ret_t __sraiw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 199: ADDW */ - compile_ret_t __addw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 200: SUBW */ - compile_ret_t __subw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 201: SLLW */ - compile_ret_t __sllw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 202: SRLW */ - compile_ret_t __srlw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ - } - - /* instruction 203: SRAW */ - compile_ret_t __sraw(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ + /* 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(imm, 64U), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + cur_pc_val, + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(4, 64U)), 64); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(4, 64U)), 64); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 8), + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 16), + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 8), + 64, + true), 64); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 16), + 64, + true), 64); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 8); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 16); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_xor( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_or( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, 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,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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.shl( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 64U)), 64); + tu.store(Xtmp0_val_v, 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,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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.lshr( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 64U)), 64); + tu.store(Xtmp0_val_v, 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,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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ashr( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 64U)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.sub( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_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.constant(1, 64U), + tu.constant(0, 64U)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_xor( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_or( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.l_or( + tu.shl( + tu.constant(pred, 64U), + tu.constant(4, 64U)), + tu.constant(succ, 64U)), 64); + tu.write_mem( + traits::FENCE, + tu.constant(0, 64U), + FENCEtmp0_val_v); + 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.constant(imm, 64U), 64); + tu.write_mem( + traits::FENCE, + tu.constant(1, 64U), + FENCEtmp0_val_v); + 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.constant(rs1, 64U), 64); + tu.write_mem( + traits::FENCE, + tu.constant(2, 64U), + FENCEtmp0_val_v); + auto FENCEtmp1_val_v = tu.assignment("FENCEtmp1_val", tu.constant(rs2, 64U), 64); + tu.write_mem( + traits::FENCE, + tu.constant(3, 64U), + FENCEtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto csr_val_val = tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64); + auto CSRtmp0_val_v = tu.assignment("CSRtmp0_val", rs_val_val, 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp0_val_v); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", csr_val_val, 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + } else { + auto CSRtmp2_val_v = tu.assignment("CSRtmp2_val", rs_val_val, 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp2_val_v); + } + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 64); + auto xrs1_val = tu.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", xrd_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(rs1 != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_or( + xrd_val, + xrs1_val), 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 64); + auto xrs1_val = tu.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", xrd_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(rs1 != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_and( + xrd_val, + tu.l_not(xrs1_val)), 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.ext( + tu.constant(zimm, 64U), + 64, + true), 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 64); + if(zimm != 0){ + auto CSRtmp0_val_v = tu.assignment("CSRtmp0_val", tu.l_or( + res_val, + tu.ext( + tu.constant(zimm, 64U), + 64, + true)), 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp0_val_v); + } + if(rd != 0){ + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", res_val, 64); + tu.store(Xtmp1_val_v, 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.read_mem(traits::CSR, tu.constant(csr, 16U), 64); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(zimm != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_and( + res_val, + tu.l_not(tu.ext( + tu.constant(zimm, 64U), + 64, + true))), 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + true), 64); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.add( + tu.ext( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + 32, false), + tu.constant(imm, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.shl( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.constant(shamt, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.lshr( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.constant(shamt, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.ashr( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.constant(shamt, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.add( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + )); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.sub( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + )); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.l_and( + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + ), + tu.constant(mask_val, 32U)); + auto sh_val_val = tu.shl( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + count_val); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.l_and( + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + ), + tu.constant(mask_val, 32U)); + auto sh_val_val = tu.lshr( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + count_val); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.l_and( + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + ), + tu.constant(mask_val, 32U)); + auto sh_val_val = tu.ashr( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + count_val); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + true), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + true)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + true), 64); + tu.store(Xtmp0_val_v, 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + false)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.lshr( + res_val, + tu.constant(64, 64U)), + 64, + true), 64); + tu.store(Xtmp0_val_v, 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + true)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.lshr( + res_val, + tu.constant(64, 64U)), + 64, + true), 64); + tu.store(Xtmp0_val_v, 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.mul( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 128, + true), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 128, + true)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.lshr( + res_val, + tu.constant(64, 64U)), + 64, + true), 64); + tu.store(Xtmp0_val_v, 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)))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(MMIN_val, 64U), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.sdiv( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 64, false)), 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + tu.close_scope(); + tu(" } else {"); + auto Xtmp2_val_v = tu.assignment("Xtmp2_val", tu.neg(tu.constant(1, 64U)), 64); + tu.store(Xtmp2_val_v, 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))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.udiv( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.neg(tu.constant(1, 64U)), 64); + tu.store(Xtmp1_val_v, 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)))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(0, 64U), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.srem( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.ext( + tu.load(rs2 + traits::X0, 0), + 64, false)), 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + tu.close_scope(); + tu(" } else {"); + auto Xtmp2_val_v = tu.assignment("Xtmp2_val", tu.load(rs1 + traits::X0, 0), 64); + tu.store(Xtmp2_val_v, 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))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.urem( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.load(rs1 + traits::X0, 0), 64); + tu.store(Xtmp1_val_v, 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.mul( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + )), + 64, + false), 64); + tu.store(Xtmp0_val_v, 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)))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.shl( + tu.neg(tu.constant(1, 64U)), + tu.constant(31, 64U)), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", 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), 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + tu.close_scope(); + tu(" } else {"); + auto Xtmp2_val_v = tu.assignment("Xtmp2_val", tu.neg(tu.constant(1, 64U)), 64); + tu.store(Xtmp2_val_v, 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))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.udiv( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + )), + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.neg(tu.constant(1, 64U)), 64); + tu.store(Xtmp1_val_v, 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)))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(0, 64U), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", 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), 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + tu.close_scope(); + tu(" } else {"); + auto Xtmp2_val_v = tu.assignment("Xtmp2_val", tu.ext( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + 64, + false), 64); + tu.store(Xtmp2_val_v, 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))); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.urem( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + )), + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + tu(" } else {"); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.ext( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + 64, + false), 64); + tu.store(Xtmp1_val_v, 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.load(rs1 + traits::X0, 0); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto REStmp1_val_v = tu.assignment("REStmp1_val", tu.ext( + tu.neg(tu.constant(1, 8U)), + 32, + false), 32); + tu.write_mem( + traits::RES, + offs_val, + REStmp1_val_v); + } + 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.read_mem(traits::RES, offs_val, 32); + tu( " if({}) {{", tu.icmp( + ICmpInst::ICMP_NE, + res1_val, + tu.constant(0, 32U))); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + tu.close_scope(); + if(rd != 0){ + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", 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)), 64); + tu.store(Xtmp1_val_v, 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.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.add( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_xor( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_and( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_or( + res1_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = 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); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = 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); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.choose( + tu.icmp( + ICmpInst::ICMP_UGT, + res1_val, + tu.load(rs2 + traits::X0, 0)), + tu.load(rs2 + traits::X0, 0), + res1_val); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.choose( + tu.icmp( + ICmpInst::ICMP_ULT, + res1_val, + tu.load(rs2 + traits::X0, 0)), + tu.load(rs2 + traits::X0, 0), + res1_val); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto REStmp1_val_v = tu.assignment("REStmp1_val", tu.ext( + tu.neg(tu.constant(1, 8U)), + 64, + false), 64); + tu.write_mem( + traits::RES, + offs_val, + REStmp1_val_v); + } + 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.load(rs1 + traits::X0, 0); + auto res_val = tu.read_mem(traits::RES, offs_val, 8); + tu( " if({}) {{", tu.icmp( + ICmpInst::ICMP_NE, + res_val, + tu.constant(0, 64U))); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v);if(rd != 0){ + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.constant(0, 64U), 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + } + tu(" } else {"); + if(rd != 0){ + auto Xtmp2_val_v = tu.assignment("Xtmp2_val", tu.constant(1, 64U), 64); + tu.store(Xtmp2_val_v, 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.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", tu.load(rs2 + traits::X0, 0), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.add( + res_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_xor( + res_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_and( + res_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.l_or( + res_val, + tu.load(rs2 + traits::X0, 0)); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = 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); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = 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); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.choose( + tu.icmp( + ICmpInst::ICMP_UGT, + res_val, + tu.load(rs2 + traits::X0, 0)), + tu.load(rs2 + traits::X0, 0), + res_val); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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.load(rs1 + traits::X0, 0); + auto res1_val = tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res1_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto res2_val = tu.choose( + tu.icmp( + ICmpInst::ICMP_ULT, + res1_val, + tu.load(rs2 + traits::X0, 0)), + tu.load(rs2 + traits::X0, 0), + res1_val); + auto MEMtmp1_val_v = tu.assignment("MEMtmp1_val", res2_val, 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp1_val_v); + 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}(x{rs1})", fmt::arg("mnemonic", "flw"), + fmt::arg("rd", rd), fmt::arg("imm", imm), 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 offs_val = tu.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 32); + if(64 == 32){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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}(x{rs1})", fmt::arg("mnemonic", "fsw"), + fmt::arg("rs2", rs2), fmt::arg("imm", imm), 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 offs_val = tu.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + traits::F0, 0), + 32 + ), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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} 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto frs3_val = tu.callf("unbox_s", + tu.load(rs3 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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} 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto frs3_val = tu.callf("unbox_s", + tu.load(rs3 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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} 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto frs3_val = tu.callf("unbox_s", + tu.load(rs3 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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} 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)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto frs3_val = tu.callf("unbox_s", + tu.load(rs3 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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 + )) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto res_val = 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 + )) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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))), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = tu.l_or( + tu.l_and( + frs1_val, + tu.constant(0x7fffffff, 32U)), + tu.l_and( + frs2_val, + tu.constant(0x80000000, 32U))); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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))), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = tu.l_or( + tu.l_and( + frs1_val, + tu.constant(0x7fffffff, 32U)), + tu.l_and( + tu.l_not(frs2_val), + tu.constant(0x80000000, 32U))); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", tu.l_xor( + tu.load(rs1 + traits::F0, 0), + tu.l_and( + tu.load(rs2 + traits::F0, 0), + tu.constant(0x80000000, 64U))), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = tu.l_xor( + frs1_val, + tu.l_and( + frs2_val, + tu.constant(0x80000000, 32U))); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", tu.callf("fsel_s", + tu.load(rs1 + traits::F0, 0), + tu.load(rs2 + traits::F0, 0), + tu.ext( + tu.constant(0LL, 64U), + 32, + true) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = tu.callf("fsel_s", + frs1_val, + frs2_val, + tu.ext( + tu.constant(0LL, 64U), + 32, + true) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", tu.callf("fsel_s", + tu.load(rs1 + traits::F0, 0), + tu.load(rs2 + traits::F0, 0), + tu.ext( + tu.constant(1LL, 64U), + 32, + true) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto res_val = tu.callf("fsel_s", + frs1_val, + frs2_val, + tu.ext( + tu.constant(1LL, 64U), + 32, + true) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.ext( + tu.callf("fcvt_s", + frs1_val, + tu.ext( + tu.constant(0LL, 64U), + 32, + true), + tu.constant(rm, 8U) + ), + 64, + false), 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.ext( + tu.callf("fcvt_s", + frs1_val, + tu.ext( + tu.constant(1LL, 64U), + 32, + true), + tu.constant(rm, 8U) + ), + 64, + false), 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.ext( + tu.callf("fcmp_s", + frs1_val, + frs2_val, + tu.ext( + tu.constant(0LL, 64U), + 32, + true) + ), + 64, + true), 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.ext( + tu.callf("fcmp_s", + frs1_val, + frs2_val, + tu.ext( + tu.constant(2LL, 64U), + 32, + true) + ), + 64, + true), 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + } + auto Xtmp2_val_v = tu.assignment("Xtmp2_val", 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) + ), 64); + tu.store(Xtmp2_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } else { + auto frs1_val = tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ); + auto frs2_val = tu.callf("unbox_s", + tu.load(rs2 + traits::F0, 0) + ); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", tu.ext( + tu.callf("fcmp_s", + frs1_val, + frs2_val, + tu.ext( + tu.constant(1LL, 64U), + 32, + true) + ), + 64, + true), 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.callf("fclass_s", + tu.callf("unbox_s", + tu.load(rs1 + traits::F0, 0) + ) + ), 64); + tu.store(Xtmp0_val_v, 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto res_val = 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) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", 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) + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + auto res_val = 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) + ); + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.trunc( + tu.load(rs1 + traits::F0, 0), + 32 + ), + 64, + false), 64); + tu.store(Xtmp0_val_v, 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){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", 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)), 64); + tu.store(Ftmp1_val_v, 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} x{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.l.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.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) + ); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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} x{rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.lu.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.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) + ); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + true), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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}, x{rs1}", fmt::arg("mnemonic", "fcvt.s.l"), + 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.callf("fcvt_64_32", + tu.load(rs1 + traits::X0, 0), + tu.ext( + tu.constant(2LL, 64U), + 32, + true), + tu.constant(rm, 8U) + ); + if(64 == 32){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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}, x{rs1}", fmt::arg("mnemonic", "fcvt.s.lu"), + 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.callf("fcvt_64_32", + tu.load(rs1 + traits::X0, 0), + tu.ext( + tu.constant(3LL, 64U), + 32, + true), + tu.constant(rm, 8U) + ); + if(64 == 32){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 64); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + traits::F0, 0), + 64 + ), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.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 + )) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.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))); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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.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))); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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.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))); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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.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) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.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) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + auto flags_val = tu.callf("fget_flags" + ); + 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.callf("fconv_d2f", + tu.load(rs1 + traits::F0, 0), + tu.constant(rm, 8U) + ); + uint64_t upper_val = - 1; + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp0_val_v, 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.callf("fconv_f2d", + tu.trunc( + tu.load(rs1 + traits::F0, 0), + 32 + ), + tu.constant(rm, 8U) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.callf("fclass_d", + tu.trunc( + tu.load(rs1 + traits::F0, 0), + 64 + ) + ), 64); + tu.store(Xtmp0_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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.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) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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.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) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + auto flags_val = tu.callf("fget_flags" + ); + 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.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) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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.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) + ); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, 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(); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.load(rs1 + traits::F0, 0), + 64, + false), 64); + tu.store(Xtmp0_val_v, 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(); + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, + true), 64); + tu.store(Ftmp0_val_v, 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.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, 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)); + tu("print_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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.load(2 + traits::X0, 0), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, 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.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, 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))); + tu("print_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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + 8 + traits::X0); + 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.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, 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))); + tu("print_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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + 8 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.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, 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)); + tu("print_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 Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, rs1 + traits::X0); + 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.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, 165); + 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, 165); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 166: 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, 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)); + tu("print_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 Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(2, 64U)), 64); + tu.store(Xtmp0_val_v, 1 + 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, 166); + gen_trap_check(tu); + return std::make_tuple(BRANCH); + } + + /* instruction 167: 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, 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)); + tu("print_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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(imm, 64U), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + 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.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, 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)); + tu("print_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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(imm, 64U), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + 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.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, 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)); + tu("print_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 Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + tu.load(2 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, 2 + 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.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, 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)); + tu("print_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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.lshr( + tu.load(rs1_idx_val + traits::X0, 0), + tu.constant(shamt, 64U)), 64); + tu.store(Xtmp0_val_v, rs1_idx_val + 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.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, 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)); + tu("print_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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ashr( + tu.load(rs1_idx_val + traits::X0, 0), + tu.constant(shamt, 64U)), 64); + tu.store(Xtmp0_val_v, rs1_idx_val + traits::X0); + 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.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, 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)); + tu("print_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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.ext( + tu.load(rs1_idx_val + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, rs1_idx_val + 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.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, 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))); + tu("print_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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.sub( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, rd_idx_val + traits::X0); + tu.close_scope(); + 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.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, 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))); + tu("print_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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_xor( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, rd_idx_val + 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.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, 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))); + tu("print_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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_or( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, rd_idx_val + 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.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, 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))); + tu("print_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; + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.load(rd_idx_val + traits::X0, 0), + tu.load(rs2 + 8 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, rd_idx_val + 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.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, 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)); + tu("print_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, 177); + gen_trap_check(tu); + return std::make_tuple(BRANCH); + } + + /* instruction 178: 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, 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)); + tu("print_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, 178); + gen_trap_check(tu); + return std::make_tuple(BRANCH); + } + + /* instruction 179: 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, 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)); + tu("print_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, 179); + gen_trap_check(tu); + return std::make_tuple(BRANCH); + } + + /* instruction 180: 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, 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)); + tu("print_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); + } + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.shl( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 64U)), 64); + tu.store(Xtmp0_val_v, rs1 + 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.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, 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)); + tu("print_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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + 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.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, 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))); + tu("print_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 Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.load(rs2 + traits::X0, 0), 64); + tu.store(Xtmp0_val_v, rd + 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.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, 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))); + tu("print_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, 183); + gen_trap_check(tu); + return std::make_tuple(BRANCH); + } + + /* instruction 184: 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, 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))); + tu("print_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 Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.load(rd + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, rd + 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.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, 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))); + tu("print_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 Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(2, 64U)), 64); + tu.store(Xtmp0_val_v, 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, 185); + gen_trap_check(tu); + return std::make_tuple(BRANCH); + } + + /* instruction 186: 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, 186); + 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, 186); + gen_trap_check(tu); + return std::make_tuple(BRANCH); + } + + /* instruction 187: 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, 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)); + tu("print_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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + vm_base::gen_sync(tu, POST_SYNC, 187); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 188: 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, 188); + 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, 188); + gen_trap_check(tu); + return std::make_tuple(BRANCH); + } + + /* instruction 189: 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, 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))); + tu("print_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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + 8 + 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.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, 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))); + tu("print_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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + 8 + traits::X0, 0), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.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, 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))); + tu("print_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.sub( + tu.trunc( + tu.load(rd + 8 + traits::X0, 0), + 32 + ), + tu.trunc( + tu.load(rs2 + 8 + traits::X0, 0), + 32 + )); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + 8 + traits::X0); + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + vm_base::gen_sync(tu, POST_SYNC, 191); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 192: 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, 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))); + tu("print_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.add( + tu.trunc( + tu.load(rd + 8 + traits::X0, 0), + 32 + ), + tu.trunc( + tu.load(rs2 + 8 + traits::X0, 0), + 32 + )); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + 8 + 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.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, 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)); + tu("print_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.add( + tu.ext( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + 32, false), + tu.constant(imm, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, rs1 + traits::X0); + } + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + vm_base::gen_sync(tu, POST_SYNC, 193); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 194: 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, 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)); + tu("print_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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + vm_base::gen_sync(tu, POST_SYNC, 194); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 195: 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, 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)); + tu("print_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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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: 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, 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))); + tu("print_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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 32); + if(64 == 32){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + 8 + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + 8 + traits::F0); + } + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + vm_base::gen_sync(tu, POST_SYNC, 196); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 197: 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, 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))); + tu("print_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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + 8 + traits::F0, 0), + 32 + ), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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.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, 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)); + tu("print_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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 32); + if(64 == 32){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(32, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + 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.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, 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)); + tu("print_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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + traits::F0, 0), + 32 + ), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + vm_base::gen_sync(tu, POST_SYNC, 199); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 200: 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, 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))); + tu("print_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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 64); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + 8 + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + res_val), 64); + tu.store(Ftmp1_val_v, rd + 8 + traits::F0); + } + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + vm_base::gen_sync(tu, POST_SYNC, 200); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 201: 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, 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))); + tu("print_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.add( + tu.load(rs1 + 8 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + 8 + traits::F0, 0), + 64 + ), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + vm_base::gen_sync(tu, POST_SYNC, 201); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 202: 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, 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)); + tu("print_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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto res_val = tu.read_mem(traits::MEM, offs_val, 64); + if(64 == 64){ + auto Ftmp0_val_v = tu.assignment("Ftmp0_val", res_val, 64); + tu.store(Ftmp0_val_v, rd + traits::F0); + } else { + uint64_t upper_val = - 1; + auto Ftmp1_val_v = tu.assignment("Ftmp1_val", tu.l_or( + tu.shl( + tu.constant(upper_val, 64U), + tu.constant(64, 64U)), + tu.ext( + res_val, + 64, + true)), 64); + tu.store(Ftmp1_val_v, rd + traits::F0); + } + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + vm_base::gen_sync(tu, POST_SYNC, 202); + gen_trap_check(tu); + return std::make_tuple(CONT); + } + + /* instruction 203: 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, 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)); + tu("print_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.add( + tu.load(2 + traits::X0, 0), + tu.constant(uimm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.trunc( + tu.load(rs2 + traits::F0, 0), + 64 + ), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + vm_base::gen_sync(tu, POST_SYNC, 203); + 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, std::stringstream& os) { - 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); + 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); - 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); + 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; } }; @@ -1459,7 +9403,7 @@ vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) template std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, std::ostringstrem& os) { +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; @@ -1485,53 +9429,31 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, this_block); + return (this->*f)(pc, insn, tu); } -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(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_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(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_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(tu_builder& tu, unsigned type) { } -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(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;"); } -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 +} // namespace mnrv32 template <> std::unique_ptr create(arch::rv64gc *core, unsigned short port, bool dump) { diff --git a/src/vm/tcc/vm_rv64i.cpp b/src/vm/tcc/vm_rv64i.cpp index 5e28a30..02966a4 100644 --- a/src/vm/tcc/vm_rv64i.cpp +++ b/src/vm/tcc/vm_rv64i.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -47,24 +48,19 @@ #include namespace iss { -namespace vm { -namespace fp_impl { -void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); -} -} - namespace tcc { namespace rv64i { using namespace iss::arch; using namespace iss::debugger; -template class vm_impl : public vm_base { +template class vm_impl : public iss::tcc::vm_base { public: - using super = typename iss::tcc::vm_base; + 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 addr_t = typename super::addr_t; + using tu_builder = typename super::tu_builder; vm_impl(); @@ -84,43 +80,43 @@ protected: 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, std::ostringstream&); + 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);} - template inline ConstantInt *size(T type) { - return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); - } - - void setup_module(Module* m) override { + void setup_module(std::string m) override { super::setup_module(m); - iss::vm::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)); + 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;"); } - compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, std::ostringstream&) 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; - - std::string 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 std::string gen_set_pc(virt_addr_t pc, unsigned reg_num) { - return fmt::format("*((uint64_t*){}) = {}\n", get_reg_ptr(reg_num), next_pc_v.val); + 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 @@ -134,9 +130,9 @@ protected: std::array lut_00, lut_01, lut_10; std::array lut_11; - std::array qlut; + std::array qlut; - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; + std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], compile_func f) { @@ -320,303 +316,2210 @@ private: /* instruction definitions */ /* instruction 0: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.constant(imm, 64U), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ - os<gen_sync(PRE_SYNC, 1); - + 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)); - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - os<core_ptr, pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } - - Value* cur_pc_val = this->gen_const(64, pc.val); + auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); pc=pc+4; - + tu.open_scope(); if(rd != 0){ - os<::X0)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + cur_pc_val, + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); } - os<gen_set_pc(pc, traits::NEXT_PC); - os<gen_sync(POST_SYNC, 1); - os<gen_trap_check(bb); + 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(4, 64U)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto align_val = tu.l_and( + new_pc_val, + tu.constant(0x2, 64U)); + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + cur_pc_val, + tu.constant(4, 64U)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 8), + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 16), + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 8), + 64, + true), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 16), + 64, + true), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 8); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 16); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 32); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_xor( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_or( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.shl( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 64U)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.lshr( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 64U)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ashr( + tu.load(rs1 + traits::X0, 0), + tu.constant(shamt, 64U)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.add( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.sub( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_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.constant(1, 64U), + tu.constant(0, 64U)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_xor( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", 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)))), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_or( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.l_and( + tu.load(rs1 + traits::X0, 0), + tu.load(rs2 + traits::X0, 0)), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.l_or( + tu.shl( + tu.constant(pred, 64U), + tu.constant(4, 64U)), + tu.constant(succ, 64U)), 64); + tu.write_mem( + traits::FENCE, + tu.constant(0, 64U), + FENCEtmp0_val_v); + 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, std::ostringstream& os){ + 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.constant(imm, 64U), 64); + tu.write_mem( + traits::FENCE, + tu.constant(1, 64U), + FENCEtmp0_val_v); + 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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, std::ostringstream& os){ + 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(); + auto FENCEtmp0_val_v = tu.assignment("FENCEtmp0_val", tu.constant(rs1, 64U), 64); + tu.write_mem( + traits::FENCE, + tu.constant(2, 64U), + FENCEtmp0_val_v); + auto FENCEtmp1_val_v = tu.assignment("FENCEtmp1_val", tu.constant(rs2, 64U), 64); + tu.write_mem( + traits::FENCE, + tu.constant(3, 64U), + FENCEtmp1_val_v); + 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, std::ostringstream& os){ + 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.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto csr_val_val = tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64); + auto CSRtmp0_val_v = tu.assignment("CSRtmp0_val", rs_val_val, 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp0_val_v); + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", csr_val_val, 64); + tu.store(Xtmp1_val_v, rd + traits::X0); + } else { + auto CSRtmp2_val_v = tu.assignment("CSRtmp2_val", rs_val_val, 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp2_val_v); + } + 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, std::ostringstream& os){ + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 64); + auto xrs1_val = tu.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", xrd_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(rs1 != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_or( + xrd_val, + xrs1_val), 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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, std::ostringstream& os){ + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 64); + auto xrs1_val = tu.load(rs1 + traits::X0, 0); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", xrd_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(rs1 != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_and( + xrd_val, + tu.l_not(xrs1_val)), 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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, std::ostringstream& os){ + 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){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.read_mem(traits::CSR, tu.constant(csr, 16U), 64), 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.ext( + tu.constant(zimm, 64U), + 64, + true), 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + 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, std::ostringstream& os){ + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 64); + if(zimm != 0){ + auto CSRtmp0_val_v = tu.assignment("CSRtmp0_val", tu.l_or( + res_val, + tu.ext( + tu.constant(zimm, 64U), + 64, + true)), 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp0_val_v); + } + if(rd != 0){ + auto Xtmp1_val_v = tu.assignment("Xtmp1_val", res_val, 64); + tu.store(Xtmp1_val_v, 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, std::ostringstream& os){ + 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.read_mem(traits::CSR, tu.constant(csr, 16U), 64); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", res_val, 64); + tu.store(Xtmp0_val_v, rd + traits::X0); + } + if(zimm != 0){ + auto CSRtmp1_val_v = tu.assignment("CSRtmp1_val", tu.l_and( + res_val, + tu.l_not(tu.ext( + tu.constant(zimm, 64U), + 64, + true))), 64); + tu.write_mem( + traits::CSR, + tu.constant(csr, 16U), + CSRtmp1_val_v); + } + 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 32), + 64, + true), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + if(rd != 0){ + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + tu.read_mem(traits::MEM, offs_val, 64), + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.load(rs1 + traits::X0, 0), + 64, false), + tu.constant(imm, 64U)); + auto MEMtmp0_val_v = tu.assignment("MEMtmp0_val", tu.load(rs2 + traits::X0, 0), 64); + tu.write_mem( + traits::MEM, + offs_val, + MEMtmp0_val_v); + 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, std::ostringstream& os){ + 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.add( + tu.ext( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + 32, false), + tu.constant(imm, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.shl( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.constant(shamt, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.lshr( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.constant(shamt, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.ashr( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.constant(shamt, 32U)); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.add( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + )); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.sub( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + )); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + res_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.l_and( + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + ), + tu.constant(mask_val, 32U)); + auto sh_val_val = tu.shl( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + count_val); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.l_and( + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + ), + tu.constant(mask_val, 32U)); + auto sh_val_val = tu.lshr( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + count_val); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::ostringstream& os){ + 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.l_and( + tu.trunc( + tu.load(rs2 + traits::X0, 0), + 32 + ), + tu.constant(mask_val, 32U)); + auto sh_val_val = tu.ashr( + tu.trunc( + tu.load(rs1 + traits::X0, 0), + 32 + ), + count_val); + auto Xtmp0_val_v = tu.assignment("Xtmp0_val", tu.ext( + sh_val_val, + 64, + false), 64); + tu.store(Xtmp0_val_v, 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, std::stringstream& os) { - 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); + 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); - 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); + 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; } }; @@ -643,7 +2546,7 @@ vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) template std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, std::ostringstrem& os) { +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; @@ -669,50 +2572,31 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, this_block); + return (this->*f)(pc, insn, tu); } -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(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_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(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_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(tu_builder& tu, unsigned type) { } -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(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;"); } -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 std::string vm_impl::gen_trap_check(BasicBlock *bb) { - return fmt::format("if(*(uint32_t){})!=0) goto trap_blk;\n", get_reg_ptr(arch::traits::TRAP_STATE)); - -} -} // namespace rv64i +} // namespace mnrv32 template <> std::unique_ptr create(arch::rv64i *core, unsigned short port, bool dump) {