diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a80cb5..8b70e49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.3) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_CURRENT_SOURCE_DIR}/sc-components/cmake) set(ENABLE_SCV TRUE CACHE BOOL "Enable use of SCV") +set(ENABLE_SHARED TRUE CACHE BOOL "Build shared libraries") include(GitFunctions) get_branch_from_git() @@ -32,7 +33,8 @@ include(Conan) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) - +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE) if(COMPILER_SUPPORTS_MARCH_NATIVE) @@ -112,7 +114,6 @@ add_subdirectory(sc-components) add_subdirectory(softfloat) GET_DIRECTORY_PROPERTY(SOFTFLOAT_INCLUDE_DIRS DIRECTORY softfloat DEFINITION SOFTFLOAT_INCLUDE_DIRS) add_subdirectory(riscv) -add_subdirectory(riscv.sc) add_subdirectory(platform) message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}") diff --git a/conanfile.txt b/conanfile.txt index c1205ab..3d6f0e2 100644 --- a/conanfile.txt +++ b/conanfile.txt @@ -1,6 +1,7 @@ [requires] - gsl_microsoft/20180102@bincrafters/stable - spdlog/0.16.3@bincrafters/stable + gsl_microsoft/20180102@bincrafters/stable + spdlog/0.16.3@bincrafters/stable + fmt/5.2.1@bincrafters/stable Seasocks/1.3.2@minres/stable SystemC/2.3.2@minres/stable SystemCVerification/2.0.1@minres/stable @@ -11,7 +12,8 @@ [options] Seasocks:shared=True + fmt:header_only=True SystemC:stdcxx=14 SystemC:shared=True SystemCVerification:stdcxx=14 - SystemC-CCI:stdcxx=14 \ No newline at end of file + SystemC-CCI:stdcxx=14 diff --git a/dbt-core b/dbt-core index f76938c..a9d8080 160000 --- a/dbt-core +++ b/dbt-core @@ -1 +1 @@ -Subproject commit f76938cbdc90da4c8fbab0fa36a155f3e0816af7 +Subproject commit a9d808088e64622a6c9bf52071436e9df206bae3 diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index 43054c9..a96449f 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -25,7 +25,6 @@ endif() add_dependent_subproject(dbt-core) add_dependent_subproject(sc-components) add_dependent_subproject(riscv) -add_dependent_subproject(riscv.sc) include_directories( ${PROJECT_SOURCE_DIR}/../external/elfio diff --git a/platform/src/CMakeLists.txt b/platform/src/CMakeLists.txt index b5b9a04..fd1f117 100644 --- a/platform/src/CMakeLists.txt +++ b/platform/src/CMakeLists.txt @@ -30,7 +30,17 @@ set(LIBRARY_NAME platform) #add_definitions(-DSC_DEFAULT_WRITER_POLICY=SC_MANY_WRITERS) # Define the library -add_library(${LIBRARY_NAME} ${LIB_SOURCES}) +add_library(${LIBRARY_NAME} SHARED ${LIB_SOURCES}) + +# Links the target exe against the libraries +target_link_libraries(${LIBRARY_NAME} riscv_sc) +target_link_libraries(${LIBRARY_NAME} dbt-core) +target_link_libraries(${LIBRARY_NAME} softfloat) +target_link_libraries(${LIBRARY_NAME} sc-components) +target_link_libraries(${LIBRARY_NAME} ${CONAN_LIBS_SEASOCKS}) +target_link_libraries(${LIBRARY_NAME} external) +target_link_libraries(${LIBRARY_NAME} ${llvm_libs}) +target_link_libraries(${LIBRARY_NAME} ${Boost_LIBRARIES} ) set_target_properties(${LIBRARY_NAME} PROPERTIES VERSION ${VERSION} # ${VERSION} was defined in the main CMakeLists. @@ -61,8 +71,7 @@ add_executable(${APPLICATION_NAME} ${APP_SOURCES}) target_include_directories(${APPLICATION_NAME} SYSTEM PRIVATE ${LLVM_INCLUDE_DIRS}) # Links the target exe against the libraries target_link_libraries(${APPLICATION_NAME} ${LIBRARY_NAME}) -target_link_libraries(${APPLICATION_NAME} riscv.sc) -target_link_libraries(${APPLICATION_NAME} riscv) +target_link_libraries(${APPLICATION_NAME} riscv_sc) target_link_libraries(${APPLICATION_NAME} dbt-core) target_link_libraries(${APPLICATION_NAME} softfloat) target_link_libraries(${APPLICATION_NAME} sc-components) diff --git a/platform/src/sc_main.cpp b/platform/src/sc_main.cpp index d9d60e3..27c058a 100644 --- a/platform/src/sc_main.cpp +++ b/platform/src/sc_main.cpp @@ -32,7 +32,6 @@ #include "CLIParser.h" #include -#include #include #include @@ -45,6 +44,7 @@ #include #include +#include #include #include diff --git a/platform/src/sysc/fe310.cpp b/platform/src/sysc/fe310.cpp index 70bbed6..1cab7e2 100644 --- a/platform/src/sysc/fe310.cpp +++ b/platform/src/sysc/fe310.cpp @@ -83,13 +83,13 @@ fe310::fe310(sc_core::sc_module_name nm) size_t i = 0; for (const auto &e : e300_plat_t_map) { i_router->initiator.at(i)(e.target); - i_router->add_target_range(i, e.start, e.size); + i_router->set_target_range(i, e.start, e.size); i++; } i_router->initiator.at(i)(i_mem_qspi->target); - i_router->add_target_range(i, 0x20000000, 512_MB); + i_router->set_target_range(i, 0x20000000, 512_MB); i_router->initiator.at(++i)(i_mem_ram->target); - i_router->add_target_range(i, 0x80000000, 128_kB); + i_router->set_target_range(i, 0x80000000, 128_kB); i_uart0->clk_i(s_tlclk); i_uart1->clk_i(s_tlclk); diff --git a/platform/src/sysc/plic.cpp b/platform/src/sysc/plic.cpp index e0b1b64..9956fd4 100644 --- a/platform/src/sysc/plic.cpp +++ b/platform/src/sysc/plic.cpp @@ -50,7 +50,7 @@ plic::plic(sc_core::sc_module_name nm) { regs->registerResources(*this); // register callbacks - regs->claim_complete.set_write_cb([this](scc::sc_register reg, uint32_t v, sc_core::sc_time d) -> bool { + regs->claim_complete.set_write_cb([this](scc::sc_register& reg, uint32_t v, sc_core::sc_time d) -> bool { reg.put(v); reset_pending_int(v); // std::cout << "Value of register: 0x" << std::hex << reg << std::endl; diff --git a/riscv.sc/CMakeLists.txt b/riscv.sc/CMakeLists.txt deleted file mode 100644 index 73afb67..0000000 --- a/riscv.sc/CMakeLists.txt +++ /dev/null @@ -1,93 +0,0 @@ -cmake_minimum_required(VERSION 3.3) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) # main (top) cmake dir - -# CMake useful variables -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") - -# Set the name of your project here -project("riscv.sc") - -include(Common) - -# check that we have averything we need -if(!SystemC_FOUND) - message( FATAL_ERROR "SystemC library not found." ) -endif() - -if(!CCI_FOUND) - message( FATAL_ERROR "SystemC CCI library not found." ) -endif() - -add_definitions(-DWITH_SYSTEMC) -include_directories(${SystemC_INCLUDE_DIRS}) -link_directories(${SystemC_LIBRARY_DIRS}) - -include_directories(${CCI_INCLUDE_DIRS}) -link_directories(${CCI_LIBRARY_DIRS}) - -if(SCV_FOUND) - add_definitions(-DWITH_SCV) - include_directories(${SCV_INCLUDE_DIRS}) - link_directories(${SCV_LIBRARY_DIRS}) -endif() - -# This sets the include directory for the reference project. This is the -I flag in gcc. -include_directories( - ${PROJECT_SOURCE_DIR}/incl - ${LLVM_INCLUDE_DIRS} -) - -add_dependent_subproject(dbt-core) -add_dependent_subproject(sc-components) -add_dependent_subproject(riscv) - -include_directories( - ${PROJECT_SOURCE_DIR}/incl - ${PROJECT_SOURCE_DIR}/../riscv/incl - ${PROJECT_SOURCE_DIR}/../external/elfio - ${PROJECT_SOURCE_DIR}/../external/libGIS - ${Boost_INCLUDE_DIRS} -) - - -# Mac needed variables (adapt for your needs - http://www.cmake.org/Wiki/CMake_RPATH_handling#Mac_OS_X_and_the_RPATH) -set(CMAKE_MACOSX_RPATH ON) -set(CMAKE_SKIP_BUILD_RPATH FALSE) -set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) -set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) - -## the following setting needs to be consistent with the library -#add_definitions(-DSC_DEFAULT_WRITER_POLICY=SC_MANY_WRITERS) - -# library files -FILE(GLOB RiscVSCHeaders *.h */*.h) - -set(LIB_HEADERS ${RiscVSCHeaders} ) -set(LIB_SOURCES src/core_complex.cpp ) - -# Define two variables in order not to repeat ourselves. -set(LIBRARY_NAME riscv.sc) - -# Define the library -add_library(${LIBRARY_NAME} ${LIB_SOURCES}) - -set_target_properties(${LIBRARY_NAME} PROPERTIES - VERSION ${VERSION} # ${VERSION} was defined in the main CMakeLists. - FRAMEWORK FALSE - PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers -) - -# -# SYSTEM PACKAGING (RPM, TGZ, ...) -# _____________________________________________________________________________ - -#include(CPackConfig) - -# -# CMAKE PACKAGING (for other CMake projects to use this one easily) -# _____________________________________________________________________________ - -#include(PackageConfigurator) \ No newline at end of file diff --git a/riscv/gen_input/RISCVBase.core_desc b/riscv/gen_input/RISCVBase.core_desc new file mode 100644 index 0000000..abc6a4a --- /dev/null +++ b/riscv/gen_input/RISCVBase.core_desc @@ -0,0 +1,50 @@ +InsructionSet RISCVBase { + constants { + XLEN, + fence:=0, + fencei:=1, + fencevmal:=2, + fencevmau:=3 + } + + address_spaces { + MEM[8], CSR[XLEN], FENCE[XLEN], RES[8] + } + + registers { + [31:0] X[XLEN], + PC[XLEN](is_pc), + alias ZERO[XLEN] is X[0], + alias RA[XLEN] is X[1], + alias SP[XLEN] is X[2], + alias GP[XLEN] is X[3], + alias TP[XLEN] is X[4], + alias T0[XLEN] is X[5], + alias T1[XLEN] is X[6], + alias T2[XLEN] is X[7], + alias S0[XLEN] is X[8], + alias S1[XLEN] is X[9], + alias A0[XLEN] is X[10], + alias A1[XLEN] is X[11], + alias A2[XLEN] is X[12], + alias A3[XLEN] is X[13], + alias A4[XLEN] is X[14], + alias A5[XLEN] is X[15], + alias A6[XLEN] is X[16], + alias A7[XLEN] is X[17], + alias S2[XLEN] is X[18], + alias S3[XLEN] is X[19], + alias S4[XLEN] is X[20], + alias S5[XLEN] is X[21], + alias S6[XLEN] is X[22], + alias S7[XLEN] is X[23], + alias S8[XLEN] is X[24], + alias S9[XLEN] is X[25], + alias S10[XLEN] is X[26], + alias S11[XLEN] is X[27], + alias T3[XLEN] is X[28], + alias T4[XLEN] is X[29], + alias T5[XLEN] is X[30], + alias T6[XLEN] is X[31] + } +} \ No newline at end of file diff --git a/riscv/gen_input/RV32A.core_desc b/riscv/gen_input/RV32A.core_desc deleted file mode 100644 index 16638c5..0000000 --- a/riscv/gen_input/RV32A.core_desc +++ /dev/null @@ -1,108 +0,0 @@ -import "RV32IBase.core_desc" - -InsructionSet RV32A extends RV32IBase{ - - address_spaces { - RES[8] - } - - instructions{ - LR.W { - encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b010 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d"; - if(rd!=0){ - val offs[XLEN] <= X[rs1]; - X[rd]<= sext(MEM[offs]{32}, XLEN); - RES[offs]{32}<=sext(-1, 32); - } - } - SC.W { - encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d"; - val offs[XLEN] <= X[rs1]; - val res1[32] <= RES[offs]{32}; - if(res1!=0) - MEM[offs]{32} <= X[rs2]; - if(rd!=0) X[rd]<= choose(res1!=0, 0, 1); - } - AMOSWAP.W{ - encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; - val offs[XLEN]<=X[rs1]; - if(rd!=0) X[rd]<=sext(MEM[offs]{32}); - MEM[offs]{32}<=X[rs2]; - } - AMOADD.W{ - encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; - val offs[XLEN]<=X[rs1]; - val res1[XLEN] <= sext(MEM[offs]{32}); - if(rd!=0) X[rd]<=res1; - val res2[XLEN]<=res1 + X[rs2]; - MEM[offs]{32}<=res2; - } - AMOXOR.W{ - encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; - val offs[XLEN]<=X[rs1]; - val res1[XLEN] <= sext(MEM[offs]{32}); - if(rd!=0) X[rd]<=res1; - val res2[XLEN]<=res1 ^ X[rs2]; - MEM[offs]{32}<=res2; - } - AMOAND.W{ - encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; - val offs[XLEN]<=X[rs1]; - val res1[XLEN] <= sext(MEM[offs]{32}); - if(rd!=0) X[rd]<=res1; - val res2[XLEN] <=res1 & X[rs2]; - MEM[offs]{32}<=res2; - } - AMOOR.W { - encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; - val offs[XLEN]<=X[rs1]; - val res1[XLEN] <= sext(MEM[offs]{32}); - if(rd!=0) X[rd]<=res1; - val res2[XLEN]<=res1 | X[rs2]; - MEM[offs]{32}<=res2; - } - AMOMIN.W{ - encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; - val offs[XLEN]<=X[rs1]; - val res1[XLEN] <= sext(MEM[offs]{32}); - if(rd!=0) X[rd]<=res1; - val res2[XLEN]<= choose(res1's>X[rs2]s, X[rs2], res1); - MEM[offs]{32}<=res2; - } - AMOMAX.W{ - encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; - val offs[XLEN]<=X[rs1]; - val res1[XLEN] <= sext(MEM[offs]{32}); - if(rd!=0) X[rd]<=res1; - val res2[XLEN]<= choose(res1'sX[rs2], X[rs2], res1); - MEM[offs]{32}<=res2; - } - AMOMAXU.W{ - encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; - val offs[XLEN]<=X[rs1]; - val res1[XLEN] <= zext(MEM[offs]{32}); - if(rd!=0) X[rd]<=res1; - val res2[XLEN]<= choose(res1'uF[rs2]f, F[rs1]f, F[rs2]f); - val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32)); - if(FLEN==32) - F[rd] <= res; - else { // NaN boxing - val upper[FLEN] <= -1; - F[rd] <= (upper<<32) | zext(res, FLEN); - } - val flags[32] <= fdispatch_fget_flags(); - FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; - } - FCVT.W.S { - encoding: b1100000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d"; - X[rd]<= sext(fdispatch_fcvt_s(F[rs1]{32}, zext(0, 32), rm{8}), XLEN); - val flags[32] <= fdispatch_fget_flags(); - FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; - } - FCVT.WU.S { - encoding: b1100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d"; - X[rd]<= zext(fdispatch_fcvt_s(F[rs1]{32}, zext(1, 32), rm{8}), XLEN); - val flags[32] <= fdispatch_fget_flags(); - FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; - } - FEQ.S { - encoding: b1010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; - X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(0, 32)); - val flags[32] <= fdispatch_fget_flags(); - FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; - } - FLT.S { - encoding: b1010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; - X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(2, 32)); - val flags[32] <= fdispatch_fget_flags(); - FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; - } - FLE.S { - encoding: b1010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; - X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32)); - val flags[32] <= fdispatch_fget_flags(); - FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; - } - FCLASS.S { - encoding: b1110000 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d"; - X[rd]<=fdispatch_fclass_s(F[rs1]{32}); - } - FCVT.S.W { - encoding: b1101000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"f%rd$d, x%rs1$d"; - val res[32] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8}); - if(FLEN==32) - F[rd] <= res; - else { // NaN boxing - val upper[FLEN] <= -1; - F[rd] <= (upper<<32) | zext(res, FLEN); - } - } - FCVT.S.WU { - encoding: b1101000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"f%rd$d, x%rs1$d"; - val res[32] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8}); - if(FLEN==32) - F[rd] <= res; - else { // NaN boxing - val upper[FLEN] <= -1; - F[rd] <= (upper<<32) | zext(res, FLEN); - } - } - FMV.X.W { - encoding: b1110000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d"; - X[rd]<=sext(F[rs1]{32}); - } - FMV.W.X { - encoding: b1111000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011; - args_disass:"f%rd$d, x%rs1$d"; - if(FLEN==32) - F[rd] <= X[rs1]; - else { // NaN boxing - val upper[FLEN] <= -1; - F[rd] <= (upper<<32) | zext(X[rs1], FLEN); - } - } - } -} \ No newline at end of file diff --git a/riscv/gen_input/RV32IBase.core_desc b/riscv/gen_input/RV32I.core_desc similarity index 77% rename from riscv/gen_input/RV32IBase.core_desc rename to riscv/gen_input/RV32I.core_desc index c768d8f..991bc19 100644 --- a/riscv/gen_input/RV32IBase.core_desc +++ b/riscv/gen_input/RV32I.core_desc @@ -1,44 +1,27 @@ -InsructionSet RV32IBase { - constants { - XLEN, - PCLEN, - XLEN_BIT_MASK:=0x1f, - fence:=0, - fencei:=1, - fencevmal:=2, - fencevmau:=3 - } - - address_spaces { - MEM[8], CSR[XLEN], FENCE[XLEN] - } - - registers { - [31:0] X[XLEN], - PC[XLEN](is_pc), - alias ZERO[XLEN] is X[0] - } +import "RISCVBase.core_desc" + +InsructionSet RV32I extends RISCVBase{ instructions { LUI{ encoding: imm[31:12]s | rd[4:0] | b0110111; - args_disass: "x%rd$d, 0x%imm$05x"; + args_disass: "{name(rd)}, {imm:#05x}"; if(rd!=0) X[rd] <= imm; } AUIPC{ encoding: imm[31:12]s | rd[4:0] | b0010111; - args_disass: "x%rd%, 0x%imm$08x"; + args_disass: "{name(rd)}, {imm:#08x}"; if(rd!=0) X[rd] <= PC's+imm; } JAL(no_cont){ encoding: imm[20:20]s | imm[10:1]s | imm[11:11]s | imm[19:12]s | rd[4:0] | b1101111; - args_disass: "x%rd$d, 0x%imm$x"; + args_disass: "{name(rd)}, {imm:#0x}"; if(rd!=0) X[rd] <= PC+4; PC<=PC's+imm; } JALR(no_cont){ encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111; - args_disass: "x%rd$d, x%rs1$d, 0x%imm$x"; + args_disass: "{name(rd)}, {name(rs1)}, {imm:#0x}"; val new_pc[XLEN] <= X[rs1]'s+ imm; val align[XLEN] <= new_pc & 0x2; if(align != 0){ @@ -50,116 +33,116 @@ InsructionSet RV32IBase { } BEQ(no_cont,cond){ encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:1]s | imm[11:11]s | b1100011; - args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; + args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}"; PC<=choose(X[rs1]==X[rs2], PC's+imm, PC+4); } BNE(no_cont,cond){ encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:1]s | imm[11:11]s | b1100011; - args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; + args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}"; PC<=choose(X[rs1]!=X[rs2], PC's+imm, PC+4); } BLT(no_cont,cond){ encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b100 | imm[4:1]s | imm[11:11]s | b1100011; - args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; + args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}"; PC<=choose(X[rs1]s=X[rs2]s, PC's+imm, PC+4); } BLTU(no_cont,cond) { encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b110 | imm[4:1]s | imm[11:11]s | b1100011; - args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; + args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}"; PC<=choose(X[rs1]=X[rs2], PC's+imm, PC+4); } LB { encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0000011; - args_disass:"x%rd$d, %imm%(x%rs1$d)"; + args_disass:"{name(rd)}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s+imm; if(rd!=0) X[rd]<=sext(MEM[offs]); } LH { encoding: imm[11:0]s | rs1[4:0] | b001 | rd[4:0] | b0000011; - args_disass:"x%rd$d, %imm%(x%rs1$d)"; + args_disass:"{name(rd)}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s+imm; if(rd!=0) X[rd]<=sext(MEM[offs]{16}); } LW { encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000011; - args_disass:"x%rd$d, %imm%(x%rs1$d)"; + args_disass:"{name(rd)}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s+imm; if(rd!=0) X[rd]<=sext(MEM[offs]{32}); } LBU { encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0000011; - args_disass:"x%rd$d, %imm%(x%rs1$d)"; + args_disass:"{name(rd)}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s+imm; if(rd!=0) X[rd]<=zext(MEM[offs]); } LHU { encoding: imm[11:0]s | rs1[4:0] | b101 | rd[4:0] | b0000011; - args_disass:"x%rd$d, %imm%(x%rs1$d)"; + args_disass:"{name(rd)}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s+imm; if(rd!=0) X[rd]<=zext(MEM[offs]{16}); } SB { encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:0]s | b0100011; - args_disass:"x%rs2$d, %imm%(x%rs1$d)"; + args_disass:"{name(rs2)}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s + imm; MEM[offs] <= X[rs2]; } SH { encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:0]s | b0100011; - args_disass:"x%rs2$d, %imm%(x%rs1$d)"; + args_disass:"{name(rs2)}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s + imm; MEM[offs]{16} <= X[rs2]; } SW { encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100011; - args_disass:"x%rs2$d, %imm%(x%rs1$d)"; + args_disass:"{name(rs2)}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s + imm; MEM[offs]{32} <= X[rs2]; } ADDI { encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %imm%"; + args_disass:"{name(rd)}, {name(rs1)}, {imm}"; if(rd != 0) X[rd] <= X[rs1]'s + imm; } SLTI { encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %imm%"; + args_disass:"{name(rd)}, {name(rs1)}, {imm}"; if (rd != 0) X[rd] <= choose(X[rs1]s < imm's, 1, 0); } SLTIU { encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %imm%"; + args_disass:"{name(rd)}, {name(rs1)}, {imm}"; val full_imm[XLEN] <= imm's; if (rd != 0) X[rd] <= choose(X[rs1]'u < full_imm'u, 1, 0); } XORI { encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %imm%"; + args_disass:"{name(rd)}, {name(rs1)}, {imm}"; if(rd != 0) X[rd] <= X[rs1]s ^ imm; } ORI { encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %imm%"; + args_disass:"{name(rd)}, {name(rs1)}, {imm}"; if(rd != 0) X[rd] <= X[rs1]s | imm; } ANDI { encoding: imm[11:0]s | rs1[4:0] | b111 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %imm%"; + args_disass:"{name(rd)}, {name(rs1)}, {imm}"; if(rd != 0) X[rd] <= X[rs1]s & imm; } SLLI { encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; + args_disass:"{name(rd)}, {name(rs1)}, {shamt}"; if(shamt > 31){ raise(0,0); } else { @@ -168,7 +151,7 @@ InsructionSet RV32IBase { } SRLI { encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; + args_disass:"{name(rd)}, {name(rs1)}, {shamt}"; if(shamt > 31){ raise(0,0); } else { @@ -177,7 +160,7 @@ InsructionSet RV32IBase { } SRAI { encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; + args_disass:"{name(rd)}, {name(rs1)}, {shamt}"; if(shamt > 31){ raise(0,0); } else { @@ -186,52 +169,52 @@ InsructionSet RV32IBase { } ADD { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; if(rd != 0) X[rd] <= X[rs1] + X[rs2]; } SUB { encoding: b0100000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; if(rd != 0) X[rd] <= X[rs1] - X[rs2]; } SLL { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0) X[rd] <= shll(X[rs1], X[rs2]&XLEN_BIT_MASK); + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; + if(rd != 0) X[rd] <= shll(X[rs1], X[rs2]&(XLEN-1)); } SLT { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; if (rd != 0) X[rd] <= choose(X[rs1]s < X[rs2]s, 1, 0); } SLTU { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; if (rd != 0) X[rd] <= choose(zext(X[rs1]) < zext(X[rs2]), 1, 0); } XOR { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; if(rd != 0) X[rd] <= X[rs1] ^ X[rs2]; } SRL { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0) X[rd] <= shrl(X[rs1], X[rs2]&XLEN_BIT_MASK); + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; + if(rd != 0) X[rd] <= shrl(X[rs1], X[rs2]&(XLEN-1)); } SRA { encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0) X[rd] <= shra(X[rs1], X[rs2]&XLEN_BIT_MASK); + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; + if(rd != 0) X[rd] <= shra(X[rs1], X[rs2]&(XLEN-1)); } OR { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; if(rd != 0) X[rd] <= X[rs1] | X[rs2]; } AND { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; if(rd != 0) X[rd] <= X[rs1] & X[rs2]; } FENCE { @@ -273,20 +256,20 @@ InsructionSet RV32IBase { } CSRRW { encoding: csr[11:0] | rs1[4:0] | b001 | rd[4:0] | b1110011; - args_disass:"x%rd$d, %csr$d, x%rs1$d"; + args_disass:"{name(rd)}, {csr}, {name(rs1)}"; val rs_val[XLEN] <= X[rs1]; if(rd!=0){ val csr_val[XLEN] <= CSR[csr]; CSR[csr] <= rs_val; // make sure Xrd is updated once CSR write succeeds - X[rd] <= csr_val; - } else { + X[rd] <= csr_val; + } else { CSR[csr] <= rs_val; } } CSRRS { encoding: csr[11:0] | rs1[4:0] | b010 | rd[4:0] | b1110011; - args_disass:"x%rd$d, %csr$d, x%rs1$d"; + args_disass:"{name(rd)}, {csr}, {name(rs1)}"; val xrd[XLEN] <= CSR[csr]; val xrs1[XLEN] <= X[rs1]; if(rd!=0) X[rd] <= xrd; @@ -294,7 +277,7 @@ InsructionSet RV32IBase { } CSRRC { encoding: csr[11:0] | rs1[4:0] | b011 | rd[4:0] | b1110011; - args_disass:"x%rd$d, %csr$d, x%rs1$d"; + args_disass:"{name(rd)}, {csr}, {name(rs1)}"; val xrd[XLEN] <= CSR[csr]; val xrs1[XLEN] <= X[rs1]; if(rd!=0) X[rd] <= xrd; @@ -302,13 +285,13 @@ InsructionSet RV32IBase { } CSRRWI { encoding: csr[11:0] | zimm[4:0] | b101 | rd[4:0] | b1110011; - args_disass:"x%rd$d, %csr$d, 0x%zimm$x"; + args_disass:"{name(rd)}, {csr}, {zimm:#0x}"; if(rd!=0) X[rd] <= CSR[csr]; CSR[csr] <= zext(zimm); } CSRRSI { encoding: csr[11:0] | zimm[4:0] | b110 | rd[4:0] | b1110011; - args_disass:"x%rd$d, %csr$d, 0x%zimm$x"; + args_disass:"{name(rd)}, {csr}, {zimm:#0x}"; val res[XLEN] <= CSR[csr]; if(zimm!=0) CSR[csr] <= res | zext(zimm); // make sure rd is written after csr write succeeds @@ -316,7 +299,7 @@ InsructionSet RV32IBase { } CSRRCI { encoding: csr[11:0] | zimm[4:0] | b111 | rd[4:0] | b1110011; - args_disass:"x%rd$d, %csr$d, 0x%zimm$x"; + args_disass:"{name(rd)}, {csr}, {zimm:#0x}"; val res[XLEN] <= CSR[csr]; if(rd!=0) X[rd] <= res; if(zimm!=0) CSR[csr] <= res & ~zext(zimm, XLEN); diff --git a/riscv/gen_input/RV32M.core_desc b/riscv/gen_input/RV32M.core_desc deleted file mode 100644 index a115295..0000000 --- a/riscv/gen_input/RV32M.core_desc +++ /dev/null @@ -1,97 +0,0 @@ -import "RV32IBase.core_desc" - -InsructionSet RV32M extends RV32IBase { - constants { - MAXLEN:=128 - } - instructions{ - MUL{ - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN); - X[rd]<= zext(res , XLEN); - } - } - MULH { - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - val res[MAXLEN] <= sext(X[rs1], MAXLEN) * sext(X[rs2], MAXLEN); - X[rd]<= zext(res >> XLEN, XLEN); - } - } - MULHSU { - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - val res[MAXLEN] <= sext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN); - X[rd]<= zext(res >> XLEN, XLEN); - } - } - MULHU { - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN); - X[rd]<= zext(res >> XLEN, XLEN); - } - } - DIV { - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - if(X[rs2]!=0){ - val M1[XLEN] <= -1; - val MMIN[XLEN] <= -1<<(XLEN-1); - if(X[rs1]s==MMIN's) - if(X[rs2]s==M1's) - X[rd]<=MMIN; - else - X[rd] <= X[rs1]s / X[rs2]s; - else - X[rd] <= X[rs1]s / X[rs2]s; - }else - X[rd] <= -1; - } - } - DIVU { - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - if(X[rs2]!=0) - X[rd] <= zext(X[rs1], 32) / zext(X[rs2], 32); - else - X[rd] <= -1; - } - } - REM { - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - if(X[rs2]!=0) { - val M1[XLEN] <= -1; - val MMIN[XLEN] <= -1<<(XLEN-1); - if(X[rs1]s==MMIN's) - if(X[rs2]s==M1's) - X[rd] <= 0; - else - X[rd] <= sext(X[rs1], 32) % sext(X[rs2], 32); - else - X[rd] <= sext(X[rs1], 32) % sext(X[rs2], 32); - } else - X[rd] <= X[rs1]; - } - } - REMU { - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0110011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - if(X[rs2]!=0) - X[rd] <= zext(X[rs1], 32) % zext(X[rs2], 32); - else - X[rd] <= X[rs1]; - } - } - } -} \ No newline at end of file diff --git a/riscv/gen_input/RV64A.core_desc b/riscv/gen_input/RV64A.core_desc deleted file mode 100644 index 5080d11..0000000 --- a/riscv/gen_input/RV64A.core_desc +++ /dev/null @@ -1,112 +0,0 @@ -import "RV64IBase.core_desc" -import "RV32A.core_desc" - -InsructionSet RV64A extends RV64IBase { - - address_spaces { - RES[8] - } - - instructions{ - LR.D { - encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b011 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d"; - if(rd!=0){ - val offs[XLEN] <= X[rs1]; - X[rd]<= sext(MEM[offs]{64}, XLEN); - RES[offs]{64}<=sext(-1, 64); - } - } - SC.D { - encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d"; - val offs[XLEN] <= X[rs1]; - val res[64] <= RES[offs]; - if(res!=0){ - MEM[offs]{64} <= X[rs2]; - if(rd!=0) X[rd]<=0; - } else{ - if(rd!=0) X[rd]<= 1; - } - } - AMOSWAP.D{ - encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; - val offs[XLEN] <= X[rs1]; - if(rd!=0) X[rd] <= sext(MEM[offs]{64}); - MEM[offs]{64} <= X[rs2]; - } - AMOADD.D{ - encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; - val offs[XLEN] <= X[rs1]; - val res[XLEN] <= sext(MEM[offs]{64}); - if(rd!=0) X[rd]<=res; - val res2[XLEN] <= res + X[rs2]; - MEM[offs]{64}<=res2; - } - AMOXOR.D{ - encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; - val offs[XLEN] <= X[rs1]; - val res[XLEN] <= sext(MEM[offs]{64}); - if(rd!=0) X[rd] <= res; - val res2[XLEN] <= res ^ X[rs2]; - MEM[offs]{64} <= res2; - } - AMOAND.D{ - encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; - val offs[XLEN] <= X[rs1]; - val res[XLEN] <= sext(MEM[offs]{64}); - if(rd!=0) X[rd] <= res; - val res2[XLEN] <= res & X[rs2]; - MEM[offs]{64} <= res2; - } - AMOOR.D { - encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; - val offs[XLEN] <= X[rs1]; - val res[XLEN] <= sext(MEM[offs]{64}); - if(rd!=0) X[rd] <= res; - val res2[XLEN] <= res | X[rs2]; - MEM[offs]{64} <= res2; - } - AMOMIN.D{ - encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; - val offs[XLEN] <= X[rs1]; - val res[XLEN] <= sext(MEM[offs]{64}); - if(rd!=0) X[rd] <= res; - val res2[XLEN] <= choose(res s > X[rs2]s, X[rs2], res); - MEM[offs]{64} <= res; - } - AMOMAX.D{ - encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; - val offs[XLEN] <= X[rs1]; - val res[XLEN] <= sext(MEM[offs]{64}); - if(rd!=0) X[rd] <= res; - val res2[XLEN] <= choose(res s < X[rs2]s, X[rs2], res); - MEM[offs]{64} <= res2; - } - AMOMINU.D{ - encoding: b11000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; - val offs[XLEN] <= X[rs1]; - val res[XLEN] <= zext(MEM[offs]{64}); - if(rd!=0) X[rd] <= res; - val res2[XLEN] <= choose(res > X[rs2], X[rs2], res); - MEM[offs]{64} <= res2; - } - AMOMAXU.D{ - encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; - args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; - val offs[XLEN] <= X[rs1]; - val res[XLEN] <= zext(MEM[offs]{64}); - if(rd!=0) X[rd] <= res; - val res2[XLEN] <= choose(res < X[rs2], X[rs2], res); - MEM[offs]{64} <= res2; - } - } -} \ No newline at end of file diff --git a/riscv/gen_input/RV64IBase.core_desc b/riscv/gen_input/RV64I.core_desc similarity index 80% rename from riscv/gen_input/RV64IBase.core_desc rename to riscv/gen_input/RV64I.core_desc index e44f754..59c3c0f 100644 --- a/riscv/gen_input/RV64IBase.core_desc +++ b/riscv/gen_input/RV64I.core_desc @@ -1,43 +1,43 @@ -import "RV32IBase.core_desc" +import "RV32I.core_desc" -InsructionSet RV64IBase extends RV32IBase { +InsructionSet RV64I extends RV32I { instructions{ LWU { // 80000104: 0000ef03 lwu t5,0(ra) encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0000011; - args_disass:"x%rd$d, %imm%(x%rs1$d)"; + args_disass:"{name(rd)}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s+imm; if(rd!=0) X[rd]<=zext(MEM[offs]{32}); } LD{ encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000011; - args_disass:"x%rd$d, %imm%(x%rs1$d)"; + args_disass:"{name(rd)}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s + imm; if(rd!=0) X[rd]<=sext(MEM[offs]{64}); } SD{ encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100011; - args_disass:"x%rs2$d, %imm%(x%rs1$d)"; + args_disass:"{name(rs2)}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s + imm; MEM[offs]{64} <= X[rs2]; } SLLI { encoding: b000000 | shamt[5:0] | rs1[4:0] | b001 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; + args_disass:"{name(rd)}, {name(rs1)}, {shamt}"; if(rd != 0) X[rd] <= shll(X[rs1], shamt); } SRLI { encoding: b000000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; + args_disass:"{name(rd)}, {name(rs1)}, {shamt}"; if(rd != 0) X[rd] <= shrl(X[rs1], shamt); } SRAI { encoding: b010000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; + args_disass:"{name(rd)}, {name(rs1)}, {shamt}"; if(rd != 0) X[rd] <= shra(X[rs1], shamt); } ADDIW { encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0011011; - args_disass:"x%rd$d, x%rs1$d, %imm%"; + args_disass:"{name(rd)}, {name(rs1)}, {imm}"; if(rd != 0){ val res[32] <= X[rs1]{32}'s + imm; X[rd] <= sext(res); @@ -45,7 +45,7 @@ InsructionSet RV64IBase extends RV32IBase { } SLLIW { encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0011011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; + args_disass:"{name(rd)}, {name(rs1)}, {shamt}"; if(rd != 0){ val sh_val[32] <= shll(X[rs1]{32}, shamt); X[rd] <= sext(sh_val); @@ -53,7 +53,7 @@ InsructionSet RV64IBase extends RV32IBase { } SRLIW { encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; + args_disass:"{name(rd)}, {name(rs1)}, {shamt}"; if(rd != 0){ val sh_val[32] <= shrl(X[rs1]{32}, shamt); X[rd] <= sext(sh_val); @@ -61,7 +61,7 @@ InsructionSet RV64IBase extends RV32IBase { } SRAIW { encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011; - args_disass:"x%rd$d, x%rs1$d, %shamt%"; + args_disass:"{name(rd)}, {name(rs1)}, {shamt}"; if(rd != 0){ val sh_val[32] <= shra(X[rs1]{32}, shamt); X[rd] <= sext(sh_val); @@ -83,7 +83,7 @@ InsructionSet RV64IBase extends RV32IBase { } SLLW { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0111011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; if(rd != 0){ val mask[32] <= 0x1f; val count[32] <= X[rs2]{32} & mask; @@ -93,7 +93,7 @@ InsructionSet RV64IBase extends RV32IBase { } SRLW { encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; if(rd != 0){ val mask[32] <= 0x1f; val count[32] <= X[rs2]{32} & mask; @@ -103,7 +103,7 @@ InsructionSet RV64IBase extends RV32IBase { } SRAW { encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; if(rd != 0){ val mask[32] <= 0x1f; val count[32] <= X[rs2]{32} & mask; diff --git a/riscv/gen_input/RV64M.core_desc b/riscv/gen_input/RV64M.core_desc deleted file mode 100644 index cb53da9..0000000 --- a/riscv/gen_input/RV64M.core_desc +++ /dev/null @@ -1,41 +0,0 @@ -import "RV64IBase.core_desc" - -InsructionSet RV64M extends RV64IBase { - instructions{ - MULW{ - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0111011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - X[rd]<= X[rs1] * X[rs2]; - } - } - DIVW { - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0111011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - X[rd] <= X[rs1]s / X[rs2]s; - } - } - DIVUW { - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - X[rd] <= X[rs1] / X[rs2]; - } - } - REMW { - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0111011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - X[rd] <= X[rs1]s % X[rs2]s; - } - } - REMUW { - encoding: b0000001 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0111011; - args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; - if(rd != 0){ - X[rd] <= X[rs1] % X[rs2]; - } - } - } -} \ No newline at end of file diff --git a/riscv/gen_input/RVA.core_desc b/riscv/gen_input/RVA.core_desc new file mode 100644 index 0000000..ff66baf --- /dev/null +++ b/riscv/gen_input/RVA.core_desc @@ -0,0 +1,210 @@ +import "RISCVBase.core_desc" + +InsructionSet RV32A extends RISCVBase{ + + instructions{ + LR.W { + encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b010 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}"; + if(rd!=0){ + val offs[XLEN] <= X[rs1]; + X[rd]<= sext(MEM[offs]{32}, XLEN); + RES[offs]{32}<=sext(-1, 32); + } + } + SC.W { + encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)}"; + val offs[XLEN] <= X[rs1]; + val res1[32] <= RES[offs]{32}; + if(res1!=0) + MEM[offs]{32} <= X[rs2]; + if(rd!=0) X[rd]<= choose(res1!=zext(0, 32), 0, 1); + } + AMOSWAP.W{ + encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN]<=X[rs1]; + if(rd!=0) X[rd]<=sext(MEM[offs]{32}); + MEM[offs]{32}<=X[rs2]; + } + AMOADD.W{ + encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN]<=X[rs1]; + val res1[XLEN] <= sext(MEM[offs]{32}); + if(rd!=0) X[rd]<=res1; + val res2[XLEN]<=res1 + X[rs2]; + MEM[offs]{32}<=res2; + } + AMOXOR.W{ + encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN]<=X[rs1]; + val res1[XLEN] <= sext(MEM[offs]{32}); + if(rd!=0) X[rd]<=res1; + val res2[XLEN]<=res1 ^ X[rs2]; + MEM[offs]{32}<=res2; + } + AMOAND.W{ + encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN]<=X[rs1]; + val res1[XLEN] <= sext(MEM[offs]{32}); + if(rd!=0) X[rd]<=res1; + val res2[XLEN] <=res1 & X[rs2]; + MEM[offs]{32}<=res2; + } + AMOOR.W { + encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN]<=X[rs1]; + val res1[XLEN] <= sext(MEM[offs]{32}); + if(rd!=0) X[rd]<=res1; + val res2[XLEN]<=res1 | X[rs2]; + MEM[offs]{32}<=res2; + } + AMOMIN.W{ + encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN]<=X[rs1]; + val res1[XLEN] <= sext(MEM[offs]{32}); + if(rd!=0) X[rd] <= res1; + val res2[XLEN] <= choose(res1's > X[rs2]s, X[rs2], res1); + MEM[offs]{32} <= res2; + } + AMOMAX.W{ + encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN]<=X[rs1]; + val res1[XLEN] <= sext(MEM[offs]{32}); + if(rd!=0) X[rd]<=res1; + val res2[XLEN]<= choose(res1'sX[rs2], X[rs2], res1); + MEM[offs]{32}<=res2; + } + AMOMAXU.W{ + encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN]<=X[rs1]; + val res1[XLEN] <= sext(MEM[offs]{32}); + if(rd!=0) X[rd] <= res1; + val res2[XLEN] <= choose(res1 < X[rs2], X[rs2], res1); + MEM[offs]{32} <= res2; + } + } +} + +InsructionSet RV64A extends RV32A { + + instructions{ + LR.D { + encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b011 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}"; + if(rd!=0){ + val offs[XLEN] <= X[rs1]; + X[rd]<= sext(MEM[offs]{64}, XLEN); + RES[offs]{64}<=sext(-1, 64); + } + } + SC.D { + encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)}"; + val offs[XLEN] <= X[rs1]; + val res[64] <= RES[offs]; + if(res!=0){ + MEM[offs]{64} <= X[rs2]; + if(rd!=0) X[rd]<=0; + } else{ + if(rd!=0) X[rd]<= 1; + } + } + AMOSWAP.D{ + encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN] <= X[rs1]; + if(rd!=0) X[rd] <= sext(MEM[offs]{64}); + MEM[offs]{64} <= X[rs2]; + } + AMOADD.D{ + encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN] <= X[rs1]; + val res[XLEN] <= sext(MEM[offs]{64}); + if(rd!=0) X[rd]<=res; + val res2[XLEN] <= res + X[rs2]; + MEM[offs]{64}<=res2; + } + AMOXOR.D{ + encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN] <= X[rs1]; + val res[XLEN] <= sext(MEM[offs]{64}); + if(rd!=0) X[rd] <= res; + val res2[XLEN] <= res ^ X[rs2]; + MEM[offs]{64} <= res2; + } + AMOAND.D{ + encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN] <= X[rs1]; + val res[XLEN] <= sext(MEM[offs]{64}); + if(rd!=0) X[rd] <= res; + val res2[XLEN] <= res & X[rs2]; + MEM[offs]{64} <= res2; + } + AMOOR.D { + encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN] <= X[rs1]; + val res[XLEN] <= sext(MEM[offs]{64}); + if(rd!=0) X[rd] <= res; + val res2[XLEN] <= res | X[rs2]; + MEM[offs]{64} <= res2; + } + AMOMIN.D{ + encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN] <= X[rs1]; + val res1[XLEN] <= sext(MEM[offs]{64}); + if(rd!=0) X[rd] <= res1; + val res2[XLEN] <= choose(res1's > X[rs2]s, X[rs2], res1); + MEM[offs]{64} <= res2; + } + AMOMAX.D{ + encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN] <= X[rs1]; + val res[XLEN] <= sext(MEM[offs]{64}); + if(rd!=0) X[rd] <= res; + val res2[XLEN] <= choose(res s < X[rs2]s, X[rs2], res); + MEM[offs]{64} <= res2; + } + AMOMINU.D{ + encoding: b11000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN] <= X[rs1]; + val res[XLEN] <= sext(MEM[offs]{64}); + if(rd!=0) X[rd] <= res; + val res2[XLEN] <= choose(res > X[rs2], X[rs2], res); + MEM[offs]{64} <= res2; + } + AMOMAXU.D{ + encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; + args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})"; + val offs[XLEN] <= X[rs1]; + val res1[XLEN] <= sext(MEM[offs]{64}); + if(rd!=0) X[rd] <= res1; + val res2[XLEN] <= choose(res1 < X[rs2], X[rs2], res1); + MEM[offs]{64} <= res2; + } + } +} diff --git a/riscv/gen_input/RV32C.core_desc b/riscv/gen_input/RVC.core_desc similarity index 65% rename from riscv/gen_input/RV32C.core_desc rename to riscv/gen_input/RVC.core_desc index f7de2f6..5c00c5d 100644 --- a/riscv/gen_input/RV32C.core_desc +++ b/riscv/gen_input/RVC.core_desc @@ -1,50 +1,36 @@ -import "RV32IBase.core_desc" +import "RISCVBase.core_desc" + +InsructionSet RV32IC extends RISCVBase{ -InsructionSet RV32IC { - constants { - XLEN - } - address_spaces { - MEM[8] - } - registers { - [31:0] X[XLEN], - PC[XLEN](is_pc) - } instructions{ JALR(no_cont){ // overwriting the implementation if rv32i, alignment does not need to be word encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111; - args_disass: "x%rd$d, x%rs1$d, 0x%imm$x"; - val new_pc[XLEN] <= X[rs1]s+ imm; - val align[XLEN] <= new_pc & 0x1; - if(align != 0){ - raise(0, 0); - } else { - if(rd!=0) X[rd] <= PC+4; - PC<=new_pc & ~0x1; - } + args_disass: "{name(rd)}, {name(rs1)}, {imm:#0x}"; + val new_pc[XLEN] <= X[rs1]s + imm; + if(rd!=0) X[rd] <= PC+4; + PC<=new_pc & ~0x1; } C.ADDI4SPN { //(RES, imm=0) encoding: b000 | imm[5:4] | imm[9:6] | imm[2:2] | imm[3:3] | rd[2:0] | b00; - args_disass: "x%rd$d, 0x%imm$05x"; + args_disass: "{name(rd)}, {imm:#05x}"; if(imm == 0) raise(0, 2); X[rd+8] <= X[2] + imm; } C.LW { // (RV32) encoding: b010 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00; - args_disass: "x(8+%rd$d), x(8+%rs1$d), 0x%uimm$05x"; + args_disass: "{name(8+rd)}, {uimm:#05x}({name(8+rs1)})"; val offs[XLEN] <= X[rs1+8]+uimm; - X[rd+8] <= MEM[offs]{32}; + X[rd+8] <= sext(MEM[offs]{32}); } C.SW {//(RV32) encoding: b110 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00; - args_disass: "x(8+%rs1$d), x(8+%rs2$d), 0x%uimm$05x"; + args_disass: "{name(8+rs2)}, {uimm:#05x}({name(8+rs1)})"; val offs[XLEN] <= X[rs1+8]+uimm; MEM[offs]{32} <= X[rs2+8]; } C.ADDI {//(RV32) encoding:b000 | imm[5:5]s | rs1[4:0] | imm[4:0]s | b01; - args_disass: "x%rs1$d, 0x%imm$05x"; + args_disass: "{name(rs1)}, {imm:#05x}"; X[rs1] <= X[rs1]'s + imm; } C.NOP { @@ -53,118 +39,118 @@ InsructionSet RV32IC { // C.JAL will be overwritten by C.ADDIW for RV64/128 C.JAL(no_cont) {//(RV32) encoding: b001 | imm[11:11]s | imm[4:4]s | imm[9:8]s | imm[10:10]s | imm[6:6]s | imm[7:7]s | imm[3:1]s | imm[5:5]s | b01; - args_disass: "0x%imm$05x"; + args_disass: "{imm:#05x}"; X[1] <= PC+2; PC<=PC's+imm; } C.LI {//(RV32) encoding:b010 | imm[5:5]s | rd[4:0] | imm[4:0]s | b01; - args_disass: "x%rd$d, 0x%imm$05x"; + args_disass: "{name(rd)}, {imm:#05x}"; if(rd == 0) raise(0, 2); //TODO: should it be handled as trap? X[rd] <= imm; } // order matters here as C.ADDI16SP overwrites C.LUI vor rd==2 C.LUI {//(RV32) encoding:b011 | imm[17:17] | rd[4:0] | imm[16:12]s | b01; - args_disass: "x%rd$d, 0x%imm$05x"; + args_disass: "{name(rd)}, {imm:#05x}"; if(rd == 0) raise(0, 2); //TODO: should it be handled as trap? if(imm == 0) raise(0, 2); //TODO: should it be handled as trap? X[rd] <= imm; } C.ADDI16SP {//(RV32) encoding:b011 | imm[9:9]s | b00010 | imm[4:4]s | imm[6:6]s | imm[8:7]s | imm[5:5]s | b01; - args_disass: "0x%imm$05x"; + args_disass: "{imm:#05x}"; X[2] <= X[2]s + imm; } C.SRLI {//(RV32 nse) encoding:b100 | b0 | b00 | rs1[2:0] | shamt[4:0] | b01; - args_disass: "x(8+%rs1$d), %shamt$d"; + args_disass: "{name(8+rs1)}, {shamt}"; val rs1_idx[5] <= rs1+8; X[rs1_idx] <= shrl(X[rs1_idx], shamt); } C.SRAI {//(RV32) encoding:b100 | b0 | b01 | rs1[2:0] | shamt[4:0] | b01; - args_disass: "x(8+%rs1$d), %shamt$d"; + args_disass: "{name(8+rs1)}, {shamt}"; val rs1_idx[5] <= rs1+8; X[rs1_idx] <= shra(X[rs1_idx], shamt); } C.ANDI {//(RV32) - encoding:b100 | imm[5:5] | b10 | rs1[2:0] | imm[4:0] | b01; - args_disass: "x(8+%rs1$d), 0x%imm$05x"; + encoding:b100 | imm[5:5]s | b10 | rs1[2:0] | imm[4:0]s | b01; + args_disass: "{name(8+rs1)}, {imm:#05x}"; val rs1_idx[5] <= rs1 + 8; - X[rs1_idx] <= X[rs1_idx] & imm; + X[rs1_idx] <= X[rs1_idx]s & imm; } C.SUB {//(RV32) encoding:b100 | b0 | b11 | rd[2:0] | b00 | rs2[2:0] | b01; - args_disass: "x(8+%rd$d), x(8+%rs2$d)"; + args_disass: "{name(8+rd)}, {name(8+rs2)}"; val rd_idx[5] <= rd + 8; X[rd_idx] <= X[rd_idx] - X[rs2 + 8]; } C.XOR {//(RV32) encoding:b100 | b0 | b11 | rd[2:0] | b01 | rs2[2:0] | b01; - args_disass: "x(8+%rd$d), x(8+%rs2$d)"; + args_disass: "{name(8+rd)}, {name(8+rs2)}"; val rd_idx[5] <= rd + 8; X[rd_idx] <= X[rd_idx] ^ X[rs2 + 8]; } C.OR {//(RV32) encoding:b100 | b0 | b11 | rd[2:0] | b10 | rs2[2:0] | b01; - args_disass: "x(8+%rd$d), x(8+%rs2$d)"; + args_disass: "{name(8+rd)}, {name(8+rs2)}"; val rd_idx[5] <= rd + 8; X[rd_idx] <= X[rd_idx] | X[rs2 + 8]; } C.AND {//(RV32) encoding:b100 | b0 | b11 | rd[2:0] | b11 | rs2[2:0] | b01; - args_disass: "x(8+%rd$d), x(8+%rs2$d)"; + args_disass: "{name(8+rd)}, {name(8+rs2)}"; val rd_idx[5] <= rd + 8; X[rd_idx] <= X[rd_idx] & X[rs2 + 8]; } C.J(no_cont) {//(RV32) encoding:b101 | imm[11:11]s | imm[4:4]s | imm[9:8]s | imm[10:10]s | imm[6:6]s | imm[7:7]s | imm[3:1]s | imm[5:5]s | b01; - args_disass: "0x%imm$05x"; + args_disass: "{imm:#05x}"; PC<=PC's+imm; } C.BEQZ(no_cont,cond) {//(RV32) encoding:b110 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s |imm[2:1]s | imm[5:5]s | b01; - args_disass: "x(8+%rs1$d), 0x%imm$05x"; + args_disass: "{name(8+rs1)}, {imm:#05x}"; PC<=choose(X[rs1+8]==0, PC's+imm, PC+2); } C.BNEZ(no_cont,cond) {//(RV32) encoding:b111 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s | imm[2:1]s | imm[5:5]s | b01; - args_disass: "x(8+%rs1$d), 0x%imm$05x"; + args_disass: "{name(8+rs1)}, {imm:#05x}"; PC<=choose(X[rs1+8]!=0, PC's+imm, PC+2); } C.SLLI {//(RV32) encoding:b000 | b0 | rs1[4:0] | shamt[4:0] | b10; - args_disass: "x%rs1$d, %shamt$d"; + args_disass: "{name(rs1)}, {shamt}"; if(rs1 == 0) raise(0, 2); X[rs1] <= shll(X[rs1], shamt); } C.LWSP {// encoding:b010 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10; - args_disass: "x%rd$d, sp, 0x%uimm$05x"; + args_disass: "{name(rd)}, sp, {uimm:#05x}"; val offs[XLEN] <= X[2] + uimm; - X[rd] <= MEM[offs]{32}; + X[rd] <= sext(MEM[offs]{32}); } // order matters as C.JR is a special case of C.MV C.MV {//(RV32) encoding:b100 | b0 | rd[4:0] | rs2[4:0] | b10; - args_disass: "x%rd$d, x%rs2$d"; + args_disass: "{name(rd)}, {name(rs2)}"; X[rd] <= X[rs2]; } C.JR(no_cont) {//(RV32) encoding:b100 | b0 | rs1[4:0] | b00000 | b10; - args_disass: "x%rs1$d"; + args_disass: "{name(rs1)}"; PC <= X[rs1]; } // order matters as C.EBREAK is a special case of C.JALR which is a special case of C.ADD C.ADD {//(RV32) encoding:b100 | b1 | rd[4:0] | rs2[4:0] | b10; - args_disass: "x%rd$d, x%rs2$d"; + args_disass: "{name(rd)}, {name(rs2)}"; X[rd] <= X[rd] + X[rs2]; } C.JALR(no_cont) {//(RV32) encoding:b100 | b1 | rs1[4:0] | b00000 | b10; - args_disass: "x%rs1$d"; + args_disass: "{name(rs1)}"; X[1] <= PC+2; PC<=X[rs1]; } @@ -174,7 +160,7 @@ InsructionSet RV32IC { } C.SWSP {// encoding:b110 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10; - args_disass: "x2+0x%uimm$05x, x%rs2$d"; + args_disass: "{name(rs2)}, {uimm:#05x}(sp)"; val offs[XLEN] <= X[2] + uimm; MEM[offs]{32} <= X[rs2]; } @@ -187,19 +173,15 @@ InsructionSet RV32IC { InsructionSet RV32FC extends RV32IC{ constants { - XLEN, FLEN - } - address_spaces { - MEM[8] + FLEN } registers { - [31:0] X[XLEN], [31:0] F[FLEN] } instructions{ C.FLW { encoding: b011 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00; - args_disass:"f(8+%rd$d), %uimm%(x(8+%rs1$d))"; + args_disass:"f(8+{rd}), {uimm}({name(8+rs1)})"; val offs[XLEN] <= X[rs1+8]+uimm; val res[32] <= MEM[offs]{32}; if(FLEN==32) @@ -211,13 +193,13 @@ InsructionSet RV32FC extends RV32IC{ } C.FSW { encoding: b111 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00; - args_disass:"f(8+%rs2$d), %uimm%(x(8+%rs1$d))"; + args_disass:"f(8+{rs2}), {uimm}({name(8+rs1)})"; val offs[XLEN] <= X[rs1+8]+uimm; MEM[offs]{32}<=F[rs2+8]{32}; } C.FLWSP { encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10; - args_disass:"f%rd$d, %uimm%(x2)"; + args_disass:"f{rd}, {uimm}(x2)"; val offs[XLEN] <= X[2]+uimm; val res[32] <= MEM[offs]{32}; if(FLEN==32) @@ -229,7 +211,7 @@ InsructionSet RV32FC extends RV32IC{ } C.FSWSP { encoding:b111 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10; - args_disass:"f%rs2$d, %uimm%(x2), "; + args_disass:"f{rs2}, {uimm}(x2), "; val offs[XLEN] <= X[2]+uimm; MEM[offs]{32}<=F[rs2]{32}; } @@ -238,19 +220,15 @@ InsructionSet RV32FC extends RV32IC{ InsructionSet RV32DC extends RV32IC{ constants { - XLEN, FLEN - } - address_spaces { - MEM[8] + FLEN } registers { - [31:0] X[XLEN], [31:0] F[FLEN] } instructions{ C.FLD { //(RV32/64) encoding: b001 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00; - args_disass:"f(8+%rd$d), %uimm%(x(8+%rs1$d))"; + args_disass:"f(8+{rd}), {uimm}({name(8+rs1)})"; val offs[XLEN] <= X[rs1+8]+uimm; val res[64] <= MEM[offs]{64}; if(FLEN==64) @@ -262,13 +240,13 @@ InsructionSet RV32DC extends RV32IC{ } C.FSD { //(RV32/64) encoding: b101 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00; - args_disass:"f(8+%rs2$d), %uimm%(x(8+%rs1$d))"; + args_disass:"f(8+{rs2}), {uimm}({name(8+rs1)})"; val offs[XLEN] <= X[rs1+8]+uimm; MEM[offs]{64}<=F[rs2+8]{64}; } C.FLDSP {//(RV32/64) encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10; - args_disass:"f%rd$d, %uimm%(x2)"; + args_disass:"f{rd}, {uimm}(x2)"; val offs[XLEN] <= X[2]+uimm; val res[64] <= MEM[offs]{64}; if(FLEN==64) @@ -280,7 +258,7 @@ InsructionSet RV32DC extends RV32IC{ } C.FSDSP {//(RV32/64) encoding:b101 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10; - args_disass:"f%rs2$d, %uimm%(x2), "; + args_disass:"f{rs2}, {uimm}(x2), "; val offs[XLEN] <= X[2]+uimm; MEM[offs]{64}<=F[rs2]{64}; } @@ -288,65 +266,94 @@ InsructionSet RV32DC extends RV32IC{ } InsructionSet RV64IC extends RV32IC { - constants { - XLEN - } - address_spaces { - MEM[8] - } - registers { - [31:0] X[XLEN], - PC[XLEN](is_pc) - } + instructions{ C.LD {//(RV64/128) encoding:b011 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00; + args_disass: "{name(8+rd)}, {uimm},({name(8+rs1)})"; + val offs[XLEN] <= X[rs1+8] + uimm; + X[rd+8]<=sext(MEM[offs]{64}); } C.SD { //(RV64/128) encoding:b111 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00; + args_disass: "{name(8+rs2)}, {uimm},({name(8+rs1)})"; + val offs[XLEN] <= X[rs1+8] + uimm; + MEM[offs]{64} <= X[rs2+8]; } C.SUBW {//(RV64/128, RV32 res) encoding:b100 | b1 | b11 | rd[2:0] | b00 | rs2[2:0] | b01; - args_disass: "x%rd$d, sp, 0x%imm$05x"; + args_disass: "{name(8+rd)}, {name(8+rd)}, {name(8+rs2)}"; + val res[32] <= X[rd+8]{32} - X[rs2+8]{32}; + X[rd+8] <= sext(res); } C.ADDW {//(RV64/128 RV32 res) encoding:b100 | b1 | b11 | rd[2:0] | b01 | rs2[2:0] | b01; - args_disass: "x%rd$d, sp, 0x%imm$05x"; + args_disass: "{name(8+rd)}, {name(8+rd)}, {name(8+rs2)}"; + val res[32] <= X[rd+8]{32} + X[rs2+8]{32}; + X[rd+8] <= sext(res); } C.ADDIW {//(RV64/128) - encoding:b001 | imm[5:5] | rs1[4:0] | imm[4:0] | b01; + encoding:b001 | imm[5:5]s | rs1[4:0] | imm[4:0]s | b01; + args_disass: "{name(rs1)}, {imm:#05x}"; + if(rs1 != 0){ + val res[32] <= X[rs1]{32}'s + imm; + X[rs1] <= sext(res); + } } - C.SRLI64 {//(RV32/64/128) - encoding:b100 | b0 | b00 | rs1[2:0] | b00000 | b01; - } - C.SRAI64 {//(RV32/64/128) - encoding:b100 | b0 | b01 | rs1[2:0] | b00000 | b01; + C.SRLI {//(RV64) + encoding:b100 | shamt[5:5] | b00 | rs1[2:0] | shamt[4:0] | b01; + args_disass: "{name(8+rs1)}, {shamt}"; + val rs1_idx[5] <= rs1+8; + X[rs1_idx] <= shrl(X[rs1_idx], shamt); } - C.SLLI64 {//(RV128 RV32/64) - encoding:b000 | b0 | rs1[4:0] | b00000 | b10; + C.SRAI {//(RV64) + encoding:b100 | shamt[5:5] | b01 | rs1[2:0] | shamt[4:0] | b01; + args_disass: "{name(8+rs1)}, {shamt}"; + val rs1_idx[5] <= rs1+8; + X[rs1_idx] <= shra(X[rs1_idx], shamt); + } + C.SLLI {//(RV64) + encoding:b000 | shamt[5:5] | rs1[4:0] | shamt[4:0] | b10; + args_disass: "{name(rs1)}, {shamt}"; + if(rs1 == 0) raise(0, 2); + X[rs1] <= shll(X[rs1], shamt); } C.LDSP {//(RV64/128 encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10; - args_disass: "x%rd$d, sp, 0x%imm$05x"; + args_disass:"{name(rd)}, {uimm}(sp)"; + val offs[XLEN] <= X[2] + uimm; + if(rd!=0) X[rd]<=sext(MEM[offs]{64}); } C.SDSP {//(RV64/128) encoding:b111 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10; + args_disass:"{name(rs2)}, {uimm}(sp)"; + val offs[XLEN] <= X[2] + uimm; + MEM[offs]{64} <= X[rs2]; } } } InsructionSet RV128IC extends RV64IC { - constants { - XLEN - } - address_spaces { - MEM[8] - } - registers { - [31:0] X[XLEN], - PC[XLEN](is_pc) - } + instructions{ + C.SRLI {//(RV128) + encoding:b100 | shamt[5:5] | b00 | rs1[2:0] | shamt[4:0] | b01; + args_disass: "{name(8+rs1)}, {shamt}"; + val rs1_idx[5] <= rs1+8; + X[rs1_idx] <= shrl(X[rs1_idx], shamt); + } + C.SRAI {//(RV128) + encoding:b100 | shamt[5:5] | b01 | rs1[2:0] | shamt[4:0] | b01; + args_disass: "{name(8+rs1)}, {shamt}"; + val rs1_idx[5] <= rs1+8; + X[rs1_idx] <= shra(X[rs1_idx], shamt); + } + C.SLLI {//(RV128) + encoding:b000 | shamt[5:5] | rs1[4:0] | shamt[4:0] | b10; + args_disass: "{name(rs1)}, {shamt}"; + if(rs1 == 0) raise(0, 2); + X[rs1] <= shll(X[rs1], shamt); + } C.LQ { //(RV128) encoding:b001 | uimm[5:4] | uimm[8:8] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00; } diff --git a/riscv/gen_input/RV32D.core_desc b/riscv/gen_input/RVD.core_desc similarity index 70% rename from riscv/gen_input/RV32D.core_desc rename to riscv/gen_input/RVD.core_desc index caefac5..08f50c0 100644 --- a/riscv/gen_input/RV32D.core_desc +++ b/riscv/gen_input/RVD.core_desc @@ -1,6 +1,6 @@ -import "RV32IBase.core_desc" +import "RISCVBase.core_desc" -InsructionSet RV32D extends RV32IBase{ +InsructionSet RV32D extends RISCVBase{ constants { FLEN, FFLAG_MASK := 0x1f } @@ -10,7 +10,7 @@ InsructionSet RV32D extends RV32IBase{ instructions{ FLD { encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000111; - args_disass:"f%rd$d, %imm%(x%rs1$d)"; + args_disass:"f{rd}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s + imm; val res[64] <= MEM[offs]{64}; if(FLEN==64) @@ -22,13 +22,13 @@ InsructionSet RV32D extends RV32IBase{ } FSD { encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100111; - args_disass:"f%rs2$d, %imm%(x%rs1$d)"; + args_disass:"f{rs2}, {imm}({name(rs1)})"; val offs[XLEN] <= X[rs1]'s + imm; MEM[offs]{64}<=F[rs2]{64}; } FMADD.D { encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; + args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}"; //F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f; val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(0, 64), choose(rm<7, rm{8}, FCSR{8})); if(FLEN==64) @@ -42,7 +42,7 @@ InsructionSet RV32D extends RV32IBase{ } FMSUB.D { encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; + args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}"; //F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f; val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8})); if(FLEN==64) @@ -56,7 +56,7 @@ InsructionSet RV32D extends RV32IBase{ } FNMADD.D { encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; + args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}"; //F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f; val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8})); if(FLEN==64) @@ -70,7 +70,7 @@ InsructionSet RV32D extends RV32IBase{ } FNMSUB.D { encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; + args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}"; //F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f; val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8})); if(FLEN==64) @@ -84,7 +84,7 @@ InsructionSet RV32D extends RV32IBase{ } FADD.D { encoding: b0000001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; + args_disass:"{name(rd)}, f{rs1}, f{rs2}"; // F[rd]f <= F[rs1]f + F[rs2]f; val res[64] <= fdispatch_fadd_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); if(FLEN==64) @@ -98,7 +98,7 @@ InsructionSet RV32D extends RV32IBase{ } FSUB.D { encoding: b0000101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; + args_disass:"{name(rd)}, f{rs1}, f{rs2}"; // F[rd]f <= F[rs1]f - F[rs2]f; val res[64] <= fdispatch_fsub_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); if(FLEN==64) @@ -112,7 +112,7 @@ InsructionSet RV32D extends RV32IBase{ } FMUL.D { encoding: b0001001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; + args_disass:"{name(rd)}, f{rs1}, f{rs2}"; // F[rd]f <= F[rs1]f * F[rs2]f; val res[64] <= fdispatch_fmul_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); if(FLEN==64) @@ -126,7 +126,7 @@ InsructionSet RV32D extends RV32IBase{ } FDIV.D { encoding: b0001101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; + args_disass:"{name(rd)}, f{rs1}, f{rs2}"; // F[rd]f <= F[rs1]f / F[rs2]f; val res[64] <= fdispatch_fdiv_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); if(FLEN==64) @@ -140,7 +140,7 @@ InsructionSet RV32D extends RV32IBase{ } FSQRT.D { encoding: b0101101 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d"; + args_disass:"{name(rd)}, f{rs1}"; //F[rd]f<=sqrt(F[rs1]f); val res[64] <= fdispatch_fsqrt_d(F[rs1]{64}, choose(rm<7, rm{8}, FCSR{8})); if(FLEN==64) @@ -154,8 +154,11 @@ InsructionSet RV32D extends RV32IBase{ } FSGNJ.D { encoding: b0010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; - args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; - val res[64] <= (F[rs1]{64} & 0x7fffffff) | (F[rs2]{64} & 0x80000000); + args_disass:"f{rd}, f{rs1}, f{rs2}"; + val ONE[64] <= 1; + val MSK1[64] <= ONE<<63; + val MSK2[64] <= MSK1-1; + val res[64] <= (F[rs1]{64} & MSK2) | (F[rs2]{64} & MSK1); if(FLEN==64) F[rd] <= res; else { // NaN boxing @@ -165,8 +168,11 @@ InsructionSet RV32D extends RV32IBase{ } FSGNJN.D { encoding: b0010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; - args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; - val res[64] <= (F[rs1]{64} & 0x7fffffff) | (~F[rs2]{64} & 0x80000000); + args_disass:"f{rd}, f{rs1}, f{rs2}"; + val ONE[64] <= 1; + val MSK1[64] <= ONE<<63; + val MSK2[64] <= MSK1-1; + val res[64] <= (F[rs1]{64} & MSK2) | (~F[rs2]{64} & MSK1); if(FLEN==64) F[rd] <= res; else { // NaN boxing @@ -176,8 +182,10 @@ InsructionSet RV32D extends RV32IBase{ } FSGNJX.D { encoding: b0010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; - args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; - val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & 0x80000000); + args_disass:"f{rd}, f{rs1}, f{rs2}"; + val ONE[64] <= 1; + val MSK1[64] <= ONE<<63; + val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & MSK1); if(FLEN==64) F[rd] <= res; else { // NaN boxing @@ -187,7 +195,7 @@ InsructionSet RV32D extends RV32IBase{ } FMIN.D { encoding: b0010101 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; - args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; + args_disass:"f{rd}, f{rs1}, f{rs2}"; //F[rd]f<= choose(F[rs1]fF[rs2]f, F[rs1]f, F[rs2]f); val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)); if(FLEN==64) @@ -215,7 +223,7 @@ InsructionSet RV32D extends RV32IBase{ } FCVT.S.D { encoding: b0100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"f%rd$d, f%rs1$d"; + args_disass:"f{rd}, f{rs1}"; val res[32] <= fdispatch_fconv_d2f(F[rs1], rm{8}); // NaN boxing val upper[FLEN] <= -1; @@ -223,7 +231,7 @@ InsructionSet RV32D extends RV32IBase{ } FCVT.D.S { encoding: b0100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"f%rd$d, f%rs1$d"; + args_disass:"f{rd}, f{rs1}"; val res[64] <= fdispatch_fconv_f2d(F[rs1]{32}, rm{8}); if(FLEN==64){ F[rd] <= res; @@ -234,48 +242,49 @@ InsructionSet RV32D extends RV32IBase{ } FEQ.D { encoding: b1010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; - X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32)); + args_disass:"{name(rd)}, f{rs1}, f{rs2}"; + X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32))); val flags[32] <= fdispatch_fget_flags(); FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FLT.D { encoding: b1010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; - X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32)); + args_disass:"{name(rd)}, f{rs1}, f{rs2}"; + X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32))); val flags[32] <= fdispatch_fget_flags(); FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FLE.D { encoding: b1010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; - X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)); + args_disass:"{name(rd)}, f{rs1}, f{rs2}"; + X[rd]<=zext(fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32))); val flags[32] <= fdispatch_fget_flags(); FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FCLASS.D { encoding: b1110001 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d"; + args_disass:"{name(rd)}, f{rs1}"; X[rd]<=fdispatch_fclass_d(F[rs1]{64}); } FCVT.W.D { encoding: b1100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d"; - X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(0, 32), rm{8}), XLEN); + args_disass:"{name(rd)}, f{rs1}"; + X[rd]<= sext(fdispatch_fcvt_64_32(F[rs1]{64}, zext(0, 32), rm{8}), XLEN); val flags[32] <= fdispatch_fget_flags(); FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FCVT.WU.D { encoding: b1100001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"x%rd$d, f%rs1$d"; - X[rd]<= zext(fdispatch_fcvt_d(F[rs1]{64}, zext(1, 32), rm{8}), XLEN); + args_disass:"{name(rd)}, f{rs1}"; + //FIXME: should be zext accodring to spec but needs to be sext according to tests + X[rd]<= sext(fdispatch_fcvt_64_32(F[rs1]{64}, zext(1, 32), rm{8}), XLEN); val flags[32] <= fdispatch_fget_flags(); FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FCVT.D.W { encoding: b1101001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"f%rd$d, x%rs1$d"; - val res[64] <= fdispatch_fcvt_d(sext(X[rs1],64), zext(2, 32), rm{8}); + args_disass:"f{rd}, {name(rs1)}"; + val res[64] <= fdispatch_fcvt_32_64(sext(X[rs1]{32},64), zext(2, 32), rm{8}); if(FLEN==64) F[rd] <= res; else { // NaN boxing @@ -285,8 +294,8 @@ InsructionSet RV32D extends RV32IBase{ } FCVT.D.WU { encoding: b1101001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - args_disass:"f%rd$d, x%rs1$d"; - val res[64] <=fdispatch_fcvt_d(zext(X[rs1],64), zext(3,32), rm{8}); + args_disass:"f{rd}, {name(rs1)}"; + val res[64] <=fdispatch_fcvt_32_64(zext(X[rs1]{32},64), zext(3,32), rm{8}); if(FLEN==64) F[rd] <= res; else { // NaN boxing @@ -295,4 +304,57 @@ InsructionSet RV32D extends RV32IBase{ } } } -} \ No newline at end of file +} +InsructionSet RV64D extends RV32D{ + + instructions{ + FCVT.L.D { + encoding: b1100001 | b00010 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"{name(rd)}, f{rs1}"; + X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(0, 32), rm{8}), XLEN); + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FCVT.LU.D { + encoding: b1100001 | b00011 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"{name(rd)}, f{rs1}"; + X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(1, 32), rm{8}), XLEN); + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FCVT.D.L { + encoding: b1101001 | b00010 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"f{rd}, {name(rs1)}"; + val res[64] <= fdispatch_fcvt_d(sext(X[rs1],64), zext(2, 32), rm{8}); + if(FLEN==64) + F[rd] <= res; + else { // NaN boxing + val upper[FLEN] <= -1; + F[rd] <= (upper<<64) | res; + } + } + FCVT.D.LU { + encoding: b1101001 | b00011 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"f{rd}, {name(rs1)}"; + val res[64] <=fdispatch_fcvt_d(zext(X[rs1],64), zext(3,32), rm{8}); + if(FLEN==64) + F[rd] <= res; + else { // NaN boxing + val upper[FLEN] <= -1; + F[rd] <= (upper<<64) | res; + } + } + FMV.X.D { + encoding: b1110001 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"{name(rd)}, f{rs1}"; + X[rd]<=sext(F[rs1]); + } + FMV.D.X { + encoding: b1111001 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"f{rd}, {name(rs1)}"; + F[rd] <= zext(X[rs1]); + } + } +} + + \ No newline at end of file diff --git a/riscv/gen_input/RVF.core_desc b/riscv/gen_input/RVF.core_desc new file mode 100644 index 0000000..5134b87 --- /dev/null +++ b/riscv/gen_input/RVF.core_desc @@ -0,0 +1,400 @@ +import "RV32I.core_desc" + +InsructionSet RV32F extends RV32I{ + constants { + FLEN, FFLAG_MASK := 0x1f + } + registers { + [31:0] F[FLEN], FCSR[32] + } + instructions{ + FLW { + encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000111; + args_disass:"f{rd}, {imm}(x{rs1})"; + val offs[XLEN] <= X[rs1]'s + imm; + val res[32] <= MEM[offs]{32}; + if(FLEN==32) + F[rd] <= res; + else { // NaN boxing + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + } + FSW { + encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100111; + args_disass:"f{rs2}, {imm}(x{rs1})"; + val offs[XLEN] <= X[rs1]'s + imm; + MEM[offs]{32}<=F[rs2]{32}; + } + FMADD.S { + encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011; + args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}"; + //F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f; + if(FLEN==32) + F[rd] <= fdispatch_fmadd_s(F[rs1], F[rs2], F[rs3], zext(0, 32), choose(rm<7, rm{8}, FCSR{8})); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val frs3[32] <= fdispatch_unbox_s(F[rs3]); + val res[32] <= fdispatch_fmadd_s(frs1, frs2, frs3, zext(0, 32), choose(rm<7, rm{8}, FCSR{8})); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FMSUB.S { + encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111; + args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}"; + //F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f; + if(FLEN==32) + F[rd] <= fdispatch_fmadd_s(F[rs1], F[rs2], F[rs3], zext(1, 32), choose(rm<7, rm{8}, FCSR{8})); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val frs3[32] <= fdispatch_unbox_s(F[rs3]); + val res[32] <= fdispatch_fmadd_s(frs1, frs2, frs3, zext(1, 32), choose(rm<7, rm{8}, FCSR{8})); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FNMADD.S { + encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111; + args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}"; + //F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f; + if(FLEN==32) + F[rd] <= fdispatch_fmadd_s(F[rs1], F[rs2], F[rs3], zext(2, 32), choose(rm<7, rm{8}, FCSR{8})); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val frs3[32] <= fdispatch_unbox_s(F[rs3]); + val res[32] <= fdispatch_fmadd_s(frs1, frs2, frs3, zext(2, 32), choose(rm<7, rm{8}, FCSR{8})); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FNMSUB.S { + encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011; + args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}"; + //F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f; + if(FLEN==32) + F[rd] <= fdispatch_fmadd_s(F[rs1], F[rs2], F[rs3], zext(3, 32), choose(rm<7, rm{8}, FCSR{8})); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val frs3[32] <= fdispatch_unbox_s(F[rs3]); + val res[32] <= fdispatch_fmadd_s(frs1, frs2, frs3, zext(3, 32), choose(rm<7, rm{8}, FCSR{8})); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FADD.S { + encoding: b0000000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"f{rd}, f{rs1}, f{rs2}"; + // F[rd]f <= F[rs1]f + F[rs2]f; + if(FLEN==32) + F[rd] <= fdispatch_fadd_s(F[rs1], F[rs2], choose(rm<7, rm{8}, FCSR{8})); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val res[32] <= fdispatch_fadd_s(frs1, frs2, choose(rm<7, rm{8}, FCSR{8})); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FSUB.S { + encoding: b0000100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"f{rd}, f{rs1}, f{rs2}"; + // F[rd]f <= F[rs1]f - F[rs2]f; + if(FLEN==32) + F[rd] <= fdispatch_fsub_s(F[rs1], F[rs2], choose(rm<7, rm{8}, FCSR{8})); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val res[32] <= fdispatch_fsub_s(frs1, frs2, choose(rm<7, rm{8}, FCSR{8})); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FMUL.S { + encoding: b0001000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"f{rd}, f{rs1}, f{rs2}"; + // F[rd]f <= F[rs1]f * F[rs2]f; + if(FLEN==32) + F[rd] <= fdispatch_fmul_s(F[rs1], F[rs2], choose(rm<7, rm{8}, FCSR{8})); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val res[32] <= fdispatch_fmul_s(frs1, frs2, choose(rm<7, rm{8}, FCSR{8})); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FDIV.S { + encoding: b0001100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"f{rd}, f{rs1}, f{rs2}"; + // F[rd]f <= F[rs1]f / F[rs2]f; + if(FLEN==32) + F[rd] <= fdispatch_fdiv_s(F[rs1], F[rs2], choose(rm<7, rm{8}, FCSR{8})); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val res[32] <= fdispatch_fdiv_s(frs1, frs2, choose(rm<7, rm{8}, FCSR{8})); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FSQRT.S { + encoding: b0101100 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"f{rd}, f{rs1}"; + //F[rd]f<=sqrt(F[rs1]f); + if(FLEN==32) + F[rd] <= fdispatch_fsqrt_s(F[rs1], choose(rm<7, rm{8}, FCSR{8})); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val res[32] <= fdispatch_fsqrt_s(frs1, choose(rm<7, rm{8}, FCSR{8})); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FSGNJ.S { + encoding: b0010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"f{rd}, f{rs1}, f{rs2}"; + if(FLEN==32) + F[rd] <= (F[rs1] & 0x7fffffff) | (F[rs2] & 0x80000000); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val res[32] <= (frs1 & 0x7fffffff) | (frs2 & 0x80000000); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + } + FSGNJN.S { + encoding: b0010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; + args_disass:"f{rd}, f{rs1}, f{rs2}"; + if(FLEN==32) + F[rd] <= (F[rs1] & 0x7fffffff) | (~F[rs2] & 0x80000000); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val res[32] <= (frs1 & 0x7fffffff) | (~frs2 & 0x80000000); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + } + FSGNJX.S { + encoding: b0010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; + args_disass:"f{rd}, f{rs1}, f{rs2}"; + if(FLEN==32) + F[rd] <= F[rs1] ^ (F[rs2] & 0x80000000); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val res[32] <= frs1 ^ (frs2 & 0x80000000); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + } + FMIN.S { + encoding: b0010100 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"f{rd}, f{rs1}, f{rs2}"; + //F[rd]f<= choose(F[rs1]fF[rs2]f, F[rs1]f, F[rs2]f); + if(FLEN==32) + F[rd] <= fdispatch_fsel_s(F[rs1], F[rs2], zext(1, 32)); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + val res[32] <= fdispatch_fsel_s(frs1, frs2, zext(1, 32)); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FCVT.W.S { + encoding: b1100000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"{name(rd)}, f{rs1}"; + if(FLEN==32) + X[rd] <= sext(fdispatch_fcvt_s(F[rs1], zext(0, 32), rm{8}), XLEN); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + X[rd]<= sext(fdispatch_fcvt_s(frs1, zext(0, 32), rm{8}), XLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FCVT.WU.S { + encoding: b1100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"{name(rd)}, f{rs1}"; + //FIXME: according to the spec it should be zero-extended not sign extended + if(FLEN==32) + X[rd]<= sext(fdispatch_fcvt_s(F[rs1], zext(1, 32), rm{8}), XLEN); + else { // NaN boxing + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + X[rd]<= sext(fdispatch_fcvt_s(frs1, zext(1, 32), rm{8}), XLEN); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FEQ.S { + encoding: b1010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; + args_disass:"{name(rd)}, f{rs1}, f{rs2}"; + if(FLEN==32) + X[rd]<=zext(fdispatch_fcmp_s(F[rs1], F[rs2], zext(0, 32))); + else { + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + X[rd]<=zext(fdispatch_fcmp_s(frs1, frs2, zext(0, 32))); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FLT.S { + encoding: b1010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; + args_disass:"{name(rd)}, f{rs1}, f{rs2}"; + if(FLEN==32) + X[rd]<=zext(fdispatch_fcmp_s(F[rs1], F[rs2], zext(2, 32))); + else { + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + X[rd]<=zext(fdispatch_fcmp_s(frs1, frs2, zext(2, 32))); + } + X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(2, 32)); + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FLE.S { + encoding: b1010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"{name(rd)}, f{rs1}, f{rs2}"; + if(FLEN==32) + X[rd]<=zext(fdispatch_fcmp_s(F[rs1], F[rs2], zext(1, 32))); + else { + val frs1[32] <= fdispatch_unbox_s(F[rs1]); + val frs2[32] <= fdispatch_unbox_s(F[rs2]); + X[rd]<=zext(fdispatch_fcmp_s(frs1, frs2, zext(1, 32))); + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FCLASS.S { + encoding: b1110000 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011; + args_disass:"{name(rd)}, f{rs1}"; + X[rd]<=fdispatch_fclass_s(fdispatch_unbox_s(F[rs1])); + } + FCVT.S.W { + encoding: b1101000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"f{rd}, {name(rs1)}"; + if(FLEN==32) + F[rd] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8}); + else { // NaN boxing + val res[32] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8}); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + } + FCVT.S.WU { + encoding: b1101000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"f{rd}, {name(rs1)}"; + if(FLEN==32) + F[rd] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8}); + else { // NaN boxing + val res[32] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8}); + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + } + FMV.X.W { + encoding: b1110000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"{name(rd)}, f{rs1}"; + X[rd]<=sext(F[rs1]{32}); + } + FMV.W.X { + encoding: b1111000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"f{rd}, {name(rs1)}"; + if(FLEN==32) + F[rd] <= X[rs1]{32}; + else { // NaN boxing + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(X[rs1]{32}, FLEN); + } + } + } +} + +InsructionSet RV64F extends RV32F{ + + instructions{ + FCVT.L.S { // fp to 64bit signed integer + encoding: b1100000 | b00010 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"x{rd}, f{rs1}"; + val res[64] <= fdispatch_fcvt_32_64(fdispatch_unbox_s(F[rs1]), zext(0, 32), rm{8}); + X[rd]<= sext(res); + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FCVT.LU.S { // fp to 64bit unsigned integer + encoding: b1100000 | b00011 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"x{rd}, f{rs1}"; + val res[64] <= fdispatch_fcvt_32_64(fdispatch_unbox_s(F[rs1]), zext(1, 32), rm{8}); + X[rd]<= zext(res); + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + 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)); + if(FLEN==32) + F[rd] <= res; + else { // NaN boxing + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + } + 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)); + if(FLEN==32) + F[rd] <= res; + else { // NaN boxing + val upper[FLEN] <= -1; + F[rd] <= (upper<<32) | zext(res, FLEN); + } + } + } +} + \ No newline at end of file diff --git a/riscv/gen_input/RVM.core_desc b/riscv/gen_input/RVM.core_desc new file mode 100644 index 0000000..49edd18 --- /dev/null +++ b/riscv/gen_input/RVM.core_desc @@ -0,0 +1,160 @@ +import "RISCVBase.core_desc" + +InsructionSet RV32M extends RISCVBase { + constants { + MAXLEN:=128 + } + instructions{ + MUL{ + encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; + if(rd != 0){ + val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN); + X[rd]<= zext(res , XLEN); + } + } + MULH { + encoding: b0000001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; + if(rd != 0){ + val res[MAXLEN] <= sext(X[rs1], MAXLEN) * sext(X[rs2], MAXLEN); + X[rd]<= zext(res >> XLEN, XLEN); + } + } + MULHSU { + encoding: b0000001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; + if(rd != 0){ + val res[MAXLEN] <= sext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN); + X[rd]<= zext(res >> XLEN, XLEN); + } + } + MULHU { + encoding: b0000001 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; + if(rd != 0){ + val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN); + X[rd]<= zext(res >> XLEN, XLEN); + } + } + DIV { + encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; + if(rd != 0){ + if(X[rs2]!=0){ + val M1[XLEN] <= -1; + val XLM1[8] <= XLEN-1; + val ONE[XLEN] <= 1; + val MMIN[XLEN] <= ONE< 32) 64 else if(size > 16) 32 else if(size > 8) 16 else 8 } +def getOriginalName(reg){ + if( reg.original instanceof RegisterFile) { + if( reg.index != null ) { + return reg.original.name+generator.generateHostCode(reg.index) + } else { + return reg.original.name + } + } else if(reg.original instanceof Register){ + return reg.original.name + } +} +def getRegisterNames(){ + def regNames = [] + allRegs.each { reg -> + if( reg instanceof RegisterFile) { + (reg.range.right..reg.range.left).each{ + regNames+=reg.name.toLowerCase()+it + } + } else if(reg instanceof Register){ + regNames+=reg.name.toLowerCase() + } + } + return regNames +} +def getRegisterAliasNames(){ + def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]} + return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg -> + if( reg instanceof RegisterFile) { + return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() } + } else if(reg instanceof Register){ + regMap[reg.name]?:reg.name.toLowerCase() + } + }.flatten() +} %> #ifndef _${coreDef.name.toUpperCase()}_H_ #define _${coreDef.name.toUpperCase()}_H_ +#include +#include #include #include -#include -#include namespace iss { namespace arch { struct ${coreDef.name.toLowerCase()}; -template<> -struct traits<${coreDef.name.toLowerCase()}> { +template <> struct traits<${coreDef.name.toLowerCase()}> { constexpr static char const* const core_type = "${coreDef.name}"; + static constexpr std::array reg_names{ + {"${getRegisterNames().join("\", \"")}"}}; + + static constexpr std::array reg_aliases{ + {"${getRegisterAliasNames().join("\", \"")}"}}; + enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}}; constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0}; @@ -65,7 +106,7 @@ struct traits<${coreDef.name.toLowerCase()}> { ${reg.name}${it},<% } } else if(reg instanceof Register){ %> - ${reg.name},<% + ${reg.name},<% } }%> NUM_REGS, @@ -74,7 +115,12 @@ struct traits<${coreDef.name.toLowerCase()}> { PENDING_TRAP, MACHINE_STATE, LAST_BRANCH, - ICOUNT + ICOUNT<% + allRegs.each { reg -> + if(reg instanceof RegisterAlias){ def aliasname=getOriginalName(reg)%>, + ${reg.name} = ${aliasname}<% + } + }%> }; using reg_t = uint${regDataWidth}_t; @@ -87,21 +133,17 @@ struct traits<${coreDef.name.toLowerCase()}> { using phys_addr_t = iss::typed_addr_t; - constexpr static unsigned reg_bit_width(unsigned r) { - constexpr std::array ${coreDef.name}_reg_size{{${regSizes.join(",")}}}; - return ${coreDef.name}_reg_size[r]; - } + static constexpr std::array reg_bit_widths{ + {${regSizes.join(",")}}}; - constexpr static unsigned reg_byte_offset(unsigned r) { - constexpr std::array ${coreDef.name}_reg_byte_offset{{${regOffsets.join(",")}}}; - return ${coreDef.name}_reg_byte_offset[r]; - } + static constexpr std::array reg_byte_offsets{ + {${regOffsets.join(",")}}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); - enum sreg_flag_e {FLAGS}; + enum sreg_flag_e { FLAGS }; - enum mem_type_e {${allSpaces.collect{s -> s.name}.join(', ')}}; + enum mem_type_e { ${allSpaces.collect{s -> s.name}.join(', ')} }; }; struct ${coreDef.name.toLowerCase()}: public arch_if { @@ -126,12 +168,13 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { /// deprecated void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; - uint64_t get_icount() { return reg.icount;} + inline uint64_t get_icount() { return reg.icount; } + + inline bool should_stop() { 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){ + if (addr.space != traits<${coreDef.name.toLowerCase()}>::MEM || addr.type == iss::address_type::PHYSICAL || + addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask); } else return virt2phys(addr); @@ -141,8 +184,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } - inline - uint32_t get_last_branch(){return reg.last_branch;} + inline uint32_t get_last_branch() { return reg.last_branch; } protected: struct ${coreDef.name}_regs {<% diff --git a/riscv/gen_input/templates/src-CORENAME.cpp.gtl b/riscv/gen_input/templates/src-CORENAME.cpp.gtl index cafe82c..ee9641b 100644 --- a/riscv/gen_input/templates/src-CORENAME.cpp.gtl +++ b/riscv/gen_input/templates/src-CORENAME.cpp.gtl @@ -1,35 +1,73 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017,2018 MINRES Technologies GmbH -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -//////////////////////////////////////////////////////////////////////////////// - +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + <% +import com.minres.coredsl.coreDsl.Register +import com.minres.coredsl.coreDsl.RegisterFile +import com.minres.coredsl.coreDsl.RegisterAlias +def getOriginalName(reg){ + if( reg.original instanceof RegisterFile) { + if( reg.index != null ) { + return reg.original.name+generator.generateHostCode(reg.index) + } else { + return reg.original.name + } + } else if(reg.original instanceof Register){ + return reg.original.name + } +} +def getRegisterNames(){ + def regNames = [] + allRegs.each { reg -> + if( reg instanceof RegisterFile) { + (reg.range.right..reg.range.left).each{ + regNames+=reg.name.toLowerCase()+it + } + } else if(reg instanceof Register){ + regNames+=reg.name.toLowerCase() + } + } + return regNames +} +def getRegisterAliasNames(){ + def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]} + return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg -> + if( reg instanceof RegisterFile) { + return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() } + } else if(reg instanceof Register){ + regMap[reg.name]?:reg.name.toLowerCase() + } + }.flatten() +} +%> #include "util/ities.h" #include @@ -43,18 +81,22 @@ extern "C" { #ifdef __cplusplus } #endif -#include #include #include +#include using namespace iss::arch; +constexpr std::array iss::arch::traits::reg_names; +constexpr std::array iss::arch::traits::reg_aliases; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; + ${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { - reg.icount=0; + reg.icount = 0; } -${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}(){ -} +${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default; void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits<${coreDef.name.toLowerCase()}>::reg_t),0)); @@ -62,10 +104,11 @@ void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { reg.NEXT_PC=reg.PC; reg.trap_state=0; reg.machine_state=0x0; + reg.icount=0; } -uint8_t* ${coreDef.name.toLowerCase()}::get_regs_base_ptr(){ - return reinterpret_cast(®); +uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { + return reinterpret_cast(®); } ${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) { diff --git a/riscv/gen_input/templates/vm-vm_CORENAME.cpp.gtl b/riscv/gen_input/templates/vm-vm_CORENAME.cpp.gtl index b84bae6..709da48 100644 --- a/riscv/gen_input/templates/vm-vm_CORENAME.cpp.gtl +++ b/riscv/gen_input/templates/vm-vm_CORENAME.cpp.gtl @@ -1,56 +1,52 @@ -//////////////////////////////////////////////////////////////////////////////// -// 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 -// -// -//////////////////////////////////////////////////////////////////////////////// +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ #include #include #include #include #include -#include +#include #include -#include +#include -#include #include +#include namespace iss { namespace vm { -namespace fp_impl{ -void add_fp_functions_2_module(llvm::Module *, unsigned); +namespace fp_impl { +void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); } } @@ -58,10 +54,11 @@ namespace ${coreDef.name.toLowerCase()} { using namespace iss::arch; using namespace llvm; using namespace iss::debugger; +using namespace iss::vm::llvm; -template class vm_impl : public vm::vm_base { +template class vm_impl : public vm_base { public: - using super = typename vm::vm_base; + using super = typename iss::vm::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; @@ -73,33 +70,34 @@ public: void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } - target_adapter_if *accquire_target_adapter(server_if *srv) { + target_adapter_if *accquire_target_adapter(server_if *srv) override { debugger_if::dbg_enabled = true; - if (vm::vm_base::tgt_adapter == nullptr) - vm::vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm::vm_base::tgt_adapter; + if (vm_base::tgt_adapter == nullptr) + vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return vm_base::tgt_adapter; } protected: - using vm::vm_base::get_reg_ptr; + using vm_base::get_reg_ptr; - template inline llvm::ConstantInt *size(T type) { - return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); + 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(llvm::Module* m) override { + void setup_module(Module* m) override { super::setup_module(m); - vm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE); + iss::vm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); } - inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, unsigned size) { + inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); } - std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, - llvm::BasicBlock *) override; + std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override; - void gen_leave_behavior(llvm::BasicBlock *leave_blk) override; + void gen_leave_behavior(BasicBlock *leave_blk) override; void gen_raise_trap(uint16_t trap_id, uint16_t cause); @@ -107,17 +105,17 @@ protected: void gen_wait(unsigned type); - void gen_trap_behavior(llvm::BasicBlock *) override; + void gen_trap_behavior(BasicBlock *) override; - void gen_trap_check(llvm::BasicBlock *bb); + void gen_trap_check(BasicBlock *bb); - inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) { + 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) { - llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); + 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); } @@ -128,17 +126,17 @@ protected: enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; using this_class = vm_impl; - using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, - code_word_t instr, - llvm::BasicBlock *bb); + using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, + code_word_t instr, + BasicBlock *bb); std::array lut; std::array lut_00, lut_01, lut_10; std::array lut_11; - std::array qlut; + std::array 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) { @@ -196,15 +194,14 @@ private: /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> /* instruction ${idx}: ${instr.name} */ - std::tuple __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){<%instr.code.eachLine{%> + std::tuple __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){<%instr.code.eachLine{%> ${it}<%}%> } <%}%> /**************************************************************************** * end opcode definitions ****************************************************************************/ - std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, - llvm::BasicBlock *bb) { + std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { this->gen_sync(iss::PRE_SYNC, instr_descr.size()); this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), get_reg_ptr(traits::PC), true); @@ -216,7 +213,7 @@ private: this->gen_raise_trap(0, 2); // illegal instruction trap this->gen_sync(iss::POST_SYNC, instr_descr.size()); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } }; @@ -229,7 +226,7 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm::vm_base(core, core_id, cluster_id) { +: vm_base(core, core_id, cluster_id) { qlut[0] = lut_00.data(); qlut[1] = lut_01.data(); qlut[2] = lut_10.data(); @@ -241,27 +238,24 @@ 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, llvm::BasicBlock *this_block) { +std::tuple +vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { // we fetch at max 4 byte, alignment is 2 + enum {TRAP_ID=1<<16}; code_word_t insn = 0; const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); - try { - uint8_t *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(1, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(1, pc.val); + auto *const data = (uint8_t *)&insn; + paddr = this->core.v2p(pc); + if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary + auto res = this->core.read(paddr, 2, data); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if ((insn & 0x3) == 0x3) { // this is a 32bit instruction + res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); } - } catch (trap_access &ta) { - throw trap_access(ta.id, pc.val); + } else { + auto res = this->core.read(paddr, 4, data); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); } if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack @@ -274,7 +268,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, return (this->*f)(pc, insn, this_block); } -template void vm_impl::gen_leave_behavior(llvm::BasicBlock *leave_blk) { +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)); } @@ -286,9 +280,7 @@ template void vm_impl::gen_raise_trap(uint16_t trap_id, ui } template void vm_impl::gen_leave_trap(unsigned lvl) { - std::vector args{ - this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, 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); @@ -296,30 +288,27 @@ template void vm_impl::gen_leave_trap(unsigned lvl) { } template void vm_impl::gen_wait(unsigned type) { - std::vector args{ - this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, 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(llvm::BasicBlock *trap_blk) { +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.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(llvm::BasicBlock *bb) { +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, - llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), + ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), bb, this->trap_blk, 1); } @@ -327,10 +316,9 @@ template inline void vm_impl::gen_trap_check(llvm::BasicBl template <> std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { - std::unique_ptr<${coreDef.name.toLowerCase()}::vm_impl> ret = - std::make_unique<${coreDef.name.toLowerCase()}::vm_impl>(*core, dump); - if (port != 0) debugger::server::run_server(ret.get(), port); - return ret; + auto ret = new ${coreDef.name.toLowerCase()}::vm_impl(*core, dump); + if (port != 0) debugger::server::run_server(ret, port); + return std::unique_ptr(ret); } } // namespace iss diff --git a/riscv/gen_input/templates/vm_riscv.in.cpp b/riscv/gen_input/templates/vm_riscv.in.cpp deleted file mode 100644 index d86bf14..0000000 --- a/riscv/gen_input/templates/vm_riscv.in.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -namespace iss { -namespace CORE_DEF_NAME { -using namespace iss::arch; -using namespace llvm; -using namespace iss::debugger; - -template class vm_impl : public vm::vm_base { -public: - using super = typename vm::vm_base; - using virt_addr_t = typename super::virt_addr_t; - using phys_addr_t = typename super::phys_addr_t; - using code_word_t = typename super::code_word_t; - using addr_t = typename super::addr_t; - - vm_impl(); - - vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); - - void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } - - target_adapter_if *accquire_target_adapter(server_if *srv) { - debugger_if::dbg_enabled = true; - if (vm::vm_base::tgt_adapter == nullptr) - vm::vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm::vm_base::tgt_adapter; - } - -protected: - using vm::vm_base::get_reg_ptr; - - template inline llvm::ConstantInt *size(T type) { - return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); - } - - inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, - unsigned size) const { - return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); - } - - std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, - llvm::BasicBlock *) override; - - void gen_leave_behavior(llvm::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(llvm::BasicBlock *) override; - - void gen_trap_check(llvm::BasicBlock *bb); - - inline llvm::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) { - llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); - this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); - } - - // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; - - using this_class = vm_impl; - using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, - code_word_t instr, - llvm::BasicBlock *bb); - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } - -private: - /**************************************************************************** - * start opcode definitions - ****************************************************************************/ - struct InstructionDesriptor { - size_t length; - uint32_t value; - uint32_t mask; - compile_func op; - }; - - /* «start generated code» */ - std::array instr_descr = {{}}; - /* «end generated code» */ - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, - llvm::BasicBlock *bb) { - this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); - this->builder.CreateStore( - this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits::ICOUNT), true), - this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - this->gen_raise_trap(0, 2); // illegal instruction trap - this->gen_sync(iss::POST_SYNC, instr_descr.size()); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } -}; - -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; -} - -template vm_impl::vm_impl() { this(new ARCH()); } - -template -vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm::vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); - } -} - -template -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, llvm::BasicBlock *this_block) { - // we fetch at max 4 byte, alignment is 2 - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - try { - uint8_t *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(1, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(1, pc.val); - } - } catch (trap_access &ta) { - throw trap_access(ta.id, pc.val); - } - if (insn == 0x0000006f || (insn & 0xffff) == 0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - typename vm_impl::processing_pc_entry addr(*this, pc, paddr); - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, this_block); -} - -template void vm_impl::gen_leave_behavior(llvm::BasicBlock *leave_blk) { - this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); -} - -template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { - auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); - this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); -} - -template void vm_impl::gen_leave_trap(unsigned lvl) { - std::vector args{ - this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::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); -} - -template void vm_impl::gen_wait(unsigned type) { - std::vector args{ - this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)), - }; - this->builder.CreateCall(this->mod->getFunction("wait"), args); -} - -template void vm_impl::gen_trap_behavior(llvm::BasicBlock *trap_blk) { - this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); - 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(llvm::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, - llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, this->trap_blk, 1); -} - -} // namespace CORE_DEF_NAME - -template <> -std::unique_ptr create(arch::CORE_DEF_NAME *core, unsigned short port, bool dump) { - std::unique_ptr> ret = - std::make_unique>(*core, dump); - if (port != 0) debugger::server::run_server(ret.get(), port); - return ret; -} - -} // namespace iss diff --git a/riscv/incl/iss/arch/riscv_hart_msu_vp.h b/riscv/incl/iss/arch/riscv_hart_msu_vp.h index a8a9bab..d6fbc76 100644 --- a/riscv/incl/iss/arch/riscv_hart_msu_vp.h +++ b/riscv/incl/iss/arch/riscv_hart_msu_vp.h @@ -40,6 +40,7 @@ #include "iss/instrumentation_if.h" #include "iss/log_categories.h" #include "iss/vm_if.h" +#include #include #include #include @@ -478,10 +479,8 @@ public: void wait_until(uint64_t flags) override; void disass_output(uint64_t pc, const std::string instr) override { - std::stringstream s; - s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0') - << std::setw(sizeof(reg_t) * 2) << (reg_t)state.mstatus << std::dec << ";c:" << this->reg.icount << "]"; - CLOG(INFO, disass) << "0x" << std::setw(16) << std::setfill('0') << std::hex << pc << "\t\t" << instr << "\t" << s.str(); + CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", + pc, instr, lvl[this->reg.machine_state], (reg_t)state.mstatus, this->reg.icount); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } diff --git a/riscv/incl/iss/arch/rv32gc.h b/riscv/incl/iss/arch/rv32gc.h index da24040..649a4c5 100644 --- a/riscv/incl/iss/arch/rv32gc.h +++ b/riscv/incl/iss/arch/rv32gc.h @@ -1,53 +1,59 @@ -//////////////////////////////////////////////////////////////////////////////// -// 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. -// -//////////////////////////////////////////////////////////////////////////////// +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + #ifndef _RV32GC_H_ #define _RV32GC_H_ +#include +#include #include #include -#include -#include namespace iss { namespace arch { struct rv32gc; -template<> -struct traits { +template <> struct traits { constexpr static char const* const core_type = "RV32GC"; + static constexpr std::array reg_names{ + {"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}}; + + static constexpr std::array reg_aliases{ + {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}}; + enum constants {XLEN=32, FLEN=64, PCLEN=32, MISA_VAL=0b1000000000101000001000100101101, PGSIZE=0x1000, PGMASK=0xfff}; constexpr static unsigned FP_REGS_SIZE = 64; @@ -125,7 +131,39 @@ struct traits { PENDING_TRAP, MACHINE_STATE, LAST_BRANCH, - ICOUNT + ICOUNT, + ZERO = X0, + RA = X1, + SP = X2, + GP = X3, + TP = X4, + T0 = X5, + T1 = X6, + T2 = X7, + S0 = X8, + S1 = X9, + A0 = X10, + A1 = X11, + A2 = X12, + A3 = X13, + A4 = X14, + A5 = X15, + A6 = X16, + A7 = X17, + S2 = X18, + S3 = X19, + S4 = X20, + S5 = X21, + S6 = X22, + S7 = X23, + S8 = X24, + S9 = X25, + S10 = X26, + S11 = X27, + T3 = X28, + T4 = X29, + T5 = X30, + T6 = X31 }; using reg_t = uint32_t; @@ -138,21 +176,17 @@ struct traits { using phys_addr_t = iss::typed_addr_t; - constexpr static unsigned reg_bit_width(unsigned r) { - constexpr std::array RV32GC_reg_size{{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,32,32,64}}; - return RV32GC_reg_size[r]; - } + static constexpr std::array reg_bit_widths{ + {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,32,32,64}}; - constexpr static unsigned reg_byte_offset(unsigned r) { - constexpr std::array RV32GC_reg_byte_offset{{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,412,416,424}}; - return RV32GC_reg_byte_offset[r]; - } + static constexpr std::array reg_byte_offsets{ + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,412,416,424}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); - enum sreg_flag_e {FLAGS}; + enum sreg_flag_e { FLAGS }; - enum mem_type_e {MEM, CSR, FENCE, RES}; + enum mem_type_e { MEM, CSR, FENCE, RES }; }; struct rv32gc: public arch_if { @@ -177,14 +211,13 @@ struct rv32gc: public arch_if { /// deprecated void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; - uint64_t get_icount() { return reg.icount;} + inline uint64_t get_icount() { return reg.icount; } inline bool should_stop() { 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){ + if (addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || + addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); } else return virt2phys(addr); @@ -194,8 +227,7 @@ struct rv32gc: public arch_if { virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } - inline - uint32_t get_last_branch(){return reg.last_branch;} + inline uint32_t get_last_branch() { return reg.last_branch; } protected: struct RV32GC_regs { diff --git a/riscv/incl/iss/arch/rv32imac.h b/riscv/incl/iss/arch/rv32imac.h index 74a0183..d187084 100644 --- a/riscv/incl/iss/arch/rv32imac.h +++ b/riscv/incl/iss/arch/rv32imac.h @@ -30,6 +30,7 @@ * *******************************************************************************/ + #ifndef _RV32IMAC_H_ #define _RV32IMAC_H_ @@ -45,15 +46,15 @@ struct rv32imac; template <> struct traits { - constexpr static char const *const core_type = "RV32IMAC"; + constexpr static char const* const core_type = "RV32IMAC"; + + static constexpr std::array reg_names{ + {"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc"}}; + + static constexpr std::array reg_aliases{ + {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}}; - enum constants { - XLEN = 32, - PCLEN = 32, - MISA_VAL = 0b1000000000101000001000100000101, - PGSIZE = 0x1000, - PGMASK = 0xfff - }; + enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000101000001000100000101, PGSIZE=0x1000, PGMASK=0xfff}; constexpr static unsigned FP_REGS_SIZE = 0; @@ -92,35 +93,61 @@ template <> struct traits { X31, PC, NUM_REGS, - NEXT_PC = NUM_REGS, + NEXT_PC=NUM_REGS, TRAP_STATE, PENDING_TRAP, MACHINE_STATE, LAST_BRANCH, - ICOUNT + ICOUNT, + ZERO = X0, + RA = X1, + SP = X2, + GP = X3, + TP = X4, + T0 = X5, + T1 = X6, + T2 = X7, + S0 = X8, + S1 = X9, + A0 = X10, + A1 = X11, + A2 = X12, + A3 = X13, + A4 = X14, + A5 = X15, + A6 = X16, + A7 = X17, + S2 = X18, + S3 = X19, + S4 = X20, + S5 = X21, + S6 = X22, + S7 = X23, + S8 = X24, + S9 = X25, + S10 = X26, + S11 = X27, + T3 = X28, + T4 = X29, + T5 = X30, + T6 = X31 }; using reg_t = uint32_t; using addr_t = uint32_t; - using code_word_t = uint32_t; // TODO: check removal + using code_word_t = uint32_t; //TODO: check removal using virt_addr_t = iss::typed_addr_t; using phys_addr_t = iss::typed_addr_t; - static constexpr std::array RV32IMAC_reg_size{ - {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 64}}; + static constexpr std::array reg_bit_widths{ + {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64}}; - constexpr static unsigned reg_bit_width(unsigned r) { return RV32IMAC_reg_size[r]; } - - static constexpr std::array RV32IMAC_reg_byte_offset{ - {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, - 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 160}}; - - constexpr static unsigned reg_byte_offset(unsigned r) { return RV32IMAC_reg_byte_offset[r]; } + static constexpr std::array reg_byte_offsets{ + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,160}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); @@ -129,41 +156,41 @@ template <> struct traits { enum mem_type_e { MEM, CSR, FENCE, RES }; }; -struct rv32imac : public arch_if { +struct rv32imac: public arch_if { using virt_addr_t = typename traits::virt_addr_t; using phys_addr_t = typename traits::phys_addr_t; - using reg_t = typename traits::reg_t; + using reg_t = typename traits::reg_t; using addr_t = typename traits::addr_t; rv32imac(); ~rv32imac(); - void reset(uint64_t address = 0) override; + void reset(uint64_t address=0) override; - uint8_t *get_regs_base_ptr() override; + uint8_t* get_regs_base_ptr() override; /// deprecated - void get_reg(short idx, std::vector &value) override {} - void set_reg(short idx, const std::vector &value) override {} + void get_reg(short idx, std::vector& value) override {} + void set_reg(short idx, const std::vector& value) override {} /// deprecated - bool get_flag(int flag) override { return false; } - void set_flag(int, bool value) override{}; + bool get_flag(int flag) override {return false;} + void set_flag(int, bool value) override {}; /// deprecated - void update_flags(operations op, uint64_t opr1, uint64_t opr2) override{}; + void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; inline uint64_t get_icount() { return reg.icount; } inline bool should_stop() { return interrupt_sim; } - inline phys_addr_t v2p(const iss::addr_t &addr) { + inline phys_addr_t v2p(const iss::addr_t& addr){ if (addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || - addr_mode[static_cast(addr.access) & 0x3] == address_type::PHYSICAL) { - return phys_addr_t(addr.access, addr.space, addr.val & traits::addr_mask); + addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { + return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); } else return virt2phys(addr); } - virtual phys_addr_t virt2phys(const iss::addr_t &addr); + virtual phys_addr_t virt2phys(const iss::addr_t& addr); virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } @@ -210,12 +237,14 @@ protected: } reg; std::array addr_mode; + + bool interrupt_sim=false; - bool interrupt_sim = false; + uint32_t get_fcsr(){return 0;} + void set_fcsr(uint32_t val){} - uint32_t get_fcsr() { return 0; } - void set_fcsr(uint32_t val) {} }; + } -} +} #endif /* _RV32IMAC_H_ */ diff --git a/riscv/incl/iss/arch/rv64gc.h b/riscv/incl/iss/arch/rv64gc.h new file mode 100644 index 0000000..b10843d --- /dev/null +++ b/riscv/incl/iss/arch/rv64gc.h @@ -0,0 +1,316 @@ +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + + +#ifndef _RV64GC_H_ +#define _RV64GC_H_ + +#include +#include +#include +#include + +namespace iss { +namespace arch { + +struct rv64gc; + +template <> struct traits { + + constexpr static char const* const core_type = "RV64GC"; + + static constexpr std::array reg_names{ + {"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}}; + + static constexpr std::array reg_aliases{ + {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}}; + + enum constants {XLEN=64, FLEN=64, PCLEN=64, MISA_VAL=0b1000000000101000001000100101101, PGSIZE=0x1000, PGMASK=0xfff}; + + constexpr static unsigned FP_REGS_SIZE = 64; + + enum reg_e { + X0, + X1, + X2, + X3, + X4, + X5, + X6, + X7, + X8, + X9, + X10, + X11, + X12, + X13, + X14, + X15, + X16, + X17, + X18, + X19, + X20, + X21, + X22, + X23, + X24, + X25, + X26, + X27, + X28, + X29, + X30, + X31, + PC, + F0, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, + F25, + F26, + F27, + F28, + F29, + F30, + F31, + FCSR, + NUM_REGS, + NEXT_PC=NUM_REGS, + TRAP_STATE, + PENDING_TRAP, + MACHINE_STATE, + LAST_BRANCH, + ICOUNT, + ZERO = X0, + RA = X1, + SP = X2, + GP = X3, + TP = X4, + T0 = X5, + T1 = X6, + T2 = X7, + S0 = X8, + S1 = X9, + A0 = X10, + A1 = X11, + A2 = X12, + A3 = X13, + A4 = X14, + A5 = X15, + A6 = X16, + A7 = X17, + S2 = X18, + S3 = X19, + S4 = X20, + S5 = X21, + S6 = X22, + S7 = X23, + S8 = X24, + S9 = X25, + S10 = X26, + S11 = X27, + T3 = X28, + T4 = X29, + T5 = X30, + T6 = X31 + }; + + using reg_t = uint64_t; + + using addr_t = uint64_t; + + using code_word_t = uint64_t; //TODO: check removal + + using virt_addr_t = iss::typed_addr_t; + + using phys_addr_t = iss::typed_addr_t; + + static constexpr std::array reg_bit_widths{ + {64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,64,32,32,32,32,64}}; + + static constexpr std::array reg_byte_offsets{ + {0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,400,408,416,424,432,440,448,456,464,472,480,488,496,504,512,520,528,536,540,544,548,552,560}}; + + static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); + + enum sreg_flag_e { FLAGS }; + + enum mem_type_e { MEM, CSR, FENCE, RES }; +}; + +struct rv64gc: public arch_if { + + using virt_addr_t = typename traits::virt_addr_t; + using phys_addr_t = typename traits::phys_addr_t; + using reg_t = typename traits::reg_t; + using addr_t = typename traits::addr_t; + + rv64gc(); + ~rv64gc(); + + void reset(uint64_t address=0) override; + + uint8_t* get_regs_base_ptr() override; + /// deprecated + void get_reg(short idx, std::vector& value) override {} + void set_reg(short idx, const std::vector& value) override {} + /// deprecated + bool get_flag(int flag) override {return false;} + void set_flag(int, bool value) override {}; + /// deprecated + void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; + + inline uint64_t get_icount() { return reg.icount; } + + inline bool should_stop() { return interrupt_sim; } + + inline phys_addr_t v2p(const iss::addr_t& addr){ + if (addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || + addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { + return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); + } else + return virt2phys(addr); + } + + virtual phys_addr_t virt2phys(const iss::addr_t& addr); + + virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } + + inline uint32_t get_last_branch() { return reg.last_branch; } + +protected: + struct RV64GC_regs { + uint64_t X0 = 0; + uint64_t X1 = 0; + uint64_t X2 = 0; + uint64_t X3 = 0; + uint64_t X4 = 0; + uint64_t X5 = 0; + uint64_t X6 = 0; + uint64_t X7 = 0; + uint64_t X8 = 0; + uint64_t X9 = 0; + uint64_t X10 = 0; + uint64_t X11 = 0; + uint64_t X12 = 0; + uint64_t X13 = 0; + uint64_t X14 = 0; + uint64_t X15 = 0; + uint64_t X16 = 0; + uint64_t X17 = 0; + uint64_t X18 = 0; + uint64_t X19 = 0; + uint64_t X20 = 0; + uint64_t X21 = 0; + uint64_t X22 = 0; + uint64_t X23 = 0; + uint64_t X24 = 0; + uint64_t X25 = 0; + uint64_t X26 = 0; + uint64_t X27 = 0; + uint64_t X28 = 0; + uint64_t X29 = 0; + uint64_t X30 = 0; + uint64_t X31 = 0; + uint64_t PC = 0; + uint64_t F0 = 0; + uint64_t F1 = 0; + uint64_t F2 = 0; + uint64_t F3 = 0; + uint64_t F4 = 0; + uint64_t F5 = 0; + uint64_t F6 = 0; + uint64_t F7 = 0; + uint64_t F8 = 0; + uint64_t F9 = 0; + uint64_t F10 = 0; + uint64_t F11 = 0; + uint64_t F12 = 0; + uint64_t F13 = 0; + uint64_t F14 = 0; + uint64_t F15 = 0; + uint64_t F16 = 0; + uint64_t F17 = 0; + uint64_t F18 = 0; + uint64_t F19 = 0; + uint64_t F20 = 0; + uint64_t F21 = 0; + uint64_t F22 = 0; + uint64_t F23 = 0; + uint64_t F24 = 0; + uint64_t F25 = 0; + uint64_t F26 = 0; + uint64_t F27 = 0; + uint64_t F28 = 0; + uint64_t F29 = 0; + uint64_t F30 = 0; + uint64_t F31 = 0; + uint32_t FCSR = 0; + uint64_t NEXT_PC = 0; + uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; + uint64_t icount = 0; + } reg; + + std::array addr_mode; + + bool interrupt_sim=false; + + uint32_t get_fcsr(){return reg.FCSR;} + void set_fcsr(uint32_t val){reg.FCSR = val;} + +}; + +} +} +#endif /* _RV64GC_H_ */ diff --git a/riscv/incl/iss/arch/rv64i.h b/riscv/incl/iss/arch/rv64i.h new file mode 100644 index 0000000..2f6c2bf --- /dev/null +++ b/riscv/incl/iss/arch/rv64i.h @@ -0,0 +1,250 @@ +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + + +#ifndef _RV64I_H_ +#define _RV64I_H_ + +#include +#include +#include +#include + +namespace iss { +namespace arch { + +struct rv64i; + +template <> struct traits { + + constexpr static char const* const core_type = "RV64I"; + + static constexpr std::array reg_names{ + {"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc"}}; + + static constexpr std::array reg_aliases{ + {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}}; + + enum constants {XLEN=64, PCLEN=64, MISA_VAL=0b10000000000001000000000100000000, PGSIZE=0x1000, PGMASK=0xfff}; + + constexpr static unsigned FP_REGS_SIZE = 0; + + enum reg_e { + X0, + X1, + X2, + X3, + X4, + X5, + X6, + X7, + X8, + X9, + X10, + X11, + X12, + X13, + X14, + X15, + X16, + X17, + X18, + X19, + X20, + X21, + X22, + X23, + X24, + X25, + X26, + X27, + X28, + X29, + X30, + X31, + PC, + NUM_REGS, + NEXT_PC=NUM_REGS, + TRAP_STATE, + PENDING_TRAP, + MACHINE_STATE, + LAST_BRANCH, + ICOUNT, + ZERO = X0, + RA = X1, + SP = X2, + GP = X3, + TP = X4, + T0 = X5, + T1 = X6, + T2 = X7, + S0 = X8, + S1 = X9, + A0 = X10, + A1 = X11, + A2 = X12, + A3 = X13, + A4 = X14, + A5 = X15, + A6 = X16, + A7 = X17, + S2 = X18, + S3 = X19, + S4 = X20, + S5 = X21, + S6 = X22, + S7 = X23, + S8 = X24, + S9 = X25, + S10 = X26, + S11 = X27, + T3 = X28, + T4 = X29, + T5 = X30, + T6 = X31 + }; + + using reg_t = uint64_t; + + using addr_t = uint64_t; + + using code_word_t = uint64_t; //TODO: check removal + + using virt_addr_t = iss::typed_addr_t; + + using phys_addr_t = iss::typed_addr_t; + + static constexpr std::array reg_bit_widths{ + {64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,64}}; + + static constexpr std::array reg_byte_offsets{ + {0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,276,280,284,288,296}}; + + static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); + + enum sreg_flag_e { FLAGS }; + + enum mem_type_e { MEM, CSR, FENCE, RES }; +}; + +struct rv64i: public arch_if { + + using virt_addr_t = typename traits::virt_addr_t; + using phys_addr_t = typename traits::phys_addr_t; + using reg_t = typename traits::reg_t; + using addr_t = typename traits::addr_t; + + rv64i(); + ~rv64i(); + + void reset(uint64_t address=0) override; + + uint8_t* get_regs_base_ptr() override; + /// deprecated + void get_reg(short idx, std::vector& value) override {} + void set_reg(short idx, const std::vector& value) override {} + /// deprecated + bool get_flag(int flag) override {return false;} + void set_flag(int, bool value) override {}; + /// deprecated + void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; + + inline uint64_t get_icount() { return reg.icount; } + + inline bool should_stop() { return interrupt_sim; } + + inline phys_addr_t v2p(const iss::addr_t& addr){ + if (addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || + addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { + return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); + } else + return virt2phys(addr); + } + + virtual phys_addr_t virt2phys(const iss::addr_t& addr); + + virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } + + inline uint32_t get_last_branch() { return reg.last_branch; } + +protected: + struct RV64I_regs { + uint64_t X0 = 0; + uint64_t X1 = 0; + uint64_t X2 = 0; + uint64_t X3 = 0; + uint64_t X4 = 0; + uint64_t X5 = 0; + uint64_t X6 = 0; + uint64_t X7 = 0; + uint64_t X8 = 0; + uint64_t X9 = 0; + uint64_t X10 = 0; + uint64_t X11 = 0; + uint64_t X12 = 0; + uint64_t X13 = 0; + uint64_t X14 = 0; + uint64_t X15 = 0; + uint64_t X16 = 0; + uint64_t X17 = 0; + uint64_t X18 = 0; + uint64_t X19 = 0; + uint64_t X20 = 0; + uint64_t X21 = 0; + uint64_t X22 = 0; + uint64_t X23 = 0; + uint64_t X24 = 0; + uint64_t X25 = 0; + uint64_t X26 = 0; + uint64_t X27 = 0; + uint64_t X28 = 0; + uint64_t X29 = 0; + uint64_t X30 = 0; + uint64_t X31 = 0; + uint64_t PC = 0; + uint64_t NEXT_PC = 0; + uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; + uint64_t icount = 0; + } reg; + + std::array addr_mode; + + bool interrupt_sim=false; + + uint32_t get_fcsr(){return 0;} + void set_fcsr(uint32_t val){} + +}; + +} +} +#endif /* _RV64I_H_ */ diff --git a/riscv/incl/iss/arch/rv64ia.h b/riscv/incl/iss/arch/rv64ia.h deleted file mode 100644 index be17b06..0000000 --- a/riscv/incl/iss/arch/rv64ia.h +++ /dev/null @@ -1,218 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// 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. -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef _RV64IA_H_ -#define _RV64IA_H_ - -#include -#include -#include -#include - -namespace iss { -namespace arch { - -struct rv64ia; - -template<> -struct traits { - - constexpr static char const* const core_type = "RV64IA"; - - enum constants {XLEN=64, PCLEN=64, MISA_VAL=0b10000000000001000000000100000001, PGSIZE=0x1000, PGMASK=0xfff}; - - constexpr static unsigned FP_REGS_SIZE = 0; - - enum reg_e { - X0, - X1, - X2, - X3, - X4, - X5, - X6, - X7, - X8, - X9, - X10, - X11, - X12, - X13, - X14, - X15, - X16, - X17, - X18, - X19, - X20, - X21, - X22, - X23, - X24, - X25, - X26, - X27, - X28, - X29, - X30, - X31, - PC, - NUM_REGS, - NEXT_PC=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - LAST_BRANCH, - ICOUNT - }; - - using reg_t = uint64_t; - - using addr_t = uint64_t; - - using code_word_t = uint64_t; //TODO: check removal - - using virt_addr_t = iss::typed_addr_t; - - using phys_addr_t = iss::typed_addr_t; - - constexpr static unsigned reg_bit_width(unsigned r) { - constexpr std::array RV64IA_reg_size{{64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,64}}; - return RV64IA_reg_size[r]; - } - - constexpr static unsigned reg_byte_offset(unsigned r) { - constexpr std::array RV64IA_reg_byte_offset{{0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,276,280,284,288,296}}; - return RV64IA_reg_byte_offset[r]; - } - - static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); - - enum sreg_flag_e {FLAGS}; - - enum mem_type_e {MEM, CSR, FENCE, RES}; -}; - -struct rv64ia: public arch_if { - - using virt_addr_t = typename traits::virt_addr_t; - using phys_addr_t = typename traits::phys_addr_t; - using reg_t = typename traits::reg_t; - using addr_t = typename traits::addr_t; - - rv64ia(); - ~rv64ia(); - - void reset(uint64_t address=0) override; - - uint8_t* get_regs_base_ptr() override; - /// deprecated - void get_reg(short idx, std::vector& value) override {} - void set_reg(short idx, const std::vector& value) override {} - /// deprecated - bool get_flag(int flag) override {return false;} - void set_flag(int, bool value) override {}; - /// deprecated - void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; - - inline uint64_t get_icount() { return reg.icount; } - - inline bool should_stop() { return interrupt_sim; } - - inline phys_addr_t v2p(const iss::addr_t& addr){ - if(addr.space != traits::MEM || - addr.type == iss::address_type::PHYSICAL || - addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL){ - return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); - } else - return virt2phys(addr); - } - - virtual phys_addr_t virt2phys(const iss::addr_t& addr); - - virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } - - inline - uint32_t get_last_branch(){return reg.last_branch;} - -protected: - struct RV64IA_regs { - uint64_t X0 = 0; - uint64_t X1 = 0; - uint64_t X2 = 0; - uint64_t X3 = 0; - uint64_t X4 = 0; - uint64_t X5 = 0; - uint64_t X6 = 0; - uint64_t X7 = 0; - uint64_t X8 = 0; - uint64_t X9 = 0; - uint64_t X10 = 0; - uint64_t X11 = 0; - uint64_t X12 = 0; - uint64_t X13 = 0; - uint64_t X14 = 0; - uint64_t X15 = 0; - uint64_t X16 = 0; - uint64_t X17 = 0; - uint64_t X18 = 0; - uint64_t X19 = 0; - uint64_t X20 = 0; - uint64_t X21 = 0; - uint64_t X22 = 0; - uint64_t X23 = 0; - uint64_t X24 = 0; - uint64_t X25 = 0; - uint64_t X26 = 0; - uint64_t X27 = 0; - uint64_t X28 = 0; - uint64_t X29 = 0; - uint64_t X30 = 0; - uint64_t X31 = 0; - uint64_t PC = 0; - uint64_t NEXT_PC = 0; - uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; - uint64_t icount = 0; - } reg; - - std::array addr_mode; - - bool interrupt_sim=false; - - uint32_t get_fcsr(){return 0;} - void set_fcsr(uint32_t val){} - -}; - -} -} -#endif /* _RV64IA_H_ */ diff --git a/riscv/incl/iss/debugger/riscv_target_adapter.h b/riscv/incl/iss/debugger/riscv_target_adapter.h index 7133e34..e6ec40e 100644 --- a/riscv/incl/iss/debugger/riscv_target_adapter.h +++ b/riscv/incl/iss/debugger/riscv_target_adapter.h @@ -40,6 +40,7 @@ #include #include +#include #include namespace iss { @@ -180,8 +181,8 @@ status riscv_target_adapter::read_registers(std::vector &data, st avail.clear(); const uint8_t *reg_base = core->get_regs_base_ptr(); for (size_t reg_no = 0; reg_no < arch::traits::NUM_REGS; ++reg_no) { - auto reg_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)) / 8; - unsigned offset = traits::reg_byte_offset(reg_no); + auto reg_width = arch::traits::reg_bit_widths[static_cast::reg_e>(reg_no)] / 8; + unsigned offset = traits::reg_byte_offsets[reg_no]; for (size_t j = 0; j < reg_width; ++j) { data.push_back(*(reg_base + offset + j)); avail.push_back(0xff); @@ -215,8 +216,8 @@ template status riscv_target_adapter::write_registers(cons auto *reg_base = core->get_regs_base_ptr(); auto iter = data.data(); for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) { - auto reg_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)) / 8; - auto offset = traits::reg_byte_offset(reg_no); + auto reg_width = arch::traits::reg_bit_widths[static_cast::reg_e>(reg_no)] / 8; + auto offset = traits::reg_byte_offsets[reg_no]; std::copy(iter, iter + reg_width, reg_base); iter += 4; reg_base += offset; @@ -231,10 +232,10 @@ status riscv_target_adapter::read_single_register(unsigned int reg_no, std // auto reg_size = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no))/8; auto *reg_base = core->get_regs_base_ptr(); - auto reg_width = arch::traits::reg_bit_width(reg_no) / 8; + auto reg_width = arch::traits::reg_bit_widths[reg_no] / 8; data.resize(reg_width); avail.resize(reg_width); - auto offset = traits::reg_byte_offset(reg_no); + auto offset = traits::reg_byte_offsets[reg_no]; std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin()); std::fill(avail.begin(), avail.end(), 0xff); } else { @@ -251,8 +252,8 @@ template status riscv_target_adapter::write_single_register(unsigned int reg_no, const std::vector &data) { if (reg_no < 65) { auto *reg_base = core->get_regs_base_ptr(); - auto reg_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)) / 8; - auto offset = traits::reg_byte_offset(reg_no); + auto reg_width = arch::traits::reg_bit_widths[static_cast::reg_e>(reg_no)] / 8; + auto offset = traits::reg_byte_offsets[reg_no]; std::copy(data.begin(), data.begin() + reg_width, reg_base + offset); } else { typed_addr_t a(iss::access_type::DEBUG_WRITE, traits::CSR, reg_no - 65); @@ -296,9 +297,7 @@ template status riscv_target_adapter::raw_query(std::strin template status riscv_target_adapter::threadinfo_query(int first, std::string &out_buf) { if (first) { - std::stringstream ss; - ss << "m" << std::hex << thread_idx.val; - out_buf = ss.str(); + out_buf = fmt::format("m{:x}", thread_idx.val); } else { out_buf = "l"; } @@ -348,8 +347,8 @@ template status riscv_target_adapter::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, std::function stop_callback) { auto *reg_base = core->get_regs_base_ptr(); - auto reg_width = arch::traits::reg_bit_width(arch::traits::PC) / 8; - auto offset = traits::reg_byte_offset(arch::traits::PC); + auto reg_width = arch::traits::reg_bit_widths[arch::traits::PC] / 8; + auto offset = traits::reg_byte_offsets[arch::traits::PC]; const uint8_t *iter = reinterpret_cast(&addr); std::copy(iter, iter + reg_width, reg_base); return resume_from_current(step, sig, thread, stop_callback); diff --git a/riscv.sc/incl/sysc/core_complex.h b/riscv/incl/sysc/core_complex.h similarity index 100% rename from riscv.sc/incl/sysc/core_complex.h rename to riscv/incl/sysc/core_complex.h diff --git a/riscv/src/CMakeLists.txt b/riscv/src/CMakeLists.txt index c10d28f..845d769 100644 --- a/riscv/src/CMakeLists.txt +++ b/riscv/src/CMakeLists.txt @@ -4,18 +4,16 @@ set(LIB_HEADERS ${RiscVSCHeaders} ) set(LIB_SOURCES iss/rv32gc.cpp iss/rv32imac.cpp - iss/rv64ia.cpp + iss/rv64i.cpp + iss/rv64gc.cpp internal/fp_functions.cpp internal/vm_rv32gc.cpp internal/vm_rv32imac.cpp - internal/vm_rv64ia.cpp + internal/vm_rv64i.cpp + internal/vm_rv64gc.cpp plugin/instruction_count.cpp plugin/cycle_estimate.cpp) -set(APP_HEADERS ) - -set(APP_SOURCES main.cpp) - # Define two variables in order not to repeat ourselves. set(LIBRARY_NAME riscv) @@ -27,17 +25,44 @@ set_target_properties(${LIBRARY_NAME} PROPERTIES FRAMEWORK FALSE PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers ) +#set_property(TARGET ${LIBRARY_NAME} PROPERTY POSITION_INDEPENDENT_CODE ON) + +if(SystemC_FOUND) + set(SC_LIBRARY_NAME riscv_sc) + add_library(${SC_LIBRARY_NAME} SHARED sysc/core_complex.cpp) + add_definitions(-DWITH_SYSTEMC) + include_directories(${SystemC_INCLUDE_DIRS}) + + include_directories(${CCI_INCLUDE_DIRS}) + + if(SCV_FOUND) + add_definitions(-DWITH_SCV) + include_directories(${SCV_INCLUDE_DIRS}) + endif() + set_target_properties(${SC_LIBRARY_NAME} PROPERTIES + VERSION ${VERSION} # ${VERSION} was defined in the main CMakeLists. + FRAMEWORK FALSE + PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers + ) + target_link_libraries(${SC_LIBRARY_NAME} ${LIBRARY_NAME}) + target_link_libraries(${SC_LIBRARY_NAME} dbt-core) + target_link_libraries(${SC_LIBRARY_NAME} softfloat) + target_link_libraries(${SC_LIBRARY_NAME} sc-components) + target_link_libraries(${SC_LIBRARY_NAME} external) + target_link_libraries(${SC_LIBRARY_NAME} ${llvm_libs}) + target_link_libraries(${SC_LIBRARY_NAME} ${Boost_LIBRARIES} ) +endif() # This is a make target, so you can do a "make riscv-sc" set(APPLICATION_NAME riscv-sim) -add_executable(${APPLICATION_NAME} ${APP_SOURCES}) +add_executable(${APPLICATION_NAME} main.cpp) # Links the target exe against the libraries target_link_libraries(${APPLICATION_NAME} ${LIBRARY_NAME}) +target_link_libraries(${APPLICATION_NAME} jsoncpp) target_link_libraries(${APPLICATION_NAME} dbt-core) target_link_libraries(${APPLICATION_NAME} softfloat) -target_link_libraries(${APPLICATION_NAME} sc-components) target_link_libraries(${APPLICATION_NAME} external) target_link_libraries(${APPLICATION_NAME} ${llvm_libs}) target_link_libraries(${APPLICATION_NAME} ${Boost_LIBRARIES} ) diff --git a/riscv/src/internal/fp_functions.cpp b/riscv/src/internal/fp_functions.cpp index 34c1bac..1f0169a 100644 --- a/riscv/src/internal/fp_functions.cpp +++ b/riscv/src/internal/fp_functions.cpp @@ -33,7 +33,7 @@ //////////////////////////////////////////////////////////////////////////////// #include -#include +#include extern "C" { #include @@ -70,7 +70,7 @@ using namespace std; using namespace llvm; -void add_fp_functions_2_module(Module *mod, uint32_t flen) { +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)); @@ -83,6 +83,8 @@ void add_fp_functions_2_module(Module *mod, uint32_t flen) { 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)); @@ -96,6 +98,8 @@ void add_fp_functions_2_module(Module *mod, uint32_t flen) { 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)); + } } } @@ -198,13 +202,15 @@ uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode) { float32_t v1f{v1}; softfloat_exceptionFlags=0; float32_t r; - int32_t res; switch(op){ - case 0: //w->s, fp to int32 - res = f32_to_i32(v1f,rmm_map[mode&0x7],true); + case 0:{ //w->s, fp to int32 + uint_fast32_t res = f32_to_i32(v1f,rmm_map[mode&0x7],true); return (uint32_t)res; - case 1: //wu->s - return f32_to_ui32(v1f,rmm_map[mode&0x7],true); + } + case 1:{ //wu->s + uint_fast32_t res = f32_to_ui32(v1f,rmm_map[mode&0x7],true); + return (uint32_t)res; + } case 2: //s->w r=i32_to_f32(v1); return r.v; @@ -373,17 +379,19 @@ uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) { float64_t v1f{v1}; softfloat_exceptionFlags=0; float64_t r; - int32_t res; switch(op){ - case 0: //w->s, fp to int32 - res = f64_to_i64(v1f,rmm_map[mode&0x7],true); + case 0:{ //l->d, fp to int32 + int64_t res = f64_to_i64(v1f,rmm_map[mode&0x7],true); return (uint64_t)res; - case 1: //wu->s - return f64_to_ui64(v1f,rmm_map[mode&0x7],true); - case 2: //s->w + } + case 1:{ //lu->s + uint64_t res = f64_to_ui64(v1f,rmm_map[mode&0x7],true); + return res; + } + case 2: //s->l r=i64_to_f64(v1); return r.v; - case 3: //s->wu + case 3: //s->lu r=ui64_to_f64(v1); return r.v; } @@ -454,5 +462,53 @@ uint64_t fclass_d(uint64_t v1 ){ ( isNaN && !isSNaN ) << 9; } +uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode) { + float32_t v1f{v1}; + softfloat_exceptionFlags=0; + float64_t r; + switch(op){ + case 0: //l->s, fp to int32 + return f32_to_i64(v1f,rmm_map[mode&0x7],true); + case 1: //wu->s + return f32_to_ui64(v1f,rmm_map[mode&0x7],true); + case 2: //s->w + r=i32_to_f64(v1); + return r.v; + case 3: //s->wu + r=ui32_to_f64(v1); + return r.v; + } + return 0; +} + +uint32_t fcvt_64_32(uint64_t v1, uint32_t op, uint8_t mode) { + softfloat_exceptionFlags=0; + float32_t r; + switch(op){ + case 0:{ //wu->s + int32_t r=f64_to_i32(float64_t{v1}, rmm_map[mode&0x7],true); + return r; + } + case 1:{ //wu->s + uint32_t r=f64_to_ui32(float64_t{v1}, rmm_map[mode&0x7],true); + return r; + } + case 2: //l->s, fp to int32 + r=i64_to_f32(v1); + return r.v; + case 3: //wu->s + r=ui64_to_f32(v1); + return r.v; + } + return 0; +} + +uint32_t unbox_s(uint64_t v){ + constexpr uint64_t mask = std::numeric_limits::max() & ~((uint64_t)std::numeric_limits::max()); + if((v & mask) != mask) + return 0x7fc00000; + else + return v & std::numeric_limits::max(); +} } diff --git a/riscv/src/internal/vm_rv32gc.cpp b/riscv/src/internal/vm_rv32gc.cpp index bd78915..4cb95a4 100644 --- a/riscv/src/internal/vm_rv32gc.cpp +++ b/riscv/src/internal/vm_rv32gc.cpp @@ -1,56 +1,52 @@ -//////////////////////////////////////////////////////////////////////////////// -// 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 -// -// -//////////////////////////////////////////////////////////////////////////////// +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ #include #include #include #include #include -#include +#include #include -#include +#include -#include #include +#include namespace iss { namespace vm { -namespace fp_impl{ -void add_fp_functions_2_module(llvm::Module *, unsigned); +namespace fp_impl { +void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); } } @@ -58,10 +54,11 @@ namespace rv32gc { using namespace iss::arch; using namespace llvm; using namespace iss::debugger; +using namespace iss::vm::llvm; -template class vm_impl : public vm::vm_base { +template class vm_impl : public vm_base { public: - using super = typename vm::vm_base; + using super = typename iss::vm::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; @@ -73,33 +70,34 @@ public: void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } - target_adapter_if *accquire_target_adapter(server_if *srv) { + target_adapter_if *accquire_target_adapter(server_if *srv) override { debugger_if::dbg_enabled = true; - if (vm::vm_base::tgt_adapter == nullptr) - vm::vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm::vm_base::tgt_adapter; + if (vm_base::tgt_adapter == nullptr) + vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return vm_base::tgt_adapter; } protected: - using vm::vm_base::get_reg_ptr; + using vm_base::get_reg_ptr; - template inline llvm::ConstantInt *size(T type) { - return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); + 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(llvm::Module* m) override { + void setup_module(Module* m) override { super::setup_module(m); - vm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE); + iss::vm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); } - inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, unsigned size) { + inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); } - std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, - llvm::BasicBlock *) override; + std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override; - void gen_leave_behavior(llvm::BasicBlock *leave_blk) override; + void gen_leave_behavior(BasicBlock *leave_blk) override; void gen_raise_trap(uint16_t trap_id, uint16_t cause); @@ -107,17 +105,17 @@ protected: void gen_wait(unsigned type); - void gen_trap_behavior(llvm::BasicBlock *) override; + void gen_trap_behavior(BasicBlock *) override; - void gen_trap_check(llvm::BasicBlock *bb); + void gen_trap_check(BasicBlock *bb); - inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) { + 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) { - llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); + 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); } @@ -128,17 +126,17 @@ protected: enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; using this_class = vm_impl; - using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, - code_word_t instr, - llvm::BasicBlock *bb); + using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, + code_word_t instr, + BasicBlock *bb); std::array lut; std::array lut_00, lut_01, lut_10; std::array lut_11; - std::array qlut; + std::array 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) { @@ -190,14 +188,138 @@ 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 */ @@ -294,100 +416,6 @@ 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 FLW */ {32, 0b00000000000000000010000000000111, 0b00000000000000000111000001111111, &this_class::__flw}, /* instruction FSW */ @@ -440,208 +468,65 @@ private: {32, 0b11100000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_w}, /* instruction FMV.W.X */ {32, 0b11110000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_w_x}, - /* 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 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 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 definitions */ - /* instruction 0: LUI */ - std::tuple __lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LUI"); - - this->gen_sync(iss::PRE_SYNC, 0); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - int32_t fld_imm_val = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LUI x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_const(32U, fld_imm_val); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 0); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 1: AUIPC */ - std::tuple __auipc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AUIPC"); - - this->gen_sync(iss::PRE_SYNC, 1); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - int32_t fld_imm_val = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AUIPC x%1%, 0x%2$08x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 1); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 2: JAL */ - std::tuple __jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("JAL"); - - this->gen_sync(iss::PRE_SYNC, 2); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - int32_t fld_imm_val = 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 */ - boost::format ins_fmter("JAL x%1$d, 0x%2$x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)); - 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(iss::POST_SYNC, 2); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 3: JALR */ - std::tuple __jalr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* instruction 0: JALR */ + std::tuple __jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("JALR"); - this->gen_sync(iss::PRE_SYNC, 3); + this->gen_sync(PRE_SYNC, 0); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(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 */ - boost::format ins_fmter("JALR x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -651,16 +536,16 @@ private: Value* new_pc_val = this->builder.CreateAdd( this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(rs1 + traits::X0, 0), 32, true), - this->gen_const(32U, fld_imm_val)); + this->gen_const(32U, imm)); Value* align_val = this->builder.CreateAnd( new_pc_val, - this->gen_const(32U, 0x1)); + this->gen_const(32U, 0x2)); { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + 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, @@ -675,11 +560,11 @@ private: this->builder.CreateBr(bbnext); this->builder.SetInsertPoint(bb_else); { - if(fld_rd_val != 0){ + 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(fld_rd_val + traits::X0), false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } Value* PC_val = this->builder.CreateAnd( new_pc_val, @@ -691,3127 +576,28 @@ private: bb=bbnext; } this->builder.SetInsertPoint(bb); - this->gen_sync(iss::POST_SYNC, 3); + this->gen_sync(POST_SYNC, 0); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 4: BEQ */ - std::tuple __beq(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BEQ"); - - this->gen_sync(iss::PRE_SYNC, 4); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BEQ x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 4); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 5: BNE */ - std::tuple __bne(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BNE"); - - this->gen_sync(iss::PRE_SYNC, 5); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BNE x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 5); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 6: BLT */ - std::tuple __blt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BLT"); - - this->gen_sync(iss::PRE_SYNC, 6); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BLT x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 6); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 7: BGE */ - std::tuple __bge(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BGE"); - - this->gen_sync(iss::PRE_SYNC, 7); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BGE x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 7); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 8: BLTU */ - std::tuple __bltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BLTU"); - - this->gen_sync(iss::PRE_SYNC, 8); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BLTU x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 8); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 9: BGEU */ - std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BGEU"); - - this->gen_sync(iss::PRE_SYNC, 9); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BGEU x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 9); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 10: LB */ - std::tuple __lb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LB"); - - this->gen_sync(iss::PRE_SYNC, 10); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LB x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 10); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 11: LH */ - std::tuple __lh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LH"); - - this->gen_sync(iss::PRE_SYNC, 11); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LH x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 11); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 12: LW */ - std::tuple __lw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LW"); - - this->gen_sync(iss::PRE_SYNC, 12); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LW x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 12); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 13: LBU */ - std::tuple __lbu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LBU"); - - this->gen_sync(iss::PRE_SYNC, 13); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LBU x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 13); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 14: LHU */ - std::tuple __lhu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LHU"); - - this->gen_sync(iss::PRE_SYNC, 14); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LHU x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 14); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 15: SB */ - std::tuple __sb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SB"); - - this->gen_sync(iss::PRE_SYNC, 15); - - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SB x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 15); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 16: SH */ - std::tuple __sh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SH"); - - this->gen_sync(iss::PRE_SYNC, 16); - - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SH x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 16); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 17: SW */ - std::tuple __sw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SW"); - - this->gen_sync(iss::PRE_SYNC, 17); - - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SW x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 17); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 18: ADDI */ - std::tuple __addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ADDI"); - - this->gen_sync(iss::PRE_SYNC, 18); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ADDI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 18); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 19: SLTI */ - std::tuple __slti(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLTI"); - - this->gen_sync(iss::PRE_SYNC, 19); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLTI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 19); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 20: SLTIU */ - std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLTIU"); - - this->gen_sync(iss::PRE_SYNC, 20); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLTIU x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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 = fld_imm_val; - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(fld_rs1_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 20); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 21: XORI */ - std::tuple __xori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("XORI"); - - this->gen_sync(iss::PRE_SYNC, 21); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("XORI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 21); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 22: ORI */ - std::tuple __ori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ORI"); - - this->gen_sync(iss::PRE_SYNC, 22); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ORI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 22); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 23: ANDI */ - std::tuple __andi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ANDI"); - - this->gen_sync(iss::PRE_SYNC, 23); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ANDI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 23); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 24: SLLI */ - std::tuple __slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLLI"); - - this->gen_sync(iss::PRE_SYNC, 24); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLLI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 0); - } else { - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 24); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 25: SRLI */ - std::tuple __srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRLI"); - - this->gen_sync(iss::PRE_SYNC, 25); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRLI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 0); - } else { - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 25); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 26: SRAI */ - std::tuple __srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRAI"); - - this->gen_sync(iss::PRE_SYNC, 26); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRAI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 0); - } else { - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 26); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 27: ADD */ - std::tuple __add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ADD"); - - this->gen_sync(iss::PRE_SYNC, 27); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ADD x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 27); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 28: SUB */ - std::tuple __sub(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SUB"); - - this->gen_sync(iss::PRE_SYNC, 28); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SUB x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 28); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 29: SLL */ - std::tuple __sll(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLL"); - - this->gen_sync(iss::PRE_SYNC, 29); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLL x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - this->gen_const(32U, 0x1f))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 29); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 30: SLT */ - std::tuple __slt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLT"); - - this->gen_sync(iss::PRE_SYNC, 30); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLT x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 32, true)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 30); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 31: SLTU */ - std::tuple __sltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLTU"); - - this->gen_sync(iss::PRE_SYNC, 31); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLTU x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 32, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 32, - false)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 31); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 32: XOR */ - std::tuple __xor(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("XOR"); - - this->gen_sync(iss::PRE_SYNC, 32); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("XOR x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 32); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 33: SRL */ - std::tuple __srl(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRL"); - - this->gen_sync(iss::PRE_SYNC, 33); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRL x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - this->gen_const(32U, 0x1f))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 33); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 34: SRA */ - std::tuple __sra(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRA"); - - this->gen_sync(iss::PRE_SYNC, 34); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRA x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - this->gen_const(32U, 0x1f))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 34); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 35: OR */ - std::tuple __or(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("OR"); - - this->gen_sync(iss::PRE_SYNC, 35); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("OR x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 35); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 36: AND */ - std::tuple __and(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AND"); - - this->gen_sync(iss::PRE_SYNC, 36); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AND x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 36); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 37: FENCE */ - std::tuple __fence(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FENCE"); - - this->gen_sync(iss::PRE_SYNC, 37); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_succ_val = ((bit_sub<20,4>(instr))); - uint8_t fld_pred_val = ((bit_sub<24,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("FENCE"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(32U, fld_pred_val), - this->gen_const(32U, 4)), - this->gen_const(32U, fld_succ_val)); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 0), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 37); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 38: FENCE_I */ - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FENCE_I"); - - this->gen_sync(iss::PRE_SYNC, 38); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_imm_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("FENCE_I"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, fld_imm_val); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 1), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 38); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::FLUSH, nullptr); - } - - /* instruction 39: ECALL */ - std::tuple __ecall(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ECALL"); - - this->gen_sync(iss::PRE_SYNC, 39); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ECALL"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 11); - this->gen_sync(iss::POST_SYNC, 39); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 40: EBREAK */ - std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("EBREAK"); - - this->gen_sync(iss::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(iss::POST_SYNC, 40); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 41: URET */ - std::tuple __uret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("URET"); - - this->gen_sync(iss::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(iss::POST_SYNC, 41); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 42: SRET */ - std::tuple __sret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRET"); - - this->gen_sync(iss::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(iss::POST_SYNC, 42); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 43: MRET */ - std::tuple __mret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("MRET"); - - this->gen_sync(iss::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(iss::POST_SYNC, 43); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 44: WFI */ - std::tuple __wfi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("WFI"); - - this->gen_sync(iss::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(iss::POST_SYNC, 44); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 45: SFENCE.VMA */ - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SFENCE.VMA"); - - this->gen_sync(iss::PRE_SYNC, 45); - - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("SFENCE.VMA"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, fld_rs1_val); - 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, fld_rs2_val); - 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(iss::POST_SYNC, 45); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 46: CSRRW */ - std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRW"); - - this->gen_sync(iss::PRE_SYNC, 46); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRW x%1$d, %2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* rs_val_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, fld_csr_val), 32/8); - Value* CSRtmp0_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - Value* Xtmp1_val = csr_val_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } else { - Value* CSRtmp2_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 46); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 47: CSRRS */ - std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRS"); - - this->gen_sync(iss::PRE_SYNC, 47); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRS x%1$d, %2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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, fld_csr_val), 32/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - if(fld_rs1_val != 0){ - Value* CSRtmp1_val = this->builder.CreateOr( - xrd_val, - xrs1_val); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 47); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 48: CSRRC */ - std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRC"); - - this->gen_sync(iss::PRE_SYNC, 48); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRC x%1$d, %2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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, fld_csr_val), 32/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - if(fld_rs1_val != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - xrd_val, - this->builder.CreateNot(xrs1_val)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 48); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 49: CSRRWI */ - std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRWI"); - - this->gen_sync(iss::PRE_SYNC, 49); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_zimm_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRWI x%1$d, %2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, fld_csr_val), 32/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* CSRtmp1_val = this->gen_ext( - this->gen_const(32U, fld_zimm_val), - 32, - false); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 49); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 50: CSRRSI */ - std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRSI"); - - this->gen_sync(iss::PRE_SYNC, 50); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_zimm_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRSI x%1$d, %2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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, fld_csr_val), 32/8); - if(fld_zimm_val != 0){ - Value* CSRtmp0_val = this->builder.CreateOr( - res_val, - this->gen_ext( - this->gen_const(32U, fld_zimm_val), - 32, - false)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - } - if(fld_rd_val != 0){ - Value* Xtmp1_val = res_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 50); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 51: CSRRCI */ - std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRCI"); - - this->gen_sync(iss::PRE_SYNC, 51); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_zimm_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRCI x%1$d, %2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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, fld_csr_val), 32/8); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - if(fld_zimm_val != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - res_val, - this->builder.CreateNot(this->gen_ext( - this->gen_const(32U, fld_zimm_val), - 32, - false))); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 51); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 52: MUL */ - std::tuple __mul(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("MUL"); - - this->gen_sync(iss::PRE_SYNC, 52); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("MUL x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 128, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 128, - false)); - Value* Xtmp0_val = this->gen_ext( - res_val, - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 52); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 53: MULH */ - std::tuple __mulh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("MULH"); - - this->gen_sync(iss::PRE_SYNC, 53); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("MULH x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 128, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 53); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 54: MULHSU */ - std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("MULHSU"); - - this->gen_sync(iss::PRE_SYNC, 54); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("MULHSU x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 128, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 54); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 55: MULHU */ - std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("MULHU"); - - this->gen_sync(iss::PRE_SYNC, 55); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("MULHU x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 128, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 55); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 56: DIV */ - std::tuple __div(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("DIV"); - - this->gen_sync(iss::PRE_SYNC, 56); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("DIV x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::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(fld_rs2_val + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint32_t MMIN_val = - 1 << 32 - 1; - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 1), - 32, true), - this->gen_ext( - this->gen_const(32U, MMIN_val), - 32, true)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_const(32U, M1_val), - 32, true)), - 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(fld_rd_val + 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(fld_rs1_val + traits::X0, 3), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 3), - 32, true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + 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.CreateSDiv( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 2), - 32, true)); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp3_val = this->builder.CreateNeg(this->gen_const(32U, 1)); - this->builder.CreateStore(Xtmp3_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 56); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 57: DIVU */ - std::tuple __divu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("DIVU"); - - this->gen_sync(iss::PRE_SYNC, 57); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("DIVU x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::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(fld_rs2_val + 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_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 1), - 32, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 1), - 32, - false)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 57); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 58: REM */ - std::tuple __rem(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("REM"); - - this->gen_sync(iss::PRE_SYNC, 58); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("REM x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::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(fld_rs2_val + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint32_t MMIN_val = - 1 << 32 - 1; - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 1), - 32, true), - this->gen_ext( - this->gen_const(32U, MMIN_val), - 32, true)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_const(32U, M1_val), - 32, true)), - 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(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateURem( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 3), - 32, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 3), - 32, - true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + 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.CreateURem( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 2), - 32, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 2), - 32, - true)); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp3_val = this->gen_reg_load(fld_rs1_val + traits::X0, 1); - this->builder.CreateStore(Xtmp3_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 58); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 59: REMU */ - std::tuple __remu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("REMU"); - - this->gen_sync(iss::PRE_SYNC, 59); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("REMU x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::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(fld_rs2_val + 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_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 1), - 32, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 1), - 32, - false)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 1); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 59); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 60: LR.W */ - std::tuple __lr_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LR.W"); - - this->gen_sync(iss::PRE_SYNC, 60); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LR.W x%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* offs_val = this->gen_reg_load(fld_rs1_val + 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(fld_rd_val + 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(iss::POST_SYNC, 60); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 61: SC.W */ - std::tuple __sc_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SC.W"); - - this->gen_sync(iss::PRE_SYNC, 61); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SC.W x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_read_mem(traits::RES, offs_val, 32/8); - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::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(fld_rs2_val + 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(fld_rd_val != 0){ - Value* Xtmp1_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - res1_val, - this->gen_const(32U, 0)), - this->gen_const(32U, 0), - this->gen_const(32U, 1), - 32); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 61); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 62: AMOSWAP.W */ - std::tuple __amoswap_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOSWAP.W"); - - this->gen_sync(iss::PRE_SYNC, 62); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOSWAP.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - Value* MEMtmp1_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 62); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 63: AMOADD.W */ - std::tuple __amoadd_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOADD.W"); - - this->gen_sync(iss::PRE_SYNC, 63); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOADD.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateAdd( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 63); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 64: AMOXOR.W */ - std::tuple __amoxor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOXOR.W"); - - this->gen_sync(iss::PRE_SYNC, 64); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOXOR.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateXor( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 64); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 65: AMOAND.W */ - std::tuple __amoand_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOAND.W"); - - this->gen_sync(iss::PRE_SYNC, 65); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOAND.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateAnd( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 65); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 66: AMOOR.W */ - std::tuple __amoor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOOR.W"); - - this->gen_sync(iss::PRE_SYNC, 66); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOOR.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateOr( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 66); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 67: AMOMIN.W */ - std::tuple __amomin_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMIN.W"); - - this->gen_sync(iss::PRE_SYNC, 67); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMIN.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rs2_val + traits::X0, 0), - 32, true)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 67); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 68: AMOMAX.W */ - std::tuple __amomax_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMAX.W"); - - this->gen_sync(iss::PRE_SYNC, 68); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMAX.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rs2_val + traits::X0, 0), - 32, true)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 68); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 69: AMOMINU.W */ - std::tuple __amominu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMINU.W"); - - this->gen_sync(iss::PRE_SYNC, 69); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMINU.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - false); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGT, - res1_val, - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 69); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 70: AMOMAXU.W */ - std::tuple __amomaxu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMAXU.W"); - - this->gen_sync(iss::PRE_SYNC, 70); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMAXU.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - false); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - res1_val, - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 70); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 71: C.ADDI4SPN */ - std::tuple __c_addi4spn(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 71); + this->gen_sync(PRE_SYNC, 1); - uint8_t fld_rd_val = ((bit_sub<2,3>(instr))); - uint16_t fld_imm_val = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); + 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 */ - boost::format ins_fmter("C.ADDI4SPN x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3819,37 +605,38 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - if(fld_imm_val == 0){ + 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, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 8 + traits::X0), false); + 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(iss::POST_SYNC, 71); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 72: C.LW */ - std::tuple __c_lw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 72); + this->gen_sync(PRE_SYNC, 2); - uint8_t fld_rd_val = ((bit_sub<2,3>(instr))); - uint8_t fld_uimm_val = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t fld_rs1_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.LW x(8+%1$d), x(8+%2$d), 0x%3$05x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_uimm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3858,34 +645,38 @@ private: pc=pc+2; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val + 8 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - Value* Xtmp0_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 8 + traits::X0), false); + 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(iss::POST_SYNC, 72); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 73: C.SW */ - std::tuple __c_sw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 73); + this->gen_sync(PRE_SYNC, 3); - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_uimm_val = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t fld_rs1_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.SW x(8+%1$d), x(8+%2$d), 0x%3$05x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3894,36 +685,37 @@ private: pc=pc+2; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val + 8 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 8 + traits::X0, 0); + 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(iss::POST_SYNC, 73); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 74: C.ADDI */ - std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 74); + this->gen_sync(PRE_SYNC, 4); - int8_t fld_imm_val = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<7,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 */ - boost::format ins_fmter("C.ADDI x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3933,29 +725,29 @@ private: Value* Xtmp0_val = this->builder.CreateAdd( this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(rs1 + traits::X0, 0), 32, true), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rs1_val + traits::X0), false); + 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(iss::POST_SYNC, 74); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 75: C.NOP */ - std::tuple __c_nop(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 75); + this->gen_sync(PRE_SYNC, 5); if(this->disass_enabled){ /* generate console output when executing the command */ - std::vector args { + std::vector args { this->core_ptr, this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("C.NOP"), + this->builder.CreateGlobalStringPtr("c.nop"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3965,27 +757,28 @@ private: /* TODO: describe operations for C.NOP ! */ this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 75); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 76: C.JAL */ - std::tuple __c_jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 76); + this->gen_sync(PRE_SYNC, 6); - int16_t fld_imm_val = 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<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 */ - boost::format ins_fmter("C.JAL 0x%1$05x"); - ins_fmter % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4001,31 +794,32 @@ private: this->gen_ext( cur_pc_val, 32, true), - this->gen_const(32U, fld_imm_val)); + 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(iss::POST_SYNC, 76); + this->gen_sync(POST_SYNC, 6); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 77: C.LI */ - std::tuple __c_li(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 77); + this->gen_sync(PRE_SYNC, 7); - int8_t fld_imm_val = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); + 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 */ - boost::format ins_fmter("C.LI x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4033,34 +827,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - if(fld_rd_val == 0){ + if(rd == 0){ this->gen_raise_trap(0, 2); } - Value* Xtmp0_val = this->gen_const(32U, fld_imm_val); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); + 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(iss::POST_SYNC, 77); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 78: C.LUI */ - std::tuple __c_lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 78); + this->gen_sync(PRE_SYNC, 8); - int32_t fld_imm_val = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); + 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 */ - boost::format ins_fmter("C.LUI x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4068,36 +863,37 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - if(fld_rd_val == 0){ + if(rd == 0){ this->gen_raise_trap(0, 2); } - if(fld_imm_val == 0){ + if(imm == 0){ this->gen_raise_trap(0, 2); } - Value* Xtmp0_val = this->gen_const(32U, fld_imm_val); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); + 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(iss::POST_SYNC, 78); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 79: C.ADDI16SP */ - std::tuple __c_addi16sp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 79); + this->gen_sync(PRE_SYNC, 9); - int16_t fld_imm_val = 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<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 */ - boost::format ins_fmter("C.ADDI16SP 0x%1$05x"); - ins_fmter % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4109,31 +905,32 @@ private: this->gen_ext( this->gen_reg_load(2 + traits::X0, 0), 32, true), - this->gen_const(32U, fld_imm_val)); + 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(iss::POST_SYNC, 79); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 80: C.SRLI */ - std::tuple __c_srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 80); + this->gen_sync(PRE_SYNC, 10); - uint8_t fld_shamt_val = ((bit_sub<2,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.SRLI x(8+%1$d), %2$d"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4141,34 +938,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rs1_idx_val = fld_rs1_val + 8; + 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, fld_shamt_val)); + 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(iss::POST_SYNC, 80); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 81: C.SRAI */ - std::tuple __c_srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 81); + this->gen_sync(PRE_SYNC, 11); - uint8_t fld_shamt_val = ((bit_sub<2,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.SRAI x(8+%1$d), %2$d"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4176,34 +974,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rs1_idx_val = fld_rs1_val + 8; + 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, fld_shamt_val)); + 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(iss::POST_SYNC, 81); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 82: C.ANDI */ - std::tuple __c_andi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 82); + this->gen_sync(PRE_SYNC, 12); - uint8_t fld_imm_val = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.ANDI x(8+%1$d), 0x%2$05x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4211,34 +1010,37 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rs1_idx_val = fld_rs1_val + 8; + uint8_t rs1_idx_val = rs1 + 8; Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(32U, fld_imm_val)); + 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(iss::POST_SYNC, 82); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 83: C.SUB */ - std::tuple __c_sub(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 83); + this->gen_sync(PRE_SYNC, 13); - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.SUB x(8+%1$d), x(8+%2$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4246,34 +1048,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rd_idx_val = fld_rd_val + 8; + 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(fld_rs2_val + 8 + 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(iss::POST_SYNC, 83); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 84: C.XOR */ - std::tuple __c_xor(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 84); + this->gen_sync(PRE_SYNC, 14); - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.XOR x(8+%1$d), x(8+%2$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4281,34 +1084,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rd_idx_val = fld_rd_val + 8; + 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(fld_rs2_val + 8 + 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(iss::POST_SYNC, 84); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 85: C.OR */ - std::tuple __c_or(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 85); + this->gen_sync(PRE_SYNC, 15); - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.OR x(8+%1$d), x(8+%2$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4316,34 +1120,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rd_idx_val = fld_rd_val + 8; + 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(fld_rs2_val + 8 + 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(iss::POST_SYNC, 85); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 86: C.AND */ - std::tuple __c_and(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 86); + this->gen_sync(PRE_SYNC, 16); - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.AND x(8+%1$d), x(8+%2$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4351,33 +1156,34 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rd_idx_val = fld_rd_val + 8; + 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(fld_rs2_val + 8 + 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(iss::POST_SYNC, 86); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 87: C.J */ - std::tuple __c_j(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 87); + this->gen_sync(PRE_SYNC, 17); - int16_t fld_imm_val = 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<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 */ - boost::format ins_fmter("C.J 0x%1$05x"); - ins_fmter % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4389,31 +1195,32 @@ private: this->gen_ext( cur_pc_val, 32, true), - this->gen_const(32U, fld_imm_val)); + 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(iss::POST_SYNC, 87); + this->gen_sync(POST_SYNC, 17); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 88: C.BEQZ */ - std::tuple __c_beqz(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 88); + this->gen_sync(PRE_SYNC, 18); - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<7,3>(instr))); + 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 */ - boost::format ins_fmter("C.BEQZ x(8+%1$d), 0x%2$05x"); - ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4424,13 +1231,13 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_EQ, - this->gen_reg_load(fld_rs1_val + 8 + traits::X0, 0), + 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, fld_imm_val)), + this->gen_const(32U, imm)), this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, 2)), @@ -4438,27 +1245,28 @@ 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(iss::POST_SYNC, 88); + this->gen_sync(POST_SYNC, 18); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 89: C.BNEZ */ - std::tuple __c_bnez(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 89); + this->gen_sync(PRE_SYNC, 19); - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<7,3>(instr))); + 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 */ - boost::format ins_fmter("C.BNEZ x(8+%1$d), 0x%2$05x"); - ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4469,13 +1277,13 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_NE, - this->gen_reg_load(fld_rs1_val + 8 + traits::X0, 0), + 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, fld_imm_val)), + this->gen_const(32U, imm)), this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, 2)), @@ -4483,27 +1291,28 @@ 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(iss::POST_SYNC, 89); + this->gen_sync(POST_SYNC, 19); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 90: C.SLLI */ - std::tuple __c_slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 90); + this->gen_sync(PRE_SYNC, 20); - uint8_t fld_shamt_val = ((bit_sub<2,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<7,5>(instr))); + 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 */ - boost::format ins_fmter("C.SLLI x%1$d, %2$d"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4511,36 +1320,37 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - if(fld_rs1_val == 0){ + if(rs1 == 0){ this->gen_raise_trap(0, 2); } Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rs1_val + traits::X0), false); + 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(iss::POST_SYNC, 90); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 91: C.LWSP */ - std::tuple __c_lwsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 91); + this->gen_sync(PRE_SYNC, 21); - uint8_t fld_uimm_val = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); + 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 */ - boost::format ins_fmter("C.LWSP x%1$d, sp, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4550,32 +1360,36 @@ private: Value* offs_val = this->builder.CreateAdd( this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - Value* Xtmp0_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); + 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(iss::POST_SYNC, 91); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 92: C.MV */ - std::tuple __c_mv(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 92); + this->gen_sync(PRE_SYNC, 22); - uint8_t fld_rs2_val = ((bit_sub<2,5>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,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 */ - boost::format ins_fmter("C.MV x%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4583,30 +1397,31 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - Value* Xtmp0_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); + 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(iss::POST_SYNC, 92); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 93: C.JR */ - std::tuple __c_jr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 93); + this->gen_sync(PRE_SYNC, 23); - uint8_t fld_rs1_val = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("C.JR x%1$d"); - ins_fmter % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4614,30 +1429,31 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - Value* PC_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + 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(iss::POST_SYNC, 93); + this->gen_sync(POST_SYNC, 23); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 94: C.ADD */ - std::tuple __c_add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 94); + this->gen_sync(PRE_SYNC, 24); - uint8_t fld_rs2_val = ((bit_sub<2,5>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,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 */ - boost::format ins_fmter("C.ADD x%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4646,31 +1462,32 @@ private: pc=pc+2; Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rd_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); + 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(iss::POST_SYNC, 94); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 95: C.JALR */ - std::tuple __c_jalr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 95); + this->gen_sync(PRE_SYNC, 25); - uint8_t fld_rs1_val = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("C.JALR x%1$d"); - ins_fmter % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4682,26 +1499,26 @@ private: 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(fld_rs1_val + traits::X0, 0); + 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(iss::POST_SYNC, 95); + this->gen_sync(POST_SYNC, 25); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 96: C.EBREAK */ - std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 96); + this->gen_sync(PRE_SYNC, 26); if(this->disass_enabled){ /* generate console output when executing the command */ - std::vector args { + std::vector args { this->core_ptr, this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("C.EBREAK"), + this->builder.CreateGlobalStringPtr("c.ebreak"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4710,27 +1527,28 @@ private: pc=pc+2; this->gen_raise_trap(0, 3); - this->gen_sync(iss::POST_SYNC, 96); + this->gen_sync(POST_SYNC, 26); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 97: C.SWSP */ - std::tuple __c_swsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 97); + this->gen_sync(PRE_SYNC, 27); - uint8_t fld_rs2_val = ((bit_sub<2,5>(instr))); - uint8_t fld_uimm_val = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); + 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 */ - boost::format ins_fmter("C.SWSP x2+0x%1$05x, x%2$d"); - ins_fmter % (uint64_t)fld_uimm_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4740,31 +1558,31 @@ private: Value* offs_val = this->builder.CreateAdd( this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 97); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 98: DII */ - std::tuple __dii(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* instruction 28: DII */ + std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("DII"); - this->gen_sync(iss::PRE_SYNC, 98); + this->gen_sync(PRE_SYNC, 28); if(this->disass_enabled){ /* generate console output when executing the command */ - std::vector args { + std::vector args { this->core_ptr, this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("DII"), + this->builder.CreateGlobalStringPtr("dii"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4774,1655 +1592,30 @@ private: this->gen_raise_trap(0, 2); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 98); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 99: FLW */ - std::tuple __flw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FLW"); + /* 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(iss::PRE_SYNC, 99); + this->gen_sync(PRE_SYNC, 29); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(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 */ - boost::format ins_fmter("FLW f%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - 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(fld_rd_val + 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(fld_rd_val + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 99); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 100: FSW */ - std::tuple __fsw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FSW"); - - this->gen_sync(iss::PRE_SYNC, 100); - - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FSW f%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 100); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 101: FMADD.S */ - std::tuple __fmadd_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FMADD.S"); - - this->gen_sync(iss::PRE_SYNC, 101); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rs3_val = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FMADD.S x%1$d, f%2$d, f%3$d, f%4$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs3_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), - this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + 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(iss::POST_SYNC, 101); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 102: FMSUB.S */ - std::tuple __fmsub_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FMSUB.S"); - - this->gen_sync(iss::PRE_SYNC, 102); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rs3_val = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FMSUB.S x%1$d, f%2$d, f%3$d, f%4$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs3_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), - this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + 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(iss::POST_SYNC, 102); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 103: FNMADD.S */ - std::tuple __fnmadd_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FNMADD.S"); - - this->gen_sync(iss::PRE_SYNC, 103); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rs3_val = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FNMADD.S x%1$d, f%2$d, f%3$d, f%4$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs3_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), - this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + 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(iss::POST_SYNC, 103); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 104: FNMSUB.S */ - std::tuple __fnmsub_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FNMSUB.S"); - - this->gen_sync(iss::PRE_SYNC, 104); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rs3_val = ((bit_sub<27,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FNMSUB.S x%1$d, f%2$d, f%3$d, f%4$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs3_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), - this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + 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(iss::POST_SYNC, 104); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 105: FADD.S */ - std::tuple __fadd_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FADD.S"); - - this->gen_sync(iss::PRE_SYNC, 105); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FADD.S f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), - this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + 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(iss::POST_SYNC, 105); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 106: FSUB.S */ - std::tuple __fsub_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FSUB.S"); - - this->gen_sync(iss::PRE_SYNC, 106); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FSUB.S f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), - this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + 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(iss::POST_SYNC, 106); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 107: FMUL.S */ - std::tuple __fmul_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FMUL.S"); - - this->gen_sync(iss::PRE_SYNC, 107); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FMUL.S f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), - this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + 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(iss::POST_SYNC, 107); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 108: FDIV.S */ - std::tuple __fdiv_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FDIV.S"); - - this->gen_sync(iss::PRE_SYNC, 108); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FDIV.S f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), - this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + 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(iss::POST_SYNC, 108); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 109: FSQRT.S */ - std::tuple __fsqrt_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FSQRT.S"); - - this->gen_sync(iss::PRE_SYNC, 109); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FSQRT.S f%1$d, f%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), - this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), - this->builder.CreateTrunc( - this->gen_reg_load(traits::FCSR, 0), - this-> get_type(8) - ), - 8) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + 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(iss::POST_SYNC, 109); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 110: FSGNJ.S */ - std::tuple __fsgnj_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FSGNJ.S"); - - this->gen_sync(iss::PRE_SYNC, 110); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FSGNJ.S f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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.CreateOr( - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_const(32U, 0x7fffffff)), - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_const(32U, 0x80000000))); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 110); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 111: FSGNJN.S */ - std::tuple __fsgnjn_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FSGNJN.S"); - - this->gen_sync(iss::PRE_SYNC, 111); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FSGNJN.S f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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.CreateOr( - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_const(32U, 0x7fffffff)), - this->builder.CreateAnd( - this->builder.CreateNot(this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - )), - this->gen_const(32U, 0x80000000))); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 111); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 112: FSGNJX.S */ - std::tuple __fsgnjx_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FSGNJX.S"); - - this->gen_sync(iss::PRE_SYNC, 112); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FSGNJX.S f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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.CreateXor( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_const(32U, 0x80000000))); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 112); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 113: FMIN.S */ - std::tuple __fmin_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FMIN.S"); - - this->gen_sync(iss::PRE_SYNC, 113); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FMIN.S f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + 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(iss::POST_SYNC, 113); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 114: FMAX.S */ - std::tuple __fmax_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FMAX.S"); - - this->gen_sync(iss::PRE_SYNC, 114); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FMAX.S f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + 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(iss::POST_SYNC, 114); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 115: FCVT.W.S */ - std::tuple __fcvt_w_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FCVT.W.S"); - - this->gen_sync(iss::PRE_SYNC, 115); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FCVT.W.S x%1$d, f%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false), - this->gen_const(8U, fld_rm_val) - }), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(iss::POST_SYNC, 115); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 116: FCVT.WU.S */ - std::tuple __fcvt_wu_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FCVT.WU.S"); - - this->gen_sync(iss::PRE_SYNC, 116); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FCVT.WU.S x%1$d, f%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false), - this->gen_const(8U, fld_rm_val) - }), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(iss::POST_SYNC, 116); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 117: FEQ.S */ - std::tuple __feq_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FEQ.S"); - - this->gen_sync(iss::PRE_SYNC, 117); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FEQ.S x%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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("fcmp_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(iss::POST_SYNC, 117); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 118: FLT.S */ - std::tuple __flt_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FLT.S"); - - this->gen_sync(iss::PRE_SYNC, 118); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FLT.S x%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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("fcmp_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(iss::POST_SYNC, 118); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 119: FLE.S */ - std::tuple __fle_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FLE.S"); - - this->gen_sync(iss::PRE_SYNC, 119); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FLE.S x%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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("fcmp_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(iss::POST_SYNC, 119); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 120: FCLASS.S */ - std::tuple __fclass_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FCLASS.S"); - - this->gen_sync(iss::PRE_SYNC, 120); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FCLASS.S x%1$d, f%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->builder.CreateCall(this->mod->getFunction("fclass_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 120); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 121: FCVT.S.W */ - std::tuple __fcvt_s_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FCVT.S.W"); - - this->gen_sync(iss::PRE_SYNC, 121); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FCVT.S.W f%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false), - this->gen_const(8U, fld_rm_val) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 121); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 122: FCVT.S.WU */ - std::tuple __fcvt_s_wu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FCVT.S.WU"); - - this->gen_sync(iss::PRE_SYNC, 122); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FCVT.S.WU f%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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_s"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this-> get_type(32) - ), - this->gen_ext( - this->gen_const(64U, 3LL), - 32, - false), - this->gen_const(8U, fld_rm_val) - }); - if(64 == 32){ - Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 122); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 123: FMV.X.W */ - std::tuple __fmv_x_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FMV.X.W"); - - this->gen_sync(iss::PRE_SYNC, 123); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FMV.X.W x%1$d, f%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(32) - ), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 123); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 124: FMV.W.X */ - std::tuple __fmv_w_x(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FMV.W.X"); - - this->gen_sync(iss::PRE_SYNC, 124); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FMV.W.X f%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(64 == 32){ - Value* Ftmp0_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rs1_val + traits::X0, 0), - 64, - false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 124); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 125: C.FLW */ - std::tuple __c_flw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("C.FLW"); - - this->gen_sync(iss::PRE_SYNC, 125); - - uint8_t fld_rd_val = ((bit_sub<2,3>(instr))); - uint8_t fld_uimm_val = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t fld_rs1_val = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("C.FLW f(8+%1$d), %2%(x(8+%3$d))"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -6431,196 +1624,12 @@ private: pc=pc+2; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val + 8 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - 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(fld_rd_val + 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(fld_rd_val + 8 + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 125); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 126: C.FSW */ - std::tuple __c_fsw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("C.FSW"); - - this->gen_sync(iss::PRE_SYNC, 126); - - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_uimm_val = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t fld_rs1_val = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("C.FSW f(8+%1$d), %2%(x(8+%3$d))"); - ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + 8 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 126); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 127: C.FLWSP */ - std::tuple __c_flwsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("C.FLWSP"); - - this->gen_sync(iss::PRE_SYNC, 127); - - uint8_t fld_uimm_val = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("C.FLWSP f%1$d, %2%(x2)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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, fld_uimm_val)); - 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(fld_rd_val + 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(fld_rd_val + traits::F0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 127); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 128: C.FSWSP */ - std::tuple __c_fswsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("C.FSWSP"); - - this->gen_sync(iss::PRE_SYNC, 128); - - uint8_t fld_rs2_val = ((bit_sub<2,5>(instr))); - uint8_t fld_uimm_val = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("C.FSWSP f%1$d, %2%(x2), "); - ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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, fld_uimm_val)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 128); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 129: FLD */ - std::tuple __fld(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FLD"); - - this->gen_sync(iss::PRE_SYNC, 129); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FLD f%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); + 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(fld_rd_val + traits::F0), false); + 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( @@ -6628,32 +1637,354 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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(iss::POST_SYNC, 129); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 130: FSD */ - std::tuple __fsd(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FSD"); + /* 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(iss::PRE_SYNC, 130); + this->gen_sync(PRE_SYNC, 30); - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((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 */ - boost::format ins_fmter("FSD f%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->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); } @@ -6663,43 +1994,47 @@ private: Value* offs_val = this->builder.CreateAdd( this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(rs1 + traits::X0, 0), 32, true), - this->gen_const(32U, fld_imm_val)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + 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_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(iss::POST_SYNC, 130); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 131: FMADD.D */ - std::tuple __fmadd_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FMADD.D"); + /* instruction 38: FSD */ + std::tuple __fsd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FSD"); - this->gen_sync(iss::PRE_SYNC, 131); + this->gen_sync(PRE_SYNC, 38); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rs3_val = ((bit_sub<27,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))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("FMADD.D x%1$d, f%2$d, f%3$d, f%4$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -6707,17 +2042,64 @@ private: 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{ + 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(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs3_val + traits::F0, 0), + this->gen_reg_load(rs3 + traits::F0, 0), this-> get_type(64) ), this->gen_ext( @@ -6727,9 +2109,9 @@ private: this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->builder.CreateTrunc( this->gen_reg_load(traits::FCSR, 0), this-> get_type(8) @@ -6738,7 +2120,7 @@ private: }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -6746,9 +2128,9 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ }); Value* FCSR_val = this->builder.CreateAdd( this->builder.CreateAnd( @@ -6757,31 +2139,32 @@ 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(iss::POST_SYNC, 131); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 132: FMSUB.D */ - std::tuple __fmsub_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 132); + this->gen_sync(PRE_SYNC, 40); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rs3_val = ((bit_sub<27,5>(instr))); + 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 */ - boost::format ins_fmter("FMSUB.D x%1$d, f%2$d, f%3$d, f%4$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -6789,17 +2172,17 @@ private: 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{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs3_val + traits::F0, 0), + this->gen_reg_load(rs3 + traits::F0, 0), this-> get_type(64) ), this->gen_ext( @@ -6809,9 +2192,9 @@ private: this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->builder.CreateTrunc( this->gen_reg_load(traits::FCSR, 0), this-> get_type(8) @@ -6820,7 +2203,7 @@ private: }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -6828,9 +2211,9 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ }); Value* FCSR_val = this->builder.CreateAdd( this->builder.CreateAnd( @@ -6839,31 +2222,32 @@ 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(iss::POST_SYNC, 132); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 133: FNMADD.D */ - std::tuple __fnmadd_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 133); + this->gen_sync(PRE_SYNC, 41); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rs3_val = ((bit_sub<27,5>(instr))); + 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 */ - boost::format ins_fmter("FNMADD.D x%1$d, f%2$d, f%3$d, f%4$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -6871,17 +2255,17 @@ private: 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{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs3_val + traits::F0, 0), + this->gen_reg_load(rs3 + traits::F0, 0), this-> get_type(64) ), this->gen_ext( @@ -6891,9 +2275,9 @@ private: this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->builder.CreateTrunc( this->gen_reg_load(traits::FCSR, 0), this-> get_type(8) @@ -6902,7 +2286,7 @@ private: }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -6910,9 +2294,9 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ }); Value* FCSR_val = this->builder.CreateAdd( this->builder.CreateAnd( @@ -6921,31 +2305,32 @@ 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(iss::POST_SYNC, 133); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 134: FNMSUB.D */ - std::tuple __fnmsub_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 134); + this->gen_sync(PRE_SYNC, 42); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rs3_val = ((bit_sub<27,5>(instr))); + 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 */ - boost::format ins_fmter("FNMSUB.D x%1$d, f%2$d, f%3$d, f%4$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -6953,17 +2338,17 @@ private: 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{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs3_val + traits::F0, 0), + this->gen_reg_load(rs3 + traits::F0, 0), this-> get_type(64) ), this->gen_ext( @@ -6973,9 +2358,9 @@ private: this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->builder.CreateTrunc( this->gen_reg_load(traits::FCSR, 0), this-> get_type(8) @@ -6984,7 +2369,7 @@ private: }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -6992,9 +2377,9 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ }); Value* FCSR_val = this->builder.CreateAdd( this->builder.CreateAnd( @@ -7003,30 +2388,31 @@ 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(iss::POST_SYNC, 134); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 135: FADD.D */ - std::tuple __fadd_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 135); + this->gen_sync(PRE_SYNC, 43); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); + 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 */ - boost::format ins_fmter("FADD.D x%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7034,21 +2420,21 @@ private: 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{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fadd_d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + 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, fld_rm_val), + this->gen_const(8U, rm), this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->builder.CreateTrunc( this->gen_reg_load(traits::FCSR, 0), this-> get_type(8) @@ -7057,7 +2443,7 @@ private: }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -7065,9 +2451,9 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ }); Value* FCSR_val = this->builder.CreateAdd( this->builder.CreateAnd( @@ -7076,30 +2462,31 @@ 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(iss::POST_SYNC, 135); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 136: FSUB.D */ - std::tuple __fsub_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 136); + this->gen_sync(PRE_SYNC, 44); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); + 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 */ - boost::format ins_fmter("FSUB.D x%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7107,21 +2494,21 @@ private: 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{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsub_d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + 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, fld_rm_val), + this->gen_const(8U, rm), this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->builder.CreateTrunc( this->gen_reg_load(traits::FCSR, 0), this-> get_type(8) @@ -7130,7 +2517,7 @@ private: }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -7138,9 +2525,9 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ }); Value* FCSR_val = this->builder.CreateAdd( this->builder.CreateAnd( @@ -7149,30 +2536,31 @@ 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(iss::POST_SYNC, 136); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 137: FMUL.D */ - std::tuple __fmul_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 137); + this->gen_sync(PRE_SYNC, 45); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); + 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 */ - boost::format ins_fmter("FMUL.D x%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7180,21 +2568,21 @@ private: 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{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmul_d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + 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, fld_rm_val), + this->gen_const(8U, rm), this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->builder.CreateTrunc( this->gen_reg_load(traits::FCSR, 0), this-> get_type(8) @@ -7203,7 +2591,7 @@ private: }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -7211,9 +2599,9 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ }); Value* FCSR_val = this->builder.CreateAdd( this->builder.CreateAnd( @@ -7222,30 +2610,31 @@ 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(iss::POST_SYNC, 137); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 138: FDIV.D */ - std::tuple __fdiv_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 138); + this->gen_sync(PRE_SYNC, 46); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); + 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 */ - boost::format ins_fmter("FDIV.D x%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7253,21 +2642,21 @@ private: 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{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fdiv_d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + 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, fld_rm_val), + this->gen_const(8U, rm), this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->builder.CreateTrunc( this->gen_reg_load(traits::FCSR, 0), this-> get_type(8) @@ -7276,7 +2665,7 @@ private: }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -7284,9 +2673,9 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ }); Value* FCSR_val = this->builder.CreateAdd( this->builder.CreateAnd( @@ -7295,29 +2684,30 @@ 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(iss::POST_SYNC, 138); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 139: FSQRT.D */ - std::tuple __fsqrt_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 139); + this->gen_sync(PRE_SYNC, 47); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); + 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 */ - boost::format ins_fmter("FSQRT.D x%1$d, f%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7325,17 +2715,17 @@ private: 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{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsqrt_d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + 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, fld_rm_val), + this->gen_const(8U, rm), this->gen_const(8U, 7)), - this->gen_const(8U, fld_rm_val), + this->gen_const(8U, rm), this->builder.CreateTrunc( this->gen_reg_load(traits::FCSR, 0), this-> get_type(8) @@ -7344,7 +2734,7 @@ private: }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -7352,9 +2742,9 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ }); Value* FCSR_val = this->builder.CreateAdd( this->builder.CreateAnd( @@ -7363,29 +2753,30 @@ 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(iss::POST_SYNC, 139); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 140: FSGNJ.D */ - std::tuple __fsgnj_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 140); + this->gen_sync(PRE_SYNC, 48); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,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))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("FSGNJ.D f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7393,22 +2784,25 @@ private: 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(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), - this->gen_const(64U, 0x7fffffff)), + this->gen_const(64U, MSK2_val)), this->builder.CreateAnd( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), this-> get_type(64) ), - this->gen_const(64U, 0x80000000))); + this->gen_const(64U, MSK1_val))); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -7416,32 +2810,33 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 140); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 141: FSGNJN.D */ - std::tuple __fsgnjn_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 141); + this->gen_sync(PRE_SYNC, 49); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,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))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("FSGNJN.D f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7449,22 +2844,25 @@ private: 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(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), - this->gen_const(64U, 0x7fffffff)), + this->gen_const(64U, MSK2_val)), this->builder.CreateAnd( this->builder.CreateNot(this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), this-> get_type(64) )), - this->gen_const(64U, 0x80000000))); + this->gen_const(64U, MSK1_val))); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -7472,32 +2870,33 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 141); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 142: FSGNJX.D */ - std::tuple __fsgnjx_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 142); + this->gen_sync(PRE_SYNC, 50); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,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))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("FSGNJX.D f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7505,20 +2904,22 @@ private: 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(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateAnd( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), this-> get_type(64) ), - this->gen_const(64U, 0x80000000))); + this->gen_const(64U, MSK1_val))); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -7526,32 +2927,33 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 142); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 143: FMIN.D */ - std::tuple __fmin_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 143); + this->gen_sync(PRE_SYNC, 51); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,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))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("FMIN.D f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7559,13 +2961,13 @@ private: 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{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), this-> get_type(64) ), this->gen_ext( @@ -7575,7 +2977,7 @@ private: }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -7583,9 +2985,9 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ }); Value* FCSR_val = this->builder.CreateAdd( this->builder.CreateAnd( @@ -7594,29 +2996,30 @@ 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(iss::POST_SYNC, 143); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 144: FMAX.D */ - std::tuple __fmax_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 144); + this->gen_sync(PRE_SYNC, 52); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,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))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("FMAX.D f%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7624,13 +3027,13 @@ private: 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{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(64) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), this-> get_type(64) ), this->gen_ext( @@ -7640,7 +3043,7 @@ private: }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -7648,9 +3051,9 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), 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* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ }); Value* FCSR_val = this->builder.CreateAdd( this->builder.CreateAnd( @@ -7659,29 +3062,30 @@ 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(iss::POST_SYNC, 144); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, 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, llvm::BasicBlock* 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(iss::PRE_SYNC, 145); + this->gen_sync(PRE_SYNC, 53); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); + 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 */ - boost::format ins_fmter("FCVT.S.D f%1$d, f%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7689,9 +3093,9 @@ private: 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(fld_rs1_val + traits::F0, 0), - this->gen_const(8U, fld_rm_val) + 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( @@ -7702,31 +3106,32 @@ private: res_val, 64, false)); - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 145); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, 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, llvm::BasicBlock* 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(iss::PRE_SYNC, 146); + this->gen_sync(PRE_SYNC, 54); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); + 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 */ - boost::format ins_fmter("FCVT.D.S f%1$d, f%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7734,16 +3139,16 @@ private: 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{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fconv_f2d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this->gen_reg_load(rs1 + traits::F0, 0), this-> get_type(32) ), - this->gen_const(8U, fld_rm_val) + this->gen_const(8U, rm) }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -7751,231 +3156,33 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 146); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 147: FEQ.D */ - std::tuple __feq_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 147); + this->gen_sync(PRE_SYNC, 55); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,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))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("FEQ.D x%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), - }; - 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("fcmp_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 0LL), - 32, - false) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(iss::POST_SYNC, 147); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 148: FLT.D */ - std::tuple __flt_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FLT.D"); - - this->gen_sync(iss::PRE_SYNC, 148); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FLT.D x%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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("fcmp_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 2LL), - 32, - false) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(iss::POST_SYNC, 148); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 149: FLE.D */ - std::tuple __fle_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FLE.D"); - - this->gen_sync(iss::PRE_SYNC, 149); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FLE.D x%1$d, f%2$d, f%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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("fcmp_d"), std::vector{ - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), - this-> get_type(64) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + traits::F0, 0), - this-> get_type(64) - ), - this->gen_ext( - this->gen_const(64U, 1LL), - 32, - false) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(iss::POST_SYNC, 149); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 150: FCLASS.D */ - std::tuple __fclass_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FCLASS.D"); - - this->gen_sync(iss::PRE_SYNC, 150); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FCLASS.D x%1$d, f%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::F0, 0), - this-> get_type(64) - ) - }); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 150); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 151: FCVT.W.D */ - std::tuple __fcvt_w_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FCVT.W.D"); - - this->gen_sync(iss::PRE_SYNC, 151); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("FCVT.W.D x%1$d, f%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -7984,21 +3191,233 @@ private: pc=pc+4; Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_d"), std::vector{ + this->builder.CreateCall(this->mod->getFunction("fcmp_d"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + 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, fld_rm_val) + this->gen_const(8U, rm) }), 32, true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + 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( @@ -8007,29 +3426,30 @@ 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(iss::POST_SYNC, 151); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, 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, llvm::BasicBlock* 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(iss::PRE_SYNC, 152); + this->gen_sync(PRE_SYNC, 60); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); + 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 */ - boost::format ins_fmter("FCVT.WU.D x%1$d, f%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -8038,21 +3458,21 @@ private: pc=pc+4; Value* Xtmp0_val = this->gen_ext( - this->builder.CreateCall(this->mod->getFunction("fcvt_d"), std::vector{ + this->builder.CreateCall(this->mod->getFunction("fcvt_64_32"), std::vector{ this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::F0, 0), + 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, fld_rm_val) + this->gen_const(8U, rm) }), 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + 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( @@ -8061,29 +3481,30 @@ 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(iss::POST_SYNC, 152); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, 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, llvm::BasicBlock* 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(iss::PRE_SYNC, 153); + this->gen_sync(PRE_SYNC, 61); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); + 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 */ - boost::format ins_fmter("FCVT.D.W f%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -8091,20 +3512,23 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_d"), std::vector{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_32_64"), std::vector{ this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), + 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, fld_rm_val) + this->gen_const(8U, rm) }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -8112,32 +3536,33 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 153); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, 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, llvm::BasicBlock* 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(iss::PRE_SYNC, 154); + this->gen_sync(PRE_SYNC, 62); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rm_val = ((bit_sub<12,3>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); + 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 */ - boost::format ins_fmter("FCVT.D.WU f%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -8145,20 +3570,23 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_d"), std::vector{ + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_32_64"), std::vector{ this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), + 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, fld_rm_val) + this->gen_const(8U, rm) }); if(64 == 64){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); } else { uint64_t upper_val = - 1; Value* Ftmp1_val = this->builder.CreateOr( @@ -8166,199 +3594,5182 @@ private: this->gen_const(64U, upper_val), this->gen_const(64U, 64)), res_val); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 154); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 155: C.FLD */ - std::tuple __c_fld(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("C.FLD"); + /* instruction 63: LUI */ + std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LUI"); - this->gen_sync(iss::PRE_SYNC, 155); + this->gen_sync(PRE_SYNC, 63); - uint8_t fld_rd_val = ((bit_sub<2,3>(instr))); - uint8_t fld_uimm_val = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t fld_rs1_val = ((bit_sub<7,3>(instr))); + 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 */ - boost::format ins_fmter("C.FLD f(8+%1$d), %2%(x(8+%3$d))"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->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; + pc=pc+4; - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val + 8 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - 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(fld_rd_val + 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(fld_rd_val + 8 + traits::F0), false); + 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(iss::POST_SYNC, 155); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 156: C.FSD */ - std::tuple __c_fsd(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("C.FSD"); + /* instruction 64: AUIPC */ + std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("AUIPC"); - this->gen_sync(iss::PRE_SYNC, 156); + this->gen_sync(PRE_SYNC, 64); - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_uimm_val = ((bit_sub<5,2>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); - uint8_t fld_rs1_val = ((bit_sub<7,3>(instr))); + 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 */ - boost::format ins_fmter("C.FSD f(8+%1$d), %2%(x(8+%3$d))"); - ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->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; + 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, 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: JAL */ + std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("JAL"); + + this->gen_sync(PRE_SYNC, 65); + + 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, 65); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 66: BEQ */ + std::tuple __beq(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BEQ"); + + this->gen_sync(PRE_SYNC, 66); + + 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, 66); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 67: BNE */ + std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BNE"); + + this->gen_sync(PRE_SYNC, 67); + + 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, 67); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 68: BLT */ + std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BLT"); + + this->gen_sync(PRE_SYNC, 68); + + 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, 68); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 69: BGE */ + std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BGE"); + + this->gen_sync(PRE_SYNC, 69); + + 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, 69); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 70: BLTU */ + std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BLTU"); + + this->gen_sync(PRE_SYNC, 70); + + 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, 70); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 71: BGEU */ + std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BGEU"); + + this->gen_sync(PRE_SYNC, 71); + + 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, 71); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 72: LB */ + std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LB"); + + this->gen_sync(PRE_SYNC, 72); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = 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_reg_load(fld_rs1_val + 8 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - Value* MEMtmp0_val = this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + 8 + traits::F0, 0), - this-> get_type(64) - ); + 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, 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: LH */ + std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LH"); + + this->gen_sync(PRE_SYNC, 73); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = 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, 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: LW */ + std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LW"); + + this->gen_sync(PRE_SYNC, 74); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = 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, 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: LBU */ + std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LBU"); + + this->gen_sync(PRE_SYNC, 75); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 8/8), + 32, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: LHU */ + std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LHU"); + + this->gen_sync(PRE_SYNC, 76); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 16/8), + 32, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 76); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 77: SB */ + std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SB"); + + this->gen_sync(PRE_SYNC, 77); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 156); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 157: C.FLDSP */ - std::tuple __c_fldsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("C.FLDSP"); + /* instruction 78: SH */ + std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SH"); - this->gen_sync(iss::PRE_SYNC, 157); + this->gen_sync(PRE_SYNC, 78); - uint16_t fld_uimm_val = ((bit_sub<2,3>(instr) << 6) | (bit_sub<5,2>(instr) << 3) | (bit_sub<12,1>(instr) << 5)); - uint8_t fld_rd_val = ((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))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("C.FLDSP f%1$d, %2%(x2)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val; - std::vector args { + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { this->core_ptr, this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), + this->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; + pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 64/8); - if(64 == 64){ + 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, 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: SW */ + std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SW"); + + this->gen_sync(PRE_SYNC, 79); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 79); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 80: ADDI */ + std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADDI"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SLTI */ + std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTI"); + + this->gen_sync(PRE_SYNC, 81); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = 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, 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: SLTIU */ + std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTIU"); + + this->gen_sync(PRE_SYNC, 82); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = 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, 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: XORI */ + std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("XORI"); + + this->gen_sync(PRE_SYNC, 83); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = 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, 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: ORI */ + std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ORI"); + + this->gen_sync(PRE_SYNC, 84); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = 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, 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: ANDI */ + std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ANDI"); + + this->gen_sync(PRE_SYNC, 85); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = 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, 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: SLLI */ + std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLLI"); + + this->gen_sync(PRE_SYNC, 86); + + 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, 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: SRLI */ + std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRLI"); + + this->gen_sync(PRE_SYNC, 87); + + 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, 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: SRAI */ + std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRAI"); + + this->gen_sync(PRE_SYNC, 88); + + 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, 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: ADD */ + std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADD"); + + this->gen_sync(PRE_SYNC, 89); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SUB */ + std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SUB"); + + this->gen_sync(PRE_SYNC, 90); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {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, 90); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 91: SLL */ + std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLL"); + + this->gen_sync(PRE_SYNC, 91); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {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, 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: SLT */ + std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLT"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 32, true)), + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SLTU */ + std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTU"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, + false), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 32, + false)), + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: XOR */ + std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("XOR"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateXor( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SRL */ + std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRL"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateLShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::X0, 0), + this->builder.CreateSub( + this->gen_const(32U, 32), + this->gen_const(32U, 1)))); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SRA */ + std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRA"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::X0, 0), + this->builder.CreateSub( + this->gen_const(32U, 32), + this->gen_const(32U, 1)))); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: OR */ + std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("OR"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateOr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: AND */ + std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("AND"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAnd( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: FENCE */ + std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FENCE"); + + this->gen_sync(PRE_SYNC, 99); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("fence"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(32U, pred), + this->gen_const(32U, 4)), + this->gen_const(32U, succ)); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 0), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("fence_i"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->gen_const(32U, imm); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 1), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 100); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(FLUSH, nullptr); + } + + /* instruction 101: ECALL */ + std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ECALL"); + + this->gen_sync(PRE_SYNC, 101); + + 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, 101); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 102: EBREAK */ + std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("EBREAK"); + + this->gen_sync(PRE_SYNC, 102); + + 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, 102); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 103: URET */ + std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("URET"); + + this->gen_sync(PRE_SYNC, 103); + + 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, 103); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 104: SRET */ + std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRET"); + + this->gen_sync(PRE_SYNC, 104); + + 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, 104); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 105: MRET */ + std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MRET"); + + this->gen_sync(PRE_SYNC, 105); + + 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, 105); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 106: WFI */ + std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("WFI"); + + this->gen_sync(PRE_SYNC, 106); + + 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, 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: 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); + + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("sfence.vma"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->gen_const(32U, rs1); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 2), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); + Value* FENCEtmp1_val = this->gen_const(32U, rs2); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 3), + this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: CSRRW */ + std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRW"); + + this->gen_sync(PRE_SYNC, 108); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); + if(rd != 0){ + Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); + Value* CSRtmp0_val = rs_val_val; + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); + Value* Xtmp1_val = csr_val_val; + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } else { + Value* CSRtmp2_val = rs_val_val; + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(32))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: CSRRS */ + std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRS"); + + this->gen_sync(PRE_SYNC, 109); + + 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, 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: CSRRC */ + std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRC"); + + this->gen_sync(PRE_SYNC, 110); + + 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, 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: CSRRWI */ + std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRWI"); + + this->gen_sync(PRE_SYNC, 111); + + 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, 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: CSRRSI */ + std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRSI"); + + this->gen_sync(PRE_SYNC, 112); + + 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, 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: CSRRCI */ + std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRCI"); + + this->gen_sync(PRE_SYNC, 113); + + 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, 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: FLW */ + std::tuple __flw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FLW"); + + this->gen_sync(PRE_SYNC, 114); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, {imm}(x{rs1})", fmt::arg("mnemonic", "flw"), + fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); + if(64 == 32){ Value* Ftmp0_val = res_val; - this->builder.CreateStore(Ftmp0_val, get_reg_ptr(fld_rd_val + traits::F0), false); + 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_const(64U, 32)), this->gen_ext( res_val, 64, false)); - this->builder.CreateStore(Ftmp1_val, get_reg_ptr(fld_rd_val + traits::F0), false); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); } this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 157); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 158: C.FSDSP */ - std::tuple __c_fsdsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("C.FSDSP"); + /* instruction 115: FSW */ + std::tuple __fsw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FSW"); - this->gen_sync(iss::PRE_SYNC, 158); + this->gen_sync(PRE_SYNC, 115); - uint8_t fld_rs2_val = ((bit_sub<2,5>(instr))); - uint16_t fld_uimm_val = ((bit_sub<7,3>(instr) << 6) | (bit_sub<10,3>(instr) << 3)); + 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 */ - boost::format ins_fmter("C.FSDSP f%1$d, %2%(x2), "); - ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val; - std::vector args { + auto mnemonic = fmt::format( + "{mnemonic:10} f{rs2}, {imm}(x{rs1})", fmt::arg("mnemonic", "fsw"), + fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); + std::vector args { this->core_ptr, this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), + this->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; + pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); + 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(fld_rs2_val + traits::F0, 0), - this-> get_type(64) + 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(64))); + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 158); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 116: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rs3 = ((bit_sub<27,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmadd.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_reg_load(rs3 + traits::F0, 0), + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs3 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + frs1_val, + frs2_val, + frs3_val, + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rs3 = ((bit_sub<27,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fmsub.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_reg_load(rs3 + traits::F0, 0), + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs3 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + frs1_val, + frs2_val, + frs3_val, + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rs3 = ((bit_sub<27,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmadd.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_reg_load(rs3 + traits::F0, 0), + this->gen_ext( + this->gen_const(64U, 2LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs3 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + frs1_val, + frs2_val, + frs3_val, + this->gen_ext( + this->gen_const(64U, 2LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rs3 = ((bit_sub<27,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} x{rd}, f{rs1}, f{rs2}, f{rs3}", fmt::arg("mnemonic", "fnmsub.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2), fmt::arg("rs3", rs3)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_reg_load(rs3 + traits::F0, 0), + this->gen_ext( + this->gen_const(64U, 3LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* frs3_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs3 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + frs1_val, + frs2_val, + frs3_val, + this->gen_ext( + this->gen_const(64U, 3LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fadd.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fadd_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fadd_s"), std::vector{ + frs1_val, + frs2_val, + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsub.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsub_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsub_s"), std::vector{ + frs1_val, + frs2_val, + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmul.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fmul_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmul_s"), std::vector{ + frs1_val, + frs2_val, + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fdiv.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fdiv_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fdiv_s"), std::vector{ + frs1_val, + frs2_val, + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, f{rs1}", fmt::arg("mnemonic", "fsqrt.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsqrt_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsqrt_s"), std::vector{ + frs1_val, + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(8U, rm), + this->gen_const(8U, 7)), + this->gen_const(8U, rm), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnj.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateOr( + this->builder.CreateAnd( + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_const(64U, 0x7fffffff)), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_const(64U, 0x80000000))); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateOr( + this->builder.CreateAnd( + frs1_val, + this->gen_const(32U, 0x7fffffff)), + this->builder.CreateAnd( + frs2_val, + this->gen_const(32U, 0x80000000))); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjn.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateOr( + this->builder.CreateAnd( + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_const(64U, 0x7fffffff)), + this->builder.CreateAnd( + this->builder.CreateNot(this->gen_reg_load(rs2 + traits::F0, 0)), + this->gen_const(64U, 0x80000000))); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateOr( + this->builder.CreateAnd( + frs1_val, + this->gen_const(32U, 0x7fffffff)), + this->builder.CreateAnd( + this->builder.CreateNot(frs2_val), + this->gen_const(32U, 0x80000000))); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fsgnjx.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateXor( + this->gen_reg_load(rs1 + traits::F0, 0), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_const(64U, 0x80000000))); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateXor( + frs1_val, + this->builder.CreateAnd( + frs2_val, + this->gen_const(32U, 0x80000000))); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmin.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ + frs1_val, + frs2_val, + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fmax.s"), + fmt::arg("rd", rd), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ + frs1_val, + frs2_val, + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.w.s"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false), + this->gen_const(8U, rm) + }), + 32, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* Xtmp1_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + frs1_val, + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false), + this->gen_const(8U, rm) + }), + 32, + true); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fcvt.wu.s"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false), + this->gen_const(8U, rm) + }), + 32, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* Xtmp1_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + frs1_val, + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false), + this->gen_const(8U, rm) + }), + 32, + true); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "feq.s"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false) + }), + 32, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* Xtmp1_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ + frs1_val, + frs2_val, + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false) + }), + 32, + false); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "flt.s"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_ext( + this->gen_const(64U, 2LL), + 32, + false) + }), + 32, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* Xtmp1_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ + frs1_val, + frs2_val, + this->gen_ext( + this->gen_const(64U, 2LL), + 32, + false) + }), + 32, + false); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + Value* Xtmp2_val = this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 2LL), + 32, + false) + }); + this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, f{rs1}, f{rs2}", fmt::arg("mnemonic", "fle.s"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1), fmt::arg("rs2", rs2)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0), + this->gen_reg_load(rs2 + traits::F0, 0), + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false) + }), + 32, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } else { + Value* frs1_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }); + Value* frs2_val = this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs2 + traits::F0, 0) + }); + Value* Xtmp1_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ + frs1_val, + frs2_val, + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false) + }), + 32, + false); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 0x1f))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fclass.s"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* Xtmp0_val = this->builder.CreateCall(this->mod->getFunction("fclass_s"), std::vector{ + this->builder.CreateCall(this->mod->getFunction("unbox_s"), std::vector{ + this->gen_reg_load(rs1 + traits::F0, 0) + }) + }); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.w"), + fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 2LL), + 32, + false), + this->gen_const(8U, rm) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 2LL), + 32, + false), + this->gen_const(8U, rm) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rm = ((bit_sub<12,3>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fcvt.s.wu"), + fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 3LL), + 32, + false), + this->gen_const(8U, rm) + }); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 3LL), + 32, + false), + this->gen_const(8U, rm) + }); + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, f{rs1}", fmt::arg("mnemonic", "fmv.x.w"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", rs1)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::F0, 0), + this-> get_type(32) + ), + 32, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, {rs1}", fmt::arg("mnemonic", "fmv.w.x"), + fmt::arg("rd", rd), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(64 == 32){ + Value* Ftmp0_val = this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ); + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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, 140); + + 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, 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: 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, 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))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_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, 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); + 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, 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: 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, 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))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_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, 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: 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, 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))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_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, 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: 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, 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))); + 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, 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: 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, 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))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_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, 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: 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, 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))); + 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, 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: 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, 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.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, 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: 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, 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))); + 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, 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: 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, 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.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, 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: MUL */ + std::tuple __mul(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MUL"); + + 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))); + 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, 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: MULH */ + std::tuple __mulh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MULH"); + + 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))); + 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, 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: MULHSU */ + std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MULHSU"); + + this->gen_sync(PRE_SYNC, 153); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(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, 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: MULHU */ + std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MULHU"); + + 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))); + 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, 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: DIV */ + std::tuple __div(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("DIV"); + + 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))); + 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, 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: DIVU */ + std::tuple __divu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("DIVU"); + + 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))); + 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, 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: REM */ + std::tuple __rem(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("REM"); + + this->gen_sync(PRE_SYNC, 157); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(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, 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: REMU */ + std::tuple __remu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("REMU"); + + 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))); + 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, 158); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); } /**************************************************************************** * end opcode definitions ****************************************************************************/ - std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, - llvm::BasicBlock *bb) { + std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { this->gen_sync(iss::PRE_SYNC, instr_descr.size()); this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), get_reg_ptr(traits::PC), true); @@ -8370,7 +8781,7 @@ private: this->gen_raise_trap(0, 2); // illegal instruction trap this->gen_sync(iss::POST_SYNC, instr_descr.size()); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } }; @@ -8383,7 +8794,7 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm::vm_base(core, core_id, cluster_id) { +: vm_base(core, core_id, cluster_id) { qlut[0] = lut_00.data(); qlut[1] = lut_01.data(); qlut[2] = lut_10.data(); @@ -8395,27 +8806,24 @@ 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, llvm::BasicBlock *this_block) { +std::tuple +vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { // we fetch at max 4 byte, alignment is 2 + enum {TRAP_ID=1<<16}; code_word_t insn = 0; const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); - try { - uint8_t *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(1, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(1, pc.val); + auto *const data = (uint8_t *)&insn; + paddr = this->core.v2p(pc); + if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary + auto res = this->core.read(paddr, 2, data); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if ((insn & 0x3) == 0x3) { // this is a 32bit instruction + res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); } - } catch (trap_access &ta) { - throw trap_access(ta.id, pc.val); + } else { + auto res = this->core.read(paddr, 4, data); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); } if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack @@ -8428,7 +8836,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, return (this->*f)(pc, insn, this_block); } -template void vm_impl::gen_leave_behavior(llvm::BasicBlock *leave_blk) { +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)); } @@ -8440,9 +8848,7 @@ template void vm_impl::gen_raise_trap(uint16_t trap_id, ui } template void vm_impl::gen_leave_trap(unsigned lvl) { - std::vector args{ - this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, 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); @@ -8450,30 +8856,27 @@ template void vm_impl::gen_leave_trap(unsigned lvl) { } template void vm_impl::gen_wait(unsigned type) { - std::vector args{ - this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, 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(llvm::BasicBlock *trap_blk) { +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.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(llvm::BasicBlock *bb) { +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, - llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), + ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), bb, this->trap_blk, 1); } @@ -8481,10 +8884,9 @@ template inline void vm_impl::gen_trap_check(llvm::BasicBl template <> std::unique_ptr create(arch::rv32gc *core, unsigned short port, bool dump) { - std::unique_ptr> ret = - std::make_unique>(*core, dump); - if (port != 0) debugger::server::run_server(ret.get(), port); - return ret; + auto ret = new rv32gc::vm_impl(*core, dump); + if (port != 0) debugger::server::run_server(ret, port); + return std::unique_ptr(ret); } } // namespace iss diff --git a/riscv/src/internal/vm_rv32imac.cpp b/riscv/src/internal/vm_rv32imac.cpp index df40e5f..b153309 100644 --- a/riscv/src/internal/vm_rv32imac.cpp +++ b/riscv/src/internal/vm_rv32imac.cpp @@ -30,15 +30,15 @@ * *******************************************************************************/ -#include #include +#include #include #include #include -#include +#include #include -#include +#include #include #include @@ -46,7 +46,7 @@ namespace iss { namespace vm { namespace fp_impl { -void add_fp_functions_2_module(llvm::Module *, unsigned); +void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); } } @@ -54,10 +54,11 @@ namespace rv32imac { using namespace iss::arch; using namespace llvm; using namespace iss::debugger; +using namespace iss::vm::llvm; -template class vm_impl : public vm::vm_base { +template class vm_impl : public vm_base { public: - using super = typename vm::vm_base; + using super = typename iss::vm::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; @@ -71,31 +72,32 @@ public: target_adapter_if *accquire_target_adapter(server_if *srv) override { debugger_if::dbg_enabled = true; - if (vm::vm_base::tgt_adapter == nullptr) - vm::vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm::vm_base::tgt_adapter; + if (vm_base::tgt_adapter == nullptr) + vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return vm_base::tgt_adapter; } protected: - using vm::vm_base::get_reg_ptr; + using vm_base::get_reg_ptr; - template inline llvm::ConstantInt *size(T type) { - return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); + 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(llvm::Module *m) override { + void setup_module(Module* m) override { super::setup_module(m); - vm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE); + iss::vm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); } - inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, unsigned size) { + inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); } - std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, - llvm::BasicBlock *) override; + std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override; - void gen_leave_behavior(llvm::BasicBlock *leave_blk) override; + void gen_leave_behavior(BasicBlock *leave_blk) override; void gen_raise_trap(uint16_t trap_id, uint16_t cause); @@ -103,17 +105,17 @@ protected: void gen_wait(unsigned type); - void gen_trap_behavior(llvm::BasicBlock *) override; + void gen_trap_behavior(BasicBlock *) override; - void gen_trap_check(llvm::BasicBlock *bb); + void gen_trap_check(BasicBlock *bb); - inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) { + 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) { - llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); + 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); } @@ -124,17 +126,17 @@ protected: enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; using this_class = vm_impl; - using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, - code_word_t instr, - llvm::BasicBlock *bb); + using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, + code_word_t instr, + BasicBlock *bb); std::array lut; std::array lut_00, lut_01, lut_10; std::array lut_11; - std::array qlut; + std::array 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) { @@ -185,15 +187,109 @@ private: }; const std::array instr_descr = {{ - /* entries are: size, valid value, valid mask, function ptr */ + /* 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 */ @@ -290,234 +386,27 @@ 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: LUI */ - std::tuple __lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LUI"); - - this->gen_sync(iss::PRE_SYNC, 0); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - int32_t fld_imm_val = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LUI x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_const(32U, fld_imm_val); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 0); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 1: AUIPC */ - std::tuple __auipc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AUIPC"); - - this->gen_sync(iss::PRE_SYNC, 1); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - int32_t fld_imm_val = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AUIPC x%1%, 0x%2$08x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 1); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 2: JAL */ - std::tuple __jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("JAL"); - - this->gen_sync(iss::PRE_SYNC, 2); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - int32_t fld_imm_val = 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 */ - boost::format ins_fmter("JAL x%1$d, 0x%2$x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)); - 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(iss::POST_SYNC, 2); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 3: JALR */ - std::tuple __jalr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* instruction 0: JALR */ + std::tuple __jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("JALR"); - this->gen_sync(iss::PRE_SYNC, 3); + this->gen_sync(PRE_SYNC, 0); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(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 */ - boost::format ins_fmter("JALR x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -527,16 +416,16 @@ private: Value* new_pc_val = this->builder.CreateAdd( this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(rs1 + traits::X0, 0), 32, true), - this->gen_const(32U, fld_imm_val)); + this->gen_const(32U, imm)); Value* align_val = this->builder.CreateAnd( new_pc_val, - this->gen_const(32U, 0x1)); + this->gen_const(32U, 0x2)); { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + 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, @@ -551,11 +440,11 @@ private: this->builder.CreateBr(bbnext); this->builder.SetInsertPoint(bb_else); { - if(fld_rd_val != 0){ + 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(fld_rd_val + traits::X0), false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); } Value* PC_val = this->builder.CreateAnd( new_pc_val, @@ -567,3127 +456,28 @@ private: bb=bbnext; } this->builder.SetInsertPoint(bb); - this->gen_sync(iss::POST_SYNC, 3); + this->gen_sync(POST_SYNC, 0); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 4: BEQ */ - std::tuple __beq(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BEQ"); - - this->gen_sync(iss::PRE_SYNC, 4); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BEQ x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 4); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 5: BNE */ - std::tuple __bne(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BNE"); - - this->gen_sync(iss::PRE_SYNC, 5); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BNE x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 5); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 6: BLT */ - std::tuple __blt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BLT"); - - this->gen_sync(iss::PRE_SYNC, 6); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BLT x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 6); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 7: BGE */ - std::tuple __bge(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BGE"); - - this->gen_sync(iss::PRE_SYNC, 7); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BGE x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 7); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 8: BLTU */ - std::tuple __bltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BLTU"); - - this->gen_sync(iss::PRE_SYNC, 8); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BLTU x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 8); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 9: BGEU */ - std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BGEU"); - - this->gen_sync(iss::PRE_SYNC, 9); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BGEU x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, fld_imm_val)), - 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(iss::POST_SYNC, 9); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 10: LB */ - std::tuple __lb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LB"); - - this->gen_sync(iss::PRE_SYNC, 10); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LB x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 10); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 11: LH */ - std::tuple __lh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LH"); - - this->gen_sync(iss::PRE_SYNC, 11); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LH x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 11); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 12: LW */ - std::tuple __lw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LW"); - - this->gen_sync(iss::PRE_SYNC, 12); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LW x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 12); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 13: LBU */ - std::tuple __lbu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LBU"); - - this->gen_sync(iss::PRE_SYNC, 13); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LBU x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 13); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 14: LHU */ - std::tuple __lhu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LHU"); - - this->gen_sync(iss::PRE_SYNC, 14); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LHU x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 14); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 15: SB */ - std::tuple __sb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SB"); - - this->gen_sync(iss::PRE_SYNC, 15); - - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SB x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 15); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 16: SH */ - std::tuple __sh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SH"); - - this->gen_sync(iss::PRE_SYNC, 16); - - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SH x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 16); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 17: SW */ - std::tuple __sw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SW"); - - this->gen_sync(iss::PRE_SYNC, 17); - - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SW x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 17); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 18: ADDI */ - std::tuple __addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ADDI"); - - this->gen_sync(iss::PRE_SYNC, 18); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ADDI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 18); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 19: SLTI */ - std::tuple __slti(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLTI"); - - this->gen_sync(iss::PRE_SYNC, 19); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLTI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_const(32U, fld_imm_val)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 19); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 20: SLTIU */ - std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLTIU"); - - this->gen_sync(iss::PRE_SYNC, 20); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLTIU x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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 = fld_imm_val; - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(fld_rs1_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 20); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 21: XORI */ - std::tuple __xori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("XORI"); - - this->gen_sync(iss::PRE_SYNC, 21); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("XORI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 21); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 22: ORI */ - std::tuple __ori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ORI"); - - this->gen_sync(iss::PRE_SYNC, 22); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ORI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 22); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 23: ANDI */ - std::tuple __andi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ANDI"); - - this->gen_sync(iss::PRE_SYNC, 23); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ANDI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 23); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 24: SLLI */ - std::tuple __slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLLI"); - - this->gen_sync(iss::PRE_SYNC, 24); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLLI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 0); - } else { - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 24); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 25: SRLI */ - std::tuple __srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRLI"); - - this->gen_sync(iss::PRE_SYNC, 25); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRLI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 0); - } else { - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 25); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 26: SRAI */ - std::tuple __srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRAI"); - - this->gen_sync(iss::PRE_SYNC, 26); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRAI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 0); - } else { - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 26); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 27: ADD */ - std::tuple __add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ADD"); - - this->gen_sync(iss::PRE_SYNC, 27); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ADD x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 27); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 28: SUB */ - std::tuple __sub(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SUB"); - - this->gen_sync(iss::PRE_SYNC, 28); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SUB x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 28); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 29: SLL */ - std::tuple __sll(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLL"); - - this->gen_sync(iss::PRE_SYNC, 29); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLL x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - this->gen_const(32U, 0x1f))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 29); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 30: SLT */ - std::tuple __slt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLT"); - - this->gen_sync(iss::PRE_SYNC, 30); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLT x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 32, true)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 30); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 31: SLTU */ - std::tuple __sltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLTU"); - - this->gen_sync(iss::PRE_SYNC, 31); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLTU x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 32, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 32, - false)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 31); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 32: XOR */ - std::tuple __xor(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("XOR"); - - this->gen_sync(iss::PRE_SYNC, 32); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("XOR x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 32); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 33: SRL */ - std::tuple __srl(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRL"); - - this->gen_sync(iss::PRE_SYNC, 33); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRL x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - this->gen_const(32U, 0x1f))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 33); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 34: SRA */ - std::tuple __sra(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRA"); - - this->gen_sync(iss::PRE_SYNC, 34); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRA x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - this->gen_const(32U, 0x1f))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 34); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 35: OR */ - std::tuple __or(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("OR"); - - this->gen_sync(iss::PRE_SYNC, 35); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("OR x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 35); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 36: AND */ - std::tuple __and(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AND"); - - this->gen_sync(iss::PRE_SYNC, 36); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AND x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 36); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 37: FENCE */ - std::tuple __fence(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FENCE"); - - this->gen_sync(iss::PRE_SYNC, 37); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_succ_val = ((bit_sub<20,4>(instr))); - uint8_t fld_pred_val = ((bit_sub<24,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("FENCE"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(32U, fld_pred_val), - this->gen_const(32U, 4)), - this->gen_const(32U, fld_succ_val)); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 0), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 37); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 38: FENCE_I */ - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FENCE_I"); - - this->gen_sync(iss::PRE_SYNC, 38); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_imm_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("FENCE_I"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, fld_imm_val); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 1), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 38); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::FLUSH, nullptr); - } - - /* instruction 39: ECALL */ - std::tuple __ecall(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ECALL"); - - this->gen_sync(iss::PRE_SYNC, 39); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ECALL"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 11); - this->gen_sync(iss::POST_SYNC, 39); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 40: EBREAK */ - std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("EBREAK"); - - this->gen_sync(iss::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(iss::POST_SYNC, 40); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 41: URET */ - std::tuple __uret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("URET"); - - this->gen_sync(iss::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(iss::POST_SYNC, 41); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 42: SRET */ - std::tuple __sret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRET"); - - this->gen_sync(iss::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(iss::POST_SYNC, 42); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 43: MRET */ - std::tuple __mret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("MRET"); - - this->gen_sync(iss::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(iss::POST_SYNC, 43); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 44: WFI */ - std::tuple __wfi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("WFI"); - - this->gen_sync(iss::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(iss::POST_SYNC, 44); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 45: SFENCE.VMA */ - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SFENCE.VMA"); - - this->gen_sync(iss::PRE_SYNC, 45); - - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("SFENCE.VMA"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, fld_rs1_val); - 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, fld_rs2_val); - 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(iss::POST_SYNC, 45); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 46: CSRRW */ - std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRW"); - - this->gen_sync(iss::PRE_SYNC, 46); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRW x%1$d, %2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* rs_val_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, fld_csr_val), 32/8); - Value* CSRtmp0_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - Value* Xtmp1_val = csr_val_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } else { - Value* CSRtmp2_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 46); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 47: CSRRS */ - std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRS"); - - this->gen_sync(iss::PRE_SYNC, 47); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRS x%1$d, %2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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, fld_csr_val), 32/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - if(fld_rs1_val != 0){ - Value* CSRtmp1_val = this->builder.CreateOr( - xrd_val, - xrs1_val); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 47); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 48: CSRRC */ - std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRC"); - - this->gen_sync(iss::PRE_SYNC, 48); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRC x%1$d, %2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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, fld_csr_val), 32/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - if(fld_rs1_val != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - xrd_val, - this->builder.CreateNot(xrs1_val)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 48); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 49: CSRRWI */ - std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRWI"); - - this->gen_sync(iss::PRE_SYNC, 49); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_zimm_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRWI x%1$d, %2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, fld_csr_val), 32/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* CSRtmp1_val = this->gen_ext( - this->gen_const(32U, fld_zimm_val), - 32, - false); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 49); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 50: CSRRSI */ - std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRSI"); - - this->gen_sync(iss::PRE_SYNC, 50); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_zimm_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRSI x%1$d, %2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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, fld_csr_val), 32/8); - if(fld_zimm_val != 0){ - Value* CSRtmp0_val = this->builder.CreateOr( - res_val, - this->gen_ext( - this->gen_const(32U, fld_zimm_val), - 32, - false)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - } - if(fld_rd_val != 0){ - Value* Xtmp1_val = res_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 50); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 51: CSRRCI */ - std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRCI"); - - this->gen_sync(iss::PRE_SYNC, 51); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_zimm_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRCI x%1$d, %2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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, fld_csr_val), 32/8); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - if(fld_zimm_val != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - res_val, - this->builder.CreateNot(this->gen_ext( - this->gen_const(32U, fld_zimm_val), - 32, - false))); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 51); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 52: MUL */ - std::tuple __mul(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("MUL"); - - this->gen_sync(iss::PRE_SYNC, 52); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("MUL x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 128, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 128, - false)); - Value* Xtmp0_val = this->gen_ext( - res_val, - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 52); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 53: MULH */ - std::tuple __mulh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("MULH"); - - this->gen_sync(iss::PRE_SYNC, 53); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("MULH x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 128, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 53); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 54: MULHSU */ - std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("MULHSU"); - - this->gen_sync(iss::PRE_SYNC, 54); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("MULHSU x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 128, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 54); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 55: MULHU */ - std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("MULHU"); - - this->gen_sync(iss::PRE_SYNC, 55); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("MULHU x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 128, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 55); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 56: DIV */ - std::tuple __div(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("DIV"); - - this->gen_sync(iss::PRE_SYNC, 56); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("DIV x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::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(fld_rs2_val + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint32_t MMIN_val = - 1 << 32 - 1; - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 1), - 32, true), - this->gen_ext( - this->gen_const(32U, MMIN_val), - 32, true)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_const(32U, M1_val), - 32, true)), - 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(fld_rd_val + 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(fld_rs1_val + traits::X0, 3), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 3), - 32, true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + 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.CreateSDiv( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 2), - 32, true)); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp3_val = this->builder.CreateNeg(this->gen_const(32U, 1)); - this->builder.CreateStore(Xtmp3_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 56); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 57: DIVU */ - std::tuple __divu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("DIVU"); - - this->gen_sync(iss::PRE_SYNC, 57); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("DIVU x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::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(fld_rs2_val + 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_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 1), - 32, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 1), - 32, - false)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 57); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 58: REM */ - std::tuple __rem(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("REM"); - - this->gen_sync(iss::PRE_SYNC, 58); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("REM x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::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(fld_rs2_val + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint32_t MMIN_val = - 1 << 32 - 1; - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 1), - 32, true), - this->gen_ext( - this->gen_const(32U, MMIN_val), - 32, true)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_const(32U, M1_val), - 32, true)), - 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(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateURem( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 3), - 32, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 3), - 32, - true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + 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.CreateURem( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 2), - 32, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 2), - 32, - true)); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp3_val = this->gen_reg_load(fld_rs1_val + traits::X0, 1); - this->builder.CreateStore(Xtmp3_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 58); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 59: REMU */ - std::tuple __remu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("REMU"); - - this->gen_sync(iss::PRE_SYNC, 59); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("REMU x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::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(fld_rs2_val + 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_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 1), - 32, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 1), - 32, - false)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 1); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 59); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 60: LR.W */ - std::tuple __lr_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LR.W"); - - this->gen_sync(iss::PRE_SYNC, 60); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LR.W x%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* offs_val = this->gen_reg_load(fld_rs1_val + 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(fld_rd_val + 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(iss::POST_SYNC, 60); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 61: SC.W */ - std::tuple __sc_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SC.W"); - - this->gen_sync(iss::PRE_SYNC, 61); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SC.W x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_read_mem(traits::RES, offs_val, 32/8); - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::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(fld_rs2_val + 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(fld_rd_val != 0){ - Value* Xtmp1_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - res1_val, - this->gen_const(32U, 0)), - this->gen_const(32U, 0), - this->gen_const(32U, 1), - 32); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 61); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 62: AMOSWAP.W */ - std::tuple __amoswap_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOSWAP.W"); - - this->gen_sync(iss::PRE_SYNC, 62); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOSWAP.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - Value* MEMtmp1_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 62); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 63: AMOADD.W */ - std::tuple __amoadd_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOADD.W"); - - this->gen_sync(iss::PRE_SYNC, 63); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOADD.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateAdd( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 63); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 64: AMOXOR.W */ - std::tuple __amoxor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOXOR.W"); - - this->gen_sync(iss::PRE_SYNC, 64); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOXOR.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateXor( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 64); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 65: AMOAND.W */ - std::tuple __amoand_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOAND.W"); - - this->gen_sync(iss::PRE_SYNC, 65); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOAND.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateAnd( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 65); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 66: AMOOR.W */ - std::tuple __amoor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOOR.W"); - - this->gen_sync(iss::PRE_SYNC, 66); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOOR.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateOr( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 66); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 67: AMOMIN.W */ - std::tuple __amomin_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMIN.W"); - - this->gen_sync(iss::PRE_SYNC, 67); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMIN.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rs2_val + traits::X0, 0), - 32, true)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 67); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 68: AMOMAX.W */ - std::tuple __amomax_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMAX.W"); - - this->gen_sync(iss::PRE_SYNC, 68); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMAX.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rs2_val + traits::X0, 0), - 32, true)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 68); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 69: AMOMINU.W */ - std::tuple __amominu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMINU.W"); - - this->gen_sync(iss::PRE_SYNC, 69); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMINU.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - false); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGT, - res1_val, - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 69); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 70: AMOMAXU.W */ - std::tuple __amomaxu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMAXU.W"); - - this->gen_sync(iss::PRE_SYNC, 70); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMAXU.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - false); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - res1_val, - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 70); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 71: C.ADDI4SPN */ - std::tuple __c_addi4spn(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 71); + this->gen_sync(PRE_SYNC, 1); - uint8_t fld_rd_val = ((bit_sub<2,3>(instr))); - uint16_t fld_imm_val = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); + 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 */ - boost::format ins_fmter("C.ADDI4SPN x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3695,37 +485,38 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - if(fld_imm_val == 0){ + 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, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 8 + traits::X0), false); + 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(iss::POST_SYNC, 71); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 72: C.LW */ - std::tuple __c_lw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 72); + this->gen_sync(PRE_SYNC, 2); - uint8_t fld_rd_val = ((bit_sub<2,3>(instr))); - uint8_t fld_uimm_val = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t fld_rs1_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.LW x(8+%1$d), x(8+%2$d), 0x%3$05x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_uimm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3734,34 +525,38 @@ private: pc=pc+2; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val + 8 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - Value* Xtmp0_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 8 + traits::X0), false); + 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(iss::POST_SYNC, 72); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 73: C.SW */ - std::tuple __c_sw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 73); + this->gen_sync(PRE_SYNC, 3); - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_uimm_val = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t fld_rs1_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.SW x(8+%1$d), x(8+%2$d), 0x%3$05x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3770,36 +565,37 @@ private: pc=pc+2; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val + 8 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 8 + traits::X0, 0); + 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(iss::POST_SYNC, 73); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 74: C.ADDI */ - std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 74); + this->gen_sync(PRE_SYNC, 4); - int8_t fld_imm_val = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<7,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 */ - boost::format ins_fmter("C.ADDI x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3809,29 +605,29 @@ private: Value* Xtmp0_val = this->builder.CreateAdd( this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(rs1 + traits::X0, 0), 32, true), - this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rs1_val + traits::X0), false); + 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(iss::POST_SYNC, 74); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 75: C.NOP */ - std::tuple __c_nop(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 75); + this->gen_sync(PRE_SYNC, 5); if(this->disass_enabled){ /* generate console output when executing the command */ - std::vector args { + std::vector args { this->core_ptr, this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("C.NOP"), + this->builder.CreateGlobalStringPtr("c.nop"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3841,27 +637,28 @@ private: /* TODO: describe operations for C.NOP ! */ this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 75); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 76: C.JAL */ - std::tuple __c_jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 76); + this->gen_sync(PRE_SYNC, 6); - int16_t fld_imm_val = 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<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 */ - boost::format ins_fmter("C.JAL 0x%1$05x"); - ins_fmter % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3877,31 +674,32 @@ private: this->gen_ext( cur_pc_val, 32, true), - this->gen_const(32U, fld_imm_val)); + 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(iss::POST_SYNC, 76); + this->gen_sync(POST_SYNC, 6); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 77: C.LI */ - std::tuple __c_li(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 77); + this->gen_sync(PRE_SYNC, 7); - int8_t fld_imm_val = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); + 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 */ - boost::format ins_fmter("C.LI x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3909,34 +707,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - if(fld_rd_val == 0){ + if(rd == 0){ this->gen_raise_trap(0, 2); } - Value* Xtmp0_val = this->gen_const(32U, fld_imm_val); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); + 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(iss::POST_SYNC, 77); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 78: C.LUI */ - std::tuple __c_lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 78); + this->gen_sync(PRE_SYNC, 8); - int32_t fld_imm_val = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); + 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 */ - boost::format ins_fmter("C.LUI x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3944,36 +743,37 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - if(fld_rd_val == 0){ + if(rd == 0){ this->gen_raise_trap(0, 2); } - if(fld_imm_val == 0){ + if(imm == 0){ this->gen_raise_trap(0, 2); } - Value* Xtmp0_val = this->gen_const(32U, fld_imm_val); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); + 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(iss::POST_SYNC, 78); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 79: C.ADDI16SP */ - std::tuple __c_addi16sp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 79); + this->gen_sync(PRE_SYNC, 9); - int16_t fld_imm_val = 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<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 */ - boost::format ins_fmter("C.ADDI16SP 0x%1$05x"); - ins_fmter % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -3985,31 +785,32 @@ private: this->gen_ext( this->gen_reg_load(2 + traits::X0, 0), 32, true), - this->gen_const(32U, fld_imm_val)); + 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(iss::POST_SYNC, 79); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 80: C.SRLI */ - std::tuple __c_srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 80); + this->gen_sync(PRE_SYNC, 10); - uint8_t fld_shamt_val = ((bit_sub<2,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.SRLI x(8+%1$d), %2$d"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4017,34 +818,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rs1_idx_val = fld_rs1_val + 8; + 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, fld_shamt_val)); + 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(iss::POST_SYNC, 80); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 81: C.SRAI */ - std::tuple __c_srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 81); + this->gen_sync(PRE_SYNC, 11); - uint8_t fld_shamt_val = ((bit_sub<2,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.SRAI x(8+%1$d), %2$d"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4052,34 +854,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rs1_idx_val = fld_rs1_val + 8; + 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, fld_shamt_val)); + 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(iss::POST_SYNC, 81); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 82: C.ANDI */ - std::tuple __c_andi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 82); + this->gen_sync(PRE_SYNC, 12); - uint8_t fld_imm_val = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.ANDI x(8+%1$d), 0x%2$05x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4087,34 +890,37 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rs1_idx_val = fld_rs1_val + 8; + uint8_t rs1_idx_val = rs1 + 8; Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(32U, fld_imm_val)); + 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(iss::POST_SYNC, 82); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 83: C.SUB */ - std::tuple __c_sub(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 83); + this->gen_sync(PRE_SYNC, 13); - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.SUB x(8+%1$d), x(8+%2$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4122,34 +928,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rd_idx_val = fld_rd_val + 8; + 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(fld_rs2_val + 8 + 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(iss::POST_SYNC, 83); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 84: C.XOR */ - std::tuple __c_xor(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 84); + this->gen_sync(PRE_SYNC, 14); - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.XOR x(8+%1$d), x(8+%2$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4157,34 +964,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rd_idx_val = fld_rd_val + 8; + 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(fld_rs2_val + 8 + 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(iss::POST_SYNC, 84); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 85: C.OR */ - std::tuple __c_or(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 85); + this->gen_sync(PRE_SYNC, 15); - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.OR x(8+%1$d), x(8+%2$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4192,34 +1000,35 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rd_idx_val = fld_rd_val + 8; + 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(fld_rs2_val + 8 + 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(iss::POST_SYNC, 85); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 86: C.AND */ - std::tuple __c_and(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 86); + this->gen_sync(PRE_SYNC, 16); - uint8_t fld_rs2_val = ((bit_sub<2,3>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,3>(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 */ - boost::format ins_fmter("C.AND x(8+%1$d), x(8+%2$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4227,33 +1036,34 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - uint8_t rd_idx_val = fld_rd_val + 8; + 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(fld_rs2_val + 8 + 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(iss::POST_SYNC, 86); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 87: C.J */ - std::tuple __c_j(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 87); + this->gen_sync(PRE_SYNC, 17); - int16_t fld_imm_val = 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<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 */ - boost::format ins_fmter("C.J 0x%1$05x"); - ins_fmter % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4265,31 +1075,32 @@ private: this->gen_ext( cur_pc_val, 32, true), - this->gen_const(32U, fld_imm_val)); + 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(iss::POST_SYNC, 87); + this->gen_sync(POST_SYNC, 17); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 88: C.BEQZ */ - std::tuple __c_beqz(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 88); + this->gen_sync(PRE_SYNC, 18); - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<7,3>(instr))); + 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 */ - boost::format ins_fmter("C.BEQZ x(8+%1$d), 0x%2$05x"); - ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4300,13 +1111,13 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_EQ, - this->gen_reg_load(fld_rs1_val + 8 + traits::X0, 0), + 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, fld_imm_val)), + this->gen_const(32U, imm)), this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, 2)), @@ -4314,27 +1125,28 @@ 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(iss::POST_SYNC, 88); + this->gen_sync(POST_SYNC, 18); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 89: C.BNEZ */ - std::tuple __c_bnez(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 89); + this->gen_sync(PRE_SYNC, 19); - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<7,3>(instr))); + 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 */ - boost::format ins_fmter("C.BNEZ x(8+%1$d), 0x%2$05x"); - ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4345,13 +1157,13 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_NE, - this->gen_reg_load(fld_rs1_val + 8 + traits::X0, 0), + 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, fld_imm_val)), + this->gen_const(32U, imm)), this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, 2)), @@ -4359,27 +1171,28 @@ 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(iss::POST_SYNC, 89); + this->gen_sync(POST_SYNC, 19); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 90: C.SLLI */ - std::tuple __c_slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 90); + this->gen_sync(PRE_SYNC, 20); - uint8_t fld_shamt_val = ((bit_sub<2,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<7,5>(instr))); + 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 */ - boost::format ins_fmter("C.SLLI x%1$d, %2$d"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4387,36 +1200,37 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - if(fld_rs1_val == 0){ + if(rs1 == 0){ this->gen_raise_trap(0, 2); } Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rs1_val + traits::X0), false); + 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(iss::POST_SYNC, 90); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 91: C.LWSP */ - std::tuple __c_lwsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 91); + this->gen_sync(PRE_SYNC, 21); - uint8_t fld_uimm_val = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); + 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 */ - boost::format ins_fmter("C.LWSP x%1$d, sp, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4426,32 +1240,36 @@ private: Value* offs_val = this->builder.CreateAdd( this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - Value* Xtmp0_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); + 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(iss::POST_SYNC, 91); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 92: C.MV */ - std::tuple __c_mv(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 92); + this->gen_sync(PRE_SYNC, 22); - uint8_t fld_rs2_val = ((bit_sub<2,5>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,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 */ - boost::format ins_fmter("C.MV x%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4459,30 +1277,31 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - Value* Xtmp0_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); + 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(iss::POST_SYNC, 92); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 93: C.JR */ - std::tuple __c_jr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 93); + this->gen_sync(PRE_SYNC, 23); - uint8_t fld_rs1_val = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("C.JR x%1$d"); - ins_fmter % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4490,30 +1309,31 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - Value* PC_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + 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(iss::POST_SYNC, 93); + this->gen_sync(POST_SYNC, 23); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 94: C.ADD */ - std::tuple __c_add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 94); + this->gen_sync(PRE_SYNC, 24); - uint8_t fld_rs2_val = ((bit_sub<2,5>(instr))); - uint8_t fld_rd_val = ((bit_sub<7,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 */ - boost::format ins_fmter("C.ADD x%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4522,31 +1342,32 @@ private: pc=pc+2; Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rd_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); + 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(iss::POST_SYNC, 94); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 95: C.JALR */ - std::tuple __c_jalr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* 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(iss::PRE_SYNC, 95); + this->gen_sync(PRE_SYNC, 25); - uint8_t fld_rs1_val = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - boost::format ins_fmter("C.JALR x%1$d"); - ins_fmter % (uint64_t)fld_rs1_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4558,26 +1379,26 @@ private: 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(fld_rs1_val + traits::X0, 0); + 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(iss::POST_SYNC, 95); + this->gen_sync(POST_SYNC, 25); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 96: C.EBREAK */ - std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 96); + this->gen_sync(PRE_SYNC, 26); if(this->disass_enabled){ /* generate console output when executing the command */ - std::vector args { + std::vector args { this->core_ptr, this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("C.EBREAK"), + this->builder.CreateGlobalStringPtr("c.ebreak"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4586,27 +1407,28 @@ private: pc=pc+2; this->gen_raise_trap(0, 3); - this->gen_sync(iss::POST_SYNC, 96); + this->gen_sync(POST_SYNC, 26); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } - /* instruction 97: C.SWSP */ - std::tuple __c_swsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* 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(iss::PRE_SYNC, 97); + this->gen_sync(PRE_SYNC, 27); - uint8_t fld_rs2_val = ((bit_sub<2,5>(instr))); - uint8_t fld_uimm_val = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); + 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 */ - boost::format ins_fmter("C.SWSP x2+0x%1$05x, x%2$d"); - ins_fmter % (uint64_t)fld_uimm_val % (uint64_t)fld_rs2_val; - std::vector args { + 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(ins_fmter.str()), + this->builder.CreateGlobalStringPtr(mnemonic), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4616,31 +1438,31 @@ private: Value* offs_val = this->builder.CreateAdd( this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, fld_uimm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 97); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, bb); + return std::make_tuple(CONT, bb); } - /* instruction 98: DII */ - std::tuple __dii(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + /* instruction 28: DII */ + std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ bb->setName("DII"); - this->gen_sync(iss::PRE_SYNC, 98); + this->gen_sync(PRE_SYNC, 28); if(this->disass_enabled){ /* generate console output when executing the command */ - std::vector args { + std::vector args { this->core_ptr, this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("DII"), + this->builder.CreateGlobalStringPtr("dii"), }; this->builder.CreateCall(this->mod->getFunction("print_disass"), args); } @@ -4650,29 +1472,3240 @@ private: this->gen_raise_trap(0, 2); this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 98); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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(vm::CONT, 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); + + 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, 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: 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, 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))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_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, 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: 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, 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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.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, 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: 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, 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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.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, 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: 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, 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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.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, 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: 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, 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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.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, 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: 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, 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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.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, 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: 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, 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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.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, 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: 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, 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))); + 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, 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: 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, 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))); + 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, 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: 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, 39); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_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, 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: MUL */ + std::tuple __mul(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MUL"); + + this->gen_sync(PRE_SYNC, 40); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(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, 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: MULH */ + std::tuple __mulh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MULH"); + + this->gen_sync(PRE_SYNC, 41); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(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, 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: MULHSU */ + std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MULHSU"); + + this->gen_sync(PRE_SYNC, 42); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(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, 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: MULHU */ + std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MULHU"); + + this->gen_sync(PRE_SYNC, 43); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(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, 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: DIV */ + std::tuple __div(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("DIV"); + + this->gen_sync(PRE_SYNC, 44); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(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, 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: DIVU */ + std::tuple __divu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("DIVU"); + + this->gen_sync(PRE_SYNC, 45); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "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, 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: REM */ + std::tuple __rem(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("REM"); + + this->gen_sync(PRE_SYNC, 46); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "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, 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: REMU */ + std::tuple __remu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("REMU"); + + this->gen_sync(PRE_SYNC, 47); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "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, 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"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 8/8), + 32, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: LHU */ + std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LHU"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 16/8), + 32, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SB */ + std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SB"); + + this->gen_sync(PRE_SYNC, 62); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SH */ + std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SH"); + + this->gen_sync(PRE_SYNC, 63); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(16))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SW */ + std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SW"); + + this->gen_sync(PRE_SYNC, 64); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: ADDI */ + std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADDI"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_const(32U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SLTI */ + std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTI"); + + 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))); + 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, 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: SLTIU */ + std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTIU"); + + 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))); + 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, 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: XORI */ + std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("XORI"); + + 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))); + 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, 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: ORI */ + std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ORI"); + + 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))); + 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, 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: ANDI */ + std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ANDI"); + + 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))); + 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, 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: SLLI */ + std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLLI"); + + 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))); + 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, 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: SRLI */ + std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRLI"); + + 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))); + 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, 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: SRAI */ + std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRAI"); + + 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))); + 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, 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: ADD */ + std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADD"); + + this->gen_sync(PRE_SYNC, 74); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SUB */ + std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SUB"); + + 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.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, 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: SLL */ + std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLL"); + + this->gen_sync(PRE_SYNC, 76); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "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, 76); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 77: SLT */ + std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLT"); + + this->gen_sync(PRE_SYNC, 77); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 32, true)), + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SLTU */ + std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTU"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 32, + false), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 32, + false)), + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: XOR */ + std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("XOR"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateXor( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 79); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 80: SRL */ + std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRL"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateLShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::X0, 0), + this->builder.CreateSub( + this->gen_const(32U, 32), + this->gen_const(32U, 1)))); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SRA */ + std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRA"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::X0, 0), + this->builder.CreateSub( + this->gen_const(32U, 32), + this->gen_const(32U, 1)))); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: OR */ + std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("OR"); + + this->gen_sync(PRE_SYNC, 82); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateOr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: AND */ + std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("AND"); + + this->gen_sync(PRE_SYNC, 83); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAnd( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: FENCE */ + std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FENCE"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("fence"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(32U, pred), + this->gen_const(32U, 4)), + this->gen_const(32U, succ)); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 0), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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, 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("fence_i"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->gen_const(32U, imm); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 1), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 85); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(FLUSH, nullptr); + } + + /* instruction 86: ECALL */ + std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ECALL"); + + this->gen_sync(PRE_SYNC, 86); + + 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, 86); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 87: EBREAK */ + std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("EBREAK"); + + this->gen_sync(PRE_SYNC, 87); + + 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, 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"); + + this->gen_sync(PRE_SYNC, 88); + + 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, 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"); + + this->gen_sync(PRE_SYNC, 89); + + 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, 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"); + + this->gen_sync(PRE_SYNC, 90); + + 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, 90); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 91: WFI */ + std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("WFI"); + + this->gen_sync(PRE_SYNC, 91); + + 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, 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: 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, 92); + + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("sfence.vma"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->gen_const(32U, rs1); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 2), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); + Value* FENCEtmp1_val = this->gen_const(32U, rs2); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 3), + this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: CSRRW */ + std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRW"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); + if(rd != 0){ + Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); + Value* CSRtmp0_val = rs_val_val; + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); + Value* Xtmp1_val = csr_val_val; + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } else { + Value* CSRtmp2_val = rs_val_val; + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(32))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: CSRRS */ + std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRS"); + + this->gen_sync(PRE_SYNC, 94); + + 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, 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: CSRRC */ + std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRC"); + + 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))); + 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, 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: CSRRWI */ + std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRWI"); + + 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.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, 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: CSRRSI */ + std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRSI"); + + 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))); + 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, 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: CSRRCI */ + std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRCI"); + + 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.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, 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); } /**************************************************************************** * end opcode definitions ****************************************************************************/ - std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, - llvm::BasicBlock *bb) { - this->gen_sync(iss::PRE_SYNC, instr_descr.size()); + std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { + this->gen_sync(iss::PRE_SYNC, instr_descr.size()); this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); + 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)), + this->gen_const(64U, 1)), get_reg_ptr(traits::ICOUNT), true); pc = pc + ((instr & 3) == 3 ? 4 : 2); - this->gen_raise_trap(0, 2); // illegal instruction trap - this->gen_sync(iss::POST_SYNC, instr_descr.size()); + this->gen_raise_trap(0, 2); // illegal instruction trap + this->gen_sync(iss::POST_SYNC, instr_descr.size()); this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); + return std::make_tuple(BRANCH, nullptr); } }; @@ -4685,7 +4718,7 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm::vm_base(core, core_id, cluster_id) { +: vm_base(core, core_id, cluster_id) { qlut[0] = lut_00.data(); qlut[1] = lut_01.data(); qlut[2] = lut_10.data(); @@ -4697,29 +4730,26 @@ 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, llvm::BasicBlock *this_block) { +std::tuple +vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { // we fetch at max 4 byte, alignment is 2 + enum {TRAP_ID=1<<16}; code_word_t insn = 0; const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); - try { - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(1, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(1, pc.val); + auto *const data = (uint8_t *)&insn; + paddr = this->core.v2p(pc); + if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary + auto res = this->core.read(paddr, 2, data); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if ((insn & 0x3) == 0x3) { // this is a 32bit instruction + res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); } - } catch (trap_access &ta) { - throw trap_access(ta.id, pc.val); + } else { + auto res = this->core.read(paddr, 4, data); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); } - if (insn == 0x0000006f || (insn & 0xffff) == 0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; auto lut_val = extract_fields(insn); @@ -4730,7 +4760,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, return (this->*f)(pc, insn, this_block); } -template void vm_impl::gen_leave_behavior(llvm::BasicBlock *leave_blk) { +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)); } @@ -4738,51 +4768,46 @@ template void vm_impl::gen_leave_behavior(llvm::BasicBlock 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); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_leave_trap(unsigned lvl) { - std::vector args{ - this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, 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); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_wait(unsigned type) { - std::vector args{ - this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, 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(llvm::BasicBlock *trap_blk) { +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))}; + 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(llvm::BasicBlock *bb) { +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, - llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), + ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), bb, this->trap_blk, 1); } } // namespace rv32imac -template <> std::unique_ptr create(arch::rv32imac *core, unsigned short port, bool dump) { +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); diff --git a/riscv/src/internal/vm_rv64gc.cpp b/riscv/src/internal/vm_rv64gc.cpp new file mode 100644 index 0000000..451efa7 --- /dev/null +++ b/riscv/src/internal/vm_rv64gc.cpp @@ -0,0 +1,11368 @@ +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace iss { +namespace vm { +namespace fp_impl { +void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); +} +} + +namespace rv64gc { +using namespace iss::arch; +using namespace llvm; +using namespace iss::debugger; +using namespace iss::vm::llvm; + +template class vm_impl : public vm_base { +public: + using super = typename iss::vm::llvm::vm_base; + using virt_addr_t = typename super::virt_addr_t; + using phys_addr_t = typename super::phys_addr_t; + using code_word_t = typename super::code_word_t; + using addr_t = typename super::addr_t; + + vm_impl(); + + vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); + + void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } + + target_adapter_if *accquire_target_adapter(server_if *srv) override { + debugger_if::dbg_enabled = true; + if (vm_base::tgt_adapter == nullptr) + vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return vm_base::tgt_adapter; + } + +protected: + using vm_base::get_reg_ptr; + + inline const char *name(size_t index){return traits::reg_aliases.at(index);} + + template inline ConstantInt *size(T type) { + return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); + } + + void setup_module(Module* m) override { + super::setup_module(m); + iss::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)); + } + + std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override; + + void gen_leave_behavior(BasicBlock *leave_blk) override; + + void gen_raise_trap(uint16_t trap_id, uint16_t cause); + + void gen_leave_trap(unsigned lvl); + + void gen_wait(unsigned type); + + void gen_trap_behavior(BasicBlock *) override; + + void gen_trap_check(BasicBlock *bb); + + inline Value *gen_reg_load(unsigned i, unsigned level = 0) { + return this->builder.CreateLoad(get_reg_ptr(i), false); + } + + inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { + Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), + this->get_type(traits::XLEN)); + this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); + } + + // some compile time constants + // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; + enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; + enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; + enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + + using this_class = vm_impl; + using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, + code_word_t instr, + BasicBlock *bb); + std::array lut; + + std::array lut_00, lut_01, lut_10; + std::array lut_11; + + std::array qlut; + + std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; + + void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], + compile_func f) { + if (pos < 0) { + lut[idx] = f; + } else { + auto bitmask = 1UL << pos; + if ((mask & bitmask) == 0) { + expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); + } else { + if ((valid & bitmask) == 0) { + expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); + expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); + } else { + auto new_val = idx << 1; + if ((value & bitmask) != 0) new_val++; + expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); + } + } + } + } + + inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } + + uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { + if (pos >= 0) { + auto bitmask = 1UL << pos; + if ((mask & bitmask) == 0) { + lut_val = extract_fields(pos - 1, val, mask, lut_val); + } else { + auto new_val = lut_val << 1; + if ((val & bitmask) != 0) new_val++; + lut_val = extract_fields(pos - 1, val, mask, new_val); + } + } + return lut_val; + } + +private: + /**************************************************************************** + * start opcode definitions + ****************************************************************************/ + struct InstructionDesriptor { + size_t length; + uint32_t value; + uint32_t mask; + compile_func op; + }; + + const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */ + /* instruction 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 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 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 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 */ + std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LUI"); + + this->gen_sync(PRE_SYNC, 76); + + uint8_t rd = ((bit_sub<7,5>(instr))); + int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_const(64U, imm); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 76); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 77: AUIPC */ + std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("AUIPC"); + + this->gen_sync(PRE_SYNC, 77); + + uint8_t rd = ((bit_sub<7,5>(instr))); + int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: JAL */ + std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("JAL"); + + this->gen_sync(PRE_SYNC, 78); + + uint8_t rd = ((bit_sub<7,5>(instr))); + int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + Value* PC_val = this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 78); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 79: BEQ */ + std::tuple __beq(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BEQ"); + + this->gen_sync(PRE_SYNC, 79); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 79); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 80: BNE */ + std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BNE"); + + this->gen_sync(PRE_SYNC, 80); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 80); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 81: BLT */ + std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BLT"); + + this->gen_sync(PRE_SYNC, 81); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 64, true)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 81); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 82: BGE */ + std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BGE"); + + this->gen_sync(PRE_SYNC, 82); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SGE, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 64, true)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 82); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 83: BLTU */ + std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BLTU"); + + this->gen_sync(PRE_SYNC, 83); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 83); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 84: BGEU */ + std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BGEU"); + + this->gen_sync(PRE_SYNC, 84); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_UGE, + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 84); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 85: LB */ + std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LB"); + + this->gen_sync(PRE_SYNC, 85); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 8/8), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: LH */ + std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LH"); + + this->gen_sync(PRE_SYNC, 86); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 16/8), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: LW */ + std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LW"); + + this->gen_sync(PRE_SYNC, 87); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: LBU */ + std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LBU"); + + this->gen_sync(PRE_SYNC, 88); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 8/8), + 64, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: LHU */ + std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LHU"); + + this->gen_sync(PRE_SYNC, 89); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 16/8), + 64, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SB */ + std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SB"); + + this->gen_sync(PRE_SYNC, 90); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 90); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 91: SH */ + std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SH"); + + this->gen_sync(PRE_SYNC, 91); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(16))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SW */ + std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SW"); + + this->gen_sync(PRE_SYNC, 92); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: ADDI */ + std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADDI"); + + this->gen_sync(PRE_SYNC, 93); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SLTI */ + std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTI"); + + this->gen_sync(PRE_SYNC, 94); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)), + this->gen_const(64U, 1), + this->gen_const(64U, 0), + 64); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SLTIU */ + std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTIU"); + + this->gen_sync(PRE_SYNC, 95); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + int64_t full_imm_val = imm; + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_const(64U, full_imm_val)), + this->gen_const(64U, 1), + this->gen_const(64U, 0), + 64); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: XORI */ + std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("XORI"); + + this->gen_sync(PRE_SYNC, 96); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateXor( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: ORI */ + std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ORI"); + + this->gen_sync(PRE_SYNC, 97); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateOr( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: ANDI */ + std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ANDI"); + + this->gen_sync(PRE_SYNC, 98); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAnd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SLLI */ + std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLLI"); + + this->gen_sync(PRE_SYNC, 99); + + 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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateShl( + this->gen_reg_load(rs1 + traits::X0, 0), + this->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); + bb = BasicBlock::Create(this->mod->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 */ + std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRLI"); + + this->gen_sync(PRE_SYNC, 100); + + 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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateLShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->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); + bb = BasicBlock::Create(this->mod->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 */ + std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRAI"); + + this->gen_sync(PRE_SYNC, 101); + + 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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->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); + bb = BasicBlock::Create(this->mod->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 */ + std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADD"); + + this->gen_sync(PRE_SYNC, 102); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SUB */ + std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SUB"); + + this->gen_sync(PRE_SYNC, 103); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateSub( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SLL */ + std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLL"); + + this->gen_sync(PRE_SYNC, 104); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateShl( + this->gen_reg_load(rs1 + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::X0, 0), + this->builder.CreateSub( + this->gen_const(64U, 64), + this->gen_const(64U, 1)))); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SLT */ + std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLT"); + + this->gen_sync(PRE_SYNC, 105); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 64, true)), + this->gen_const(64U, 1), + this->gen_const(64U, 0), + 64); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SLTU */ + std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTU"); + + this->gen_sync(PRE_SYNC, 106); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, + false), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 64, + false)), + this->gen_const(64U, 1), + this->gen_const(64U, 0), + 64); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: XOR */ + std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("XOR"); + + this->gen_sync(PRE_SYNC, 107); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateXor( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SRL */ + std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRL"); + + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateLShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::X0, 0), + this->builder.CreateSub( + this->gen_const(64U, 64), + this->gen_const(64U, 1)))); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SRA */ + std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRA"); + + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::X0, 0), + this->builder.CreateSub( + this->gen_const(64U, 64), + this->gen_const(64U, 1)))); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: OR */ + std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("OR"); + + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateOr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: AND */ + std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("AND"); + + 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} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAnd( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: FENCE */ + std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FENCE"); + + this->gen_sync(PRE_SYNC, 112); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("fence"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, pred), + this->gen_const(64U, 4)), + this->gen_const(64U, succ)); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 0), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("fence_i"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->gen_const(64U, imm); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 1), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 113); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(FLUSH, nullptr); + } + + /* instruction 114: ECALL */ + std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ECALL"); + + this->gen_sync(PRE_SYNC, 114); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("ecall"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_raise_trap(0, 11); + this->gen_sync(POST_SYNC, 114); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 115: EBREAK */ + std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("EBREAK"); + + this->gen_sync(PRE_SYNC, 115); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("ebreak"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_raise_trap(0, 3); + this->gen_sync(POST_SYNC, 115); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 116: URET */ + std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("URET"); + + this->gen_sync(PRE_SYNC, 116); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("uret"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_leave_trap(0); + this->gen_sync(POST_SYNC, 116); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 117: SRET */ + std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRET"); + + this->gen_sync(PRE_SYNC, 117); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("sret"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_leave_trap(1); + this->gen_sync(POST_SYNC, 117); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 118: MRET */ + std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MRET"); + + this->gen_sync(PRE_SYNC, 118); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("mret"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_leave_trap(3); + this->gen_sync(POST_SYNC, 118); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 119: WFI */ + std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("WFI"); + + this->gen_sync(PRE_SYNC, 119); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("wfi"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_wait(1); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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); + + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("sfence.vma"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->gen_const(64U, rs1); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 2), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); + Value* FENCEtmp1_val = this->gen_const(64U, rs2); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 3), + this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: CSRRW */ + std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRW"); + + this->gen_sync(PRE_SYNC, 121); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); + if(rd != 0){ + Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* CSRtmp0_val = rs_val_val; + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(64))); + Value* Xtmp1_val = csr_val_val; + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } else { + Value* CSRtmp2_val = rs_val_val; + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(64))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: CSRRS */ + std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRS"); + + this->gen_sync(PRE_SYNC, 122); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); + if(rd != 0){ + Value* Xtmp0_val = xrd_val; + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + if(rs1 != 0){ + Value* CSRtmp1_val = this->builder.CreateOr( + xrd_val, + xrs1_val); + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: CSRRC */ + std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRC"); + + this->gen_sync(PRE_SYNC, 123); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); + if(rd != 0){ + Value* Xtmp0_val = xrd_val; + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + if(rs1 != 0){ + Value* CSRtmp1_val = this->builder.CreateAnd( + xrd_val, + this->builder.CreateNot(xrs1_val)); + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: CSRRWI */ + std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRWI"); + + this->gen_sync(PRE_SYNC, 124); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + Value* CSRtmp1_val = this->gen_ext( + this->gen_const(64U, zimm), + 64, + false); + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: CSRRSI */ + std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRSI"); + + this->gen_sync(PRE_SYNC, 125); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + if(zimm != 0){ + Value* CSRtmp0_val = this->builder.CreateOr( + res_val, + this->gen_ext( + this->gen_const(64U, zimm), + 64, + false)); + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(64))); + } + if(rd != 0){ + Value* Xtmp1_val = res_val; + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: CSRRCI */ + std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRCI"); + + this->gen_sync(PRE_SYNC, 126); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + if(rd != 0){ + Value* Xtmp0_val = res_val; + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + if(zimm != 0){ + Value* CSRtmp1_val = this->builder.CreateAnd( + res_val, + this->builder.CreateNot(this->gen_ext( + this->gen_const(64U, zimm), + 64, + false))); + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: FLW */ + std::tuple __flw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FLW"); + + this->gen_sync(PRE_SYNC, 127); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rd}, {imm}(x{rs1})", fmt::arg("mnemonic", "flw"), + fmt::arg("rd", rd), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); + if(64 == 32){ + Value* Ftmp0_val = res_val; + this->builder.CreateStore(Ftmp0_val, get_reg_ptr(rd + traits::F0), false); + } else { + uint64_t upper_val = - 1; + Value* Ftmp1_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, upper_val), + this->gen_const(64U, 32)), + this->gen_ext( + res_val, + 64, + false)); + this->builder.CreateStore(Ftmp1_val, get_reg_ptr(rd + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: FSW */ + std::tuple __fsw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FSW"); + + this->gen_sync(PRE_SYNC, 128); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} f{rs2}, {imm}(x{rs1})", fmt::arg("mnemonic", "fsw"), + fmt::arg("rs2", rs2), fmt::arg("imm", imm), fmt::arg("rs1", rs1)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + Value* MEMtmp0_val = this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::F0, 0), + this-> get_type(32) + ); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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, 129); + + 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, 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)), + 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, 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.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, 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); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}", fmt::arg("mnemonic", "lr.w"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + Value* REStmp1_val = this->gen_ext( + this->builder.CreateNeg(this->gen_const(8U, 1)), + 32, + true); + this->gen_write_mem( + traits::RES, + offs_val, + this->builder.CreateZExtOrTrunc(REStmp1_val,this->get_type(32))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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, 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 rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_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, 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( + 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); + 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, 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: 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, 169); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_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, 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){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 64/8), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + Value* MEMtmp1_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: 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, 171); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + uint8_t rl = ((bit_sub<25,1>(instr))); + uint8_t aq = ((bit_sub<26,1>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2} (aqu={aq},rel={rl})", fmt::arg("mnemonic", "amoadd.d"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("aq", aq), fmt::arg("rl", rl)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->gen_reg_load(rs1 + traits::X0, 0); + Value* res_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 64/8), + 64, + true); + if(rd != 0){ + Value* Xtmp0_val = res_val; + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + Value* res2_val = this->builder.CreateAdd( + res_val, + this->gen_reg_load(rs2 + traits::X0, 0)); + Value* MEMtmp1_val = res2_val; + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp1_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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( + 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->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); + bb = BasicBlock::Create(this->mod->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 */ + std::tuple __mul(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MUL"); + + this->gen_sync(PRE_SYNC, 179); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* res_val = this->builder.CreateMul( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 128, + false), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 128, + false)); + Value* Xtmp0_val = this->gen_ext( + res_val, + 64, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 179); + bb = BasicBlock::Create(this->mod->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 */ + std::tuple __mulh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MULH"); + + this->gen_sync(PRE_SYNC, 180); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* res_val = this->builder.CreateMul( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 128, + true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 128, + true)); + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateLShr( + res_val, + this->gen_const(64U, 64)), + 64, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: MULHSU */ + std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MULHSU"); + + this->gen_sync(PRE_SYNC, 181); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* res_val = this->builder.CreateMul( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 128, + true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 128, + false)); + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateLShr( + res_val, + this->gen_const(64U, 64)), + 64, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: MULHU */ + std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MULHU"); + + this->gen_sync(PRE_SYNC, 182); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* res_val = this->builder.CreateMul( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 128, + false), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 128, + false)); + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateLShr( + res_val, + this->gen_const(64U, 64)), + 64, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: DIV */ + std::tuple __div(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("DIV"); + + this->gen_sync(PRE_SYNC, 183); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(rs2 + traits::X0, 0), + this->gen_const(64U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + uint64_t M1_val = - 1; + uint8_t XLM1_val = 64 - 1; + uint64_t ONE_val = 1; + uint64_t MMIN_val = ONE_val << XLM1_val; + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateAnd( + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1 + traits::X0, 1), + this->gen_const(64U, MMIN_val)), + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_reg_load(rs2 + traits::X0, 1), + this->gen_const(64U, M1_val))), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* Xtmp0_val = this->gen_const(64U, MMIN_val); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp1_val = this->builder.CreateSDiv( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 2), + 64, true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 2), + 64, true)); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp2_val = this->builder.CreateNeg(this->gen_const(64U, 1)); + this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 183); + bb = BasicBlock::Create(this->mod->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 */ + std::tuple __divu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("DIVU"); + + this->gen_sync(PRE_SYNC, 184); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(rs2 + traits::X0, 0), + this->gen_const(64U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* Xtmp0_val = this->builder.CreateUDiv( + this->gen_reg_load(rs1 + traits::X0, 1), + this->gen_reg_load(rs2 + traits::X0, 1)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp1_val = this->builder.CreateNeg(this->gen_const(64U, 1)); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: REM */ + std::tuple __rem(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("REM"); + + this->gen_sync(PRE_SYNC, 185); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(rs2 + traits::X0, 0), + this->gen_const(64U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + uint64_t M1_val = - 1; + uint32_t XLM1_val = 64 - 1; + uint64_t ONE_val = 1; + uint64_t MMIN_val = ONE_val << XLM1_val; + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateAnd( + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1 + traits::X0, 1), + this->gen_const(64U, MMIN_val)), + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_reg_load(rs2 + traits::X0, 1), + this->gen_const(64U, M1_val))), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* Xtmp0_val = this->gen_const(64U, 0); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp1_val = this->builder.CreateSRem( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 2), + 64, true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 2), + 64, true)); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp2_val = this->gen_reg_load(rs1 + traits::X0, 1); + this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 185); + bb = BasicBlock::Create(this->mod->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 */ + std::tuple __remu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("REMU"); + + this->gen_sync(PRE_SYNC, 186); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(rs2 + traits::X0, 0), + this->gen_const(64U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* Xtmp0_val = this->builder.CreateURem( + this->gen_reg_load(rs1 + traits::X0, 1), + this->gen_reg_load(rs2 + traits::X0, 1)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp1_val = this->gen_reg_load(rs1 + traits::X0, 1); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 186); + bb = BasicBlock::Create(this->mod->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 */ + std::tuple __mulw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MULW"); + + this->gen_sync(PRE_SYNC, 187); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateMul( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 0), + this-> get_type(32) + )), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: DIVW */ + std::tuple __divw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("DIVW"); + + this->gen_sync(PRE_SYNC, 188); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(rs2 + traits::X0, 0), + this->gen_const(64U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + uint32_t M1_val = - 1; + uint32_t ONE_val = 1; + uint32_t MMIN_val = ONE_val << 31; + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateAnd( + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 1), + this-> get_type(32) + ), + this->gen_const(32U, MMIN_val)), + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 1), + this-> get_type(32) + ), + this->gen_const(32U, M1_val))), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* Xtmp0_val = this->builder.CreateShl( + this->builder.CreateNeg(this->gen_const(64U, 1)), + this->gen_const(64U, 31)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp1_val = this->gen_ext( + this->builder.CreateSDiv( + this->gen_ext( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 2), + this-> get_type(32) + ), + 64, true), + this->gen_ext( + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 2), + this-> get_type(32) + ), + 64, true)), + 64, + true); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp2_val = this->builder.CreateNeg(this->gen_const(64U, 1)); + this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 188); + bb = BasicBlock::Create(this->mod->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 */ + std::tuple __divuw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("DIVUW"); + + this->gen_sync(PRE_SYNC, 189); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divuw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateUDiv( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 1), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 1), + this-> get_type(32) + )), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp1_val = this->builder.CreateNeg(this->gen_const(64U, 1)); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: REMW */ + std::tuple __remw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("REMW"); + + this->gen_sync(PRE_SYNC, 190); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(rs2 + traits::X0, 0), + this->gen_const(64U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + uint32_t M1_val = - 1; + uint32_t ONE_val = 1; + uint32_t MMIN_val = ONE_val << 31; + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateAnd( + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 1), + this-> get_type(32) + ), + this->gen_const(32U, MMIN_val)), + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_reg_load(rs2 + traits::X0, 1), + this->gen_const(64U, M1_val))), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* Xtmp0_val = this->gen_const(64U, 0); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp1_val = this->gen_ext( + this->builder.CreateSRem( + this->gen_ext( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 2), + this-> get_type(32) + ), + 64, true), + this->gen_ext( + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 2), + this-> get_type(32) + ), + 64, true)), + 64, + true); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp2_val = this->gen_ext( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 1), + this-> get_type(32) + ), + 64, + true); + this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: REMUW */ + std::tuple __remuw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("REMUW"); + + this->gen_sync(PRE_SYNC, 191); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remuw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + { + BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* Xtmp0_val = this->gen_ext( + this->builder.CreateURem( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 1), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 1), + this-> get_type(32) + )), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* Xtmp1_val = this->gen_ext( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 1), + this-> get_type(32) + ), + 64, + true); + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + } + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: LWU */ + std::tuple __lwu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LWU"); + + this->gen_sync(PRE_SYNC, 192); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lwu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 64, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: LD */ + std::tuple __ld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LD"); + + this->gen_sync(PRE_SYNC, 193); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = 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, 193); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 194: SD */ + std::tuple __sd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SD"); + + this->gen_sync(PRE_SYNC, 194); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sd"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: ADDIW */ + std::tuple __addiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADDIW"); + + this->gen_sync(PRE_SYNC, 195); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addiw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* res_val = this->builder.CreateAdd( + this->gen_ext( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + 32, true), + this->gen_const(32U, imm)); + Value* Xtmp0_val = this->gen_ext( + res_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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: SLLIW */ + std::tuple __slliw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLLIW"); + + this->gen_sync(PRE_SYNC, 196); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slliw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* sh_val_val = this->builder.CreateShl( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, shamt)); + Value* Xtmp0_val = this->gen_ext( + sh_val_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 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"); + + 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))); + 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, 197); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 198: SRAIW */ + std::tuple __sraiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRAIW"); + + this->gen_sync(PRE_SYNC, 198); + + 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, 198); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 199: ADDW */ + std::tuple __addw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADDW"); + + 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))); + 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, 199); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 200: SUBW */ + std::tuple __subw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SUBW"); + + 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))); + 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, 200); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 201: SLLW */ + std::tuple __sllw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLLW"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sllw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + uint32_t mask_val = 0x1f; + Value* count_val = this->builder.CreateAnd( + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, mask_val)); + Value* sh_val_val = this->builder.CreateShl( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + count_val); + Value* Xtmp0_val = this->gen_ext( + sh_val_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 201); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 202: SRLW */ + std::tuple __srlw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRLW"); + + this->gen_sync(PRE_SYNC, 202); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srlw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + uint32_t mask_val = 0x1f; + Value* count_val = this->builder.CreateAnd( + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, mask_val)); + Value* sh_val_val = this->builder.CreateLShr( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + count_val); + Value* Xtmp0_val = this->gen_ext( + sh_val_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 202); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 203: SRAW */ + std::tuple __sraw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRAW"); + + 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))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sraw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + uint32_t mask_val = 0x1f; + Value* count_val = this->builder.CreateAnd( + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, mask_val)); + Value* sh_val_val = this->builder.CreateAShr( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + count_val); + Value* Xtmp0_val = this->gen_ext( + sh_val_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 203); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /**************************************************************************** + * end opcode definitions + ****************************************************************************/ + std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { + this->gen_sync(iss::PRE_SYNC, instr_descr.size()); + this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), + get_reg_ptr(traits::PC), true); + this->builder.CreateStore( + this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits::ICOUNT), true), + this->gen_const(64U, 1)), + get_reg_ptr(traits::ICOUNT), true); + pc = pc + ((instr & 3) == 3 ? 4 : 2); + this->gen_raise_trap(0, 2); // illegal instruction trap + this->gen_sync(iss::POST_SYNC, instr_descr.size()); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } +}; + +template void debug_fn(CODE_WORD insn) { + volatile CODE_WORD x = insn; + insn = 2 * x; +} + +template vm_impl::vm_impl() { this(new ARCH()); } + +template +vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) +: vm_base(core, core_id, cluster_id) { + qlut[0] = lut_00.data(); + qlut[1] = lut_01.data(); + qlut[2] = lut_10.data(); + qlut[3] = lut_11.data(); + for (auto instr : instr_descr) { + auto quantrant = instr.value & 0x3; + expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + } +} + +template +std::tuple +vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { + // we fetch at max 4 byte, alignment is 2 + enum {TRAP_ID=1<<16}; + code_word_t insn = 0; + const typename traits::addr_t upper_bits = ~traits::PGMASK; + phys_addr_t paddr(pc); + auto *const data = (uint8_t *)&insn; + paddr = this->core.v2p(pc); + if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary + auto res = this->core.read(paddr, 2, data); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if ((insn & 0x3) == 0x3) { // this is a 32bit instruction + res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); + } + } else { + auto res = this->core.read(paddr, 4, data); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + } + if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + // curr pc on stack + ++inst_cnt; + auto lut_val = extract_fields(insn); + auto f = qlut[insn & 0x3][lut_val]; + if (f == nullptr) { + f = &this_class::illegal_intruction; + } + return (this->*f)(pc, insn, this_block); +} + +template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { + this->builder.SetInsertPoint(leave_blk); + this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); +} + +template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { + auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); + this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); +} + +template void vm_impl::gen_leave_trap(unsigned lvl) { + std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) }; + this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); + auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); +} + +template void vm_impl::gen_wait(unsigned type) { + std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) }; + this->builder.CreateCall(this->mod->getFunction("wait"), args); +} + +template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { + this->builder.SetInsertPoint(trap_blk); + auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), + get_reg_ptr(traits::LAST_BRANCH), false); + std::vector args{this->core_ptr, this->adj_to64(trap_state_val), + this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; + this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); + auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateRet(trap_addr_val); +} + +template inline void vm_impl::gen_trap_check(BasicBlock *bb) { + auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_EQ, v, + ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), + bb, this->trap_blk, 1); +} + +} // namespace rv64gc + +template <> +std::unique_ptr create(arch::rv64gc *core, unsigned short port, bool dump) { + auto ret = new rv64gc::vm_impl(*core, dump); + if (port != 0) debugger::server::run_server(ret, port); + return std::unique_ptr(ret); +} + +} // namespace iss diff --git a/riscv/src/internal/vm_rv64i.cpp b/riscv/src/internal/vm_rv64i.cpp new file mode 100644 index 0000000..e9a1be3 --- /dev/null +++ b/riscv/src/internal/vm_rv64i.cpp @@ -0,0 +1,3151 @@ +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace iss { +namespace vm { +namespace fp_impl { +void add_fp_functions_2_module(llvm::Module *, unsigned, unsigned); +} +} + +namespace rv64i { +using namespace iss::arch; +using namespace llvm; +using namespace iss::debugger; +using namespace iss::vm::llvm; + +template class vm_impl : public vm_base { +public: + using super = typename iss::vm::llvm::vm_base; + using virt_addr_t = typename super::virt_addr_t; + using phys_addr_t = typename super::phys_addr_t; + using code_word_t = typename super::code_word_t; + using addr_t = typename super::addr_t; + + vm_impl(); + + vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); + + void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } + + target_adapter_if *accquire_target_adapter(server_if *srv) override { + debugger_if::dbg_enabled = true; + if (vm_base::tgt_adapter == nullptr) + vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return vm_base::tgt_adapter; + } + +protected: + using vm_base::get_reg_ptr; + + inline const char *name(size_t index){return traits::reg_aliases.at(index);} + + template inline ConstantInt *size(T type) { + return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); + } + + void setup_module(Module* m) override { + super::setup_module(m); + iss::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)); + } + + std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override; + + void gen_leave_behavior(BasicBlock *leave_blk) override; + + void gen_raise_trap(uint16_t trap_id, uint16_t cause); + + void gen_leave_trap(unsigned lvl); + + void gen_wait(unsigned type); + + void gen_trap_behavior(BasicBlock *) override; + + void gen_trap_check(BasicBlock *bb); + + inline Value *gen_reg_load(unsigned i, unsigned level = 0) { + return this->builder.CreateLoad(get_reg_ptr(i), false); + } + + inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { + Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), + this->get_type(traits::XLEN)); + this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); + } + + // some compile time constants + // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; + enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; + enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; + enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + + using this_class = vm_impl; + using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, + code_word_t instr, + BasicBlock *bb); + std::array lut; + + std::array lut_00, lut_01, lut_10; + std::array lut_11; + + std::array qlut; + + std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; + + void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], + compile_func f) { + if (pos < 0) { + lut[idx] = f; + } else { + auto bitmask = 1UL << pos; + if ((mask & bitmask) == 0) { + expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); + } else { + if ((valid & bitmask) == 0) { + expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); + expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); + } else { + auto new_val = idx << 1; + if ((value & bitmask) != 0) new_val++; + expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); + } + } + } + } + + inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } + + uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { + if (pos >= 0) { + auto bitmask = 1UL << pos; + if ((mask & bitmask) == 0) { + lut_val = extract_fields(pos - 1, val, mask, lut_val); + } else { + auto new_val = lut_val << 1; + if ((val & bitmask) != 0) new_val++; + lut_val = extract_fields(pos - 1, val, mask, new_val); + } + } + return lut_val; + } + +private: + /**************************************************************************** + * start opcode definitions + ****************************************************************************/ + struct InstructionDesriptor { + size_t length; + uint32_t value; + uint32_t mask; + compile_func op; + }; + + const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */ + /* instruction LUI */ + {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, + /* instruction AUIPC */ + {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, + /* instruction JAL */ + {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, + /* instruction JALR */ + {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, + /* instruction BEQ */ + {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, + /* instruction BNE */ + {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, + /* instruction BLT */ + {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, + /* instruction BGE */ + {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, + /* instruction BLTU */ + {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, + /* instruction BGEU */ + {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, + /* instruction LB */ + {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, + /* instruction LH */ + {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, + /* instruction LW */ + {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, + /* instruction LBU */ + {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, + /* instruction LHU */ + {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, + /* instruction SB */ + {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, + /* instruction SH */ + {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, + /* instruction SW */ + {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, + /* instruction ADDI */ + {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, + /* instruction SLTI */ + {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, + /* instruction SLTIU */ + {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, + /* instruction XORI */ + {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, + /* instruction ORI */ + {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, + /* instruction ANDI */ + {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, + /* instruction SLLI */ + {32, 0b00000000000000000001000000010011, 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 */ + std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LUI"); + + this->gen_sync(PRE_SYNC, 0); + + uint8_t rd = ((bit_sub<7,5>(instr))); + int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_const(64U, imm); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 0); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 1: AUIPC */ + std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("AUIPC"); + + this->gen_sync(PRE_SYNC, 1); + + uint8_t rd = ((bit_sub<7,5>(instr))); + int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 1); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 2: JAL */ + std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("JAL"); + + this->gen_sync(PRE_SYNC, 2); + + uint8_t rd = ((bit_sub<7,5>(instr))); + int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + Value* PC_val = this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 2); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 3: JALR */ + std::tuple __jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("JALR"); + + this->gen_sync(PRE_SYNC, 3); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* new_pc_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + 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, 3); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 4: BEQ */ + std::tuple __beq(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BEQ"); + + this->gen_sync(PRE_SYNC, 4); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 4); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 5: BNE */ + std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BNE"); + + this->gen_sync(PRE_SYNC, 5); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 5); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 6: BLT */ + std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BLT"); + + this->gen_sync(PRE_SYNC, 6); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 64, true)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 6); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 7: BGE */ + std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BGE"); + + this->gen_sync(PRE_SYNC, 7); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SGE, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 64, true)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 7); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 8: BLTU */ + std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BLTU"); + + this->gen_sync(PRE_SYNC, 8); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 8); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 9: BGEU */ + std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("BGEU"); + + this->gen_sync(PRE_SYNC, 9); + + int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_UGE, + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)), + this->builder.CreateAdd( + this->gen_ext( + cur_pc_val, + 64, true), + this->gen_const(64U, imm)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(64U, 4)), + 64); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); + this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_sync(POST_SYNC, 9); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 10: LB */ + std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LB"); + + this->gen_sync(PRE_SYNC, 10); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 8/8), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 10); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 11: LH */ + std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LH"); + + this->gen_sync(PRE_SYNC, 11); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 16/8), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 11); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 12: LW */ + std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LW"); + + this->gen_sync(PRE_SYNC, 12); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 12); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 13: LBU */ + std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LBU"); + + this->gen_sync(PRE_SYNC, 13); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 8/8), + 64, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 13); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 14: LHU */ + std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LHU"); + + this->gen_sync(PRE_SYNC, 14); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 16/8), + 64, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 14); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 15: SB */ + std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SB"); + + this->gen_sync(PRE_SYNC, 15); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 15); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 16: SH */ + std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SH"); + + this->gen_sync(PRE_SYNC, 16); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(16))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 16); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 17: SW */ + std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SW"); + + this->gen_sync(PRE_SYNC, 17); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 17); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 18: ADDI */ + std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADDI"); + + this->gen_sync(PRE_SYNC, 18); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 18); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 19: SLTI */ + std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTI"); + + this->gen_sync(PRE_SYNC, 19); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)), + this->gen_const(64U, 1), + this->gen_const(64U, 0), + 64); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 19); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 20: SLTIU */ + std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTIU"); + + this->gen_sync(PRE_SYNC, 20); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + int64_t full_imm_val = imm; + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_const(64U, full_imm_val)), + this->gen_const(64U, 1), + this->gen_const(64U, 0), + 64); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 20); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 21: XORI */ + std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("XORI"); + + this->gen_sync(PRE_SYNC, 21); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateXor( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 21); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 22: ORI */ + std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ORI"); + + this->gen_sync(PRE_SYNC, 22); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateOr( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 22); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 23: ANDI */ + std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ANDI"); + + this->gen_sync(PRE_SYNC, 23); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAnd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 23); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 24: SLLI */ + std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLLI"); + + this->gen_sync(PRE_SYNC, 24); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateShl( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_const(64U, shamt)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 24); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 25: SRLI */ + std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRLI"); + + this->gen_sync(PRE_SYNC, 25); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateLShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_const(64U, shamt)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 25); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 26: SRAI */ + std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRAI"); + + this->gen_sync(PRE_SYNC, 26); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,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)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_const(64U, shamt)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 26); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 27: ADD */ + std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADD"); + + this->gen_sync(PRE_SYNC, 27); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAdd( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 27); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 28: SUB */ + std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SUB"); + + this->gen_sync(PRE_SYNC, 28); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateSub( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 28); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 29: SLL */ + std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLL"); + + this->gen_sync(PRE_SYNC, 29); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateShl( + this->gen_reg_load(rs1 + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::X0, 0), + this->builder.CreateSub( + this->gen_const(64U, 64), + this->gen_const(64U, 1)))); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 29); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 30: SLT */ + std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLT"); + + this->gen_sync(PRE_SYNC, 30); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 64, true)), + this->gen_const(64U, 1), + this->gen_const(64U, 0), + 64); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 30); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 31: SLTU */ + std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLTU"); + + this->gen_sync(PRE_SYNC, 31); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, + false), + this->gen_ext( + this->gen_reg_load(rs2 + traits::X0, 0), + 64, + false)), + this->gen_const(64U, 1), + this->gen_const(64U, 0), + 64); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 31); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 32: XOR */ + std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("XOR"); + + this->gen_sync(PRE_SYNC, 32); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateXor( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 32); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 33: SRL */ + std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRL"); + + this->gen_sync(PRE_SYNC, 33); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateLShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::X0, 0), + this->builder.CreateSub( + this->gen_const(64U, 64), + this->gen_const(64U, 1)))); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 33); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 34: SRA */ + std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRA"); + + this->gen_sync(PRE_SYNC, 34); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAShr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(rs2 + traits::X0, 0), + this->builder.CreateSub( + this->gen_const(64U, 64), + this->gen_const(64U, 1)))); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 34); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 35: OR */ + std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("OR"); + + this->gen_sync(PRE_SYNC, 35); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateOr( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 35); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 36: AND */ + std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("AND"); + + this->gen_sync(PRE_SYNC, 36); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->builder.CreateAnd( + this->gen_reg_load(rs1 + traits::X0, 0), + this->gen_reg_load(rs2 + traits::X0, 0)); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 36); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 37: FENCE */ + std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FENCE"); + + this->gen_sync(PRE_SYNC, 37); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("fence"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(64U, pred), + this->gen_const(64U, 4)), + this->gen_const(64U, succ)); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 0), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 37); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 38: FENCE_I */ + std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("FENCE_I"); + + this->gen_sync(PRE_SYNC, 38); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("fence_i"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->gen_const(64U, imm); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 1), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 38); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(FLUSH, nullptr); + } + + /* instruction 39: ECALL */ + std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ECALL"); + + this->gen_sync(PRE_SYNC, 39); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("ecall"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_raise_trap(0, 11); + this->gen_sync(POST_SYNC, 39); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 40: EBREAK */ + std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("EBREAK"); + + this->gen_sync(PRE_SYNC, 40); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("ebreak"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_raise_trap(0, 3); + this->gen_sync(POST_SYNC, 40); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 41: URET */ + std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("URET"); + + this->gen_sync(PRE_SYNC, 41); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("uret"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_leave_trap(0); + this->gen_sync(POST_SYNC, 41); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 42: SRET */ + std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRET"); + + this->gen_sync(PRE_SYNC, 42); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("sret"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_leave_trap(1); + this->gen_sync(POST_SYNC, 42); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 43: MRET */ + std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("MRET"); + + this->gen_sync(PRE_SYNC, 43); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("mret"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_leave_trap(3); + this->gen_sync(POST_SYNC, 43); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } + + /* instruction 44: WFI */ + std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("WFI"); + + this->gen_sync(PRE_SYNC, 44); + + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("wfi"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + this->gen_wait(1); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 44); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 45: SFENCE.VMA */ + std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SFENCE.VMA"); + + this->gen_sync(PRE_SYNC, 45); + + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("sfence.vma"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* FENCEtmp0_val = this->gen_const(64U, rs1); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 2), + this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); + Value* FENCEtmp1_val = this->gen_const(64U, rs2); + this->gen_write_mem( + traits::FENCE, + this->gen_const(64U, 3), + this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 45); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 46: CSRRW */ + std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRW"); + + this->gen_sync(PRE_SYNC, 46); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); + if(rd != 0){ + Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* CSRtmp0_val = rs_val_val; + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(64))); + Value* Xtmp1_val = csr_val_val; + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } else { + Value* CSRtmp2_val = rs_val_val; + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(64))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 46); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 47: CSRRS */ + std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRS"); + + this->gen_sync(PRE_SYNC, 47); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); + if(rd != 0){ + Value* Xtmp0_val = xrd_val; + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + if(rs1 != 0){ + Value* CSRtmp1_val = this->builder.CreateOr( + xrd_val, + xrs1_val); + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 47); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 48: CSRRC */ + std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRC"); + + this->gen_sync(PRE_SYNC, 48); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); + if(rd != 0){ + Value* Xtmp0_val = xrd_val; + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + if(rs1 != 0){ + Value* CSRtmp1_val = this->builder.CreateAnd( + xrd_val, + this->builder.CreateNot(xrs1_val)); + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 48); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 49: CSRRWI */ + std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRWI"); + + this->gen_sync(PRE_SYNC, 49); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + Value* CSRtmp1_val = this->gen_ext( + this->gen_const(64U, zimm), + 64, + false); + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 49); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 50: CSRRSI */ + std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRSI"); + + this->gen_sync(PRE_SYNC, 50); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + if(zimm != 0){ + Value* CSRtmp0_val = this->builder.CreateOr( + res_val, + this->gen_ext( + this->gen_const(64U, zimm), + 64, + false)); + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(64))); + } + if(rd != 0){ + Value* Xtmp1_val = res_val; + this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 50); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 51: CSRRCI */ + std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("CSRRCI"); + + this->gen_sync(PRE_SYNC, 51); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 64/8); + if(rd != 0){ + Value* Xtmp0_val = res_val; + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + if(zimm != 0){ + Value* CSRtmp1_val = this->builder.CreateAnd( + res_val, + this->builder.CreateNot(this->gen_ext( + this->gen_const(64U, zimm), + 64, + false))); + this->gen_write_mem( + traits::CSR, + this->gen_const(16U, csr), + this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 51); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 52: LWU */ + std::tuple __lwu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LWU"); + + this->gen_sync(PRE_SYNC, 52); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lwu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 64, + false); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 52); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 53: LD */ + std::tuple __ld(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("LD"); + + this->gen_sync(PRE_SYNC, 53); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "ld"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + if(rd != 0){ + Value* Xtmp0_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 64/8), + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 53); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 54: SD */ + std::tuple __sd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SD"); + + this->gen_sync(PRE_SYNC, 54); + + int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sd"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(rs1 + traits::X0, 0), + 64, true), + this->gen_const(64U, imm)); + Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 54); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 55: ADDIW */ + std::tuple __addiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADDIW"); + + this->gen_sync(PRE_SYNC, 55); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + int16_t imm = signextend((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addiw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* res_val = this->builder.CreateAdd( + this->gen_ext( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + 32, true), + this->gen_const(32U, imm)); + Value* Xtmp0_val = this->gen_ext( + res_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 55); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 56: SLLIW */ + std::tuple __slliw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLLIW"); + + this->gen_sync(PRE_SYNC, 56); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slliw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* sh_val_val = this->builder.CreateShl( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, shamt)); + Value* Xtmp0_val = this->gen_ext( + sh_val_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 56); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 57: SRLIW */ + std::tuple __srliw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRLIW"); + + this->gen_sync(PRE_SYNC, 57); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srliw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* sh_val_val = this->builder.CreateLShr( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, shamt)); + Value* Xtmp0_val = this->gen_ext( + sh_val_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 57); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 58: SRAIW */ + std::tuple __sraiw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRAIW"); + + this->gen_sync(PRE_SYNC, 58); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "sraiw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* sh_val_val = this->builder.CreateAShr( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, shamt)); + Value* Xtmp0_val = this->gen_ext( + sh_val_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 58); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 59: ADDW */ + std::tuple __addw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("ADDW"); + + this->gen_sync(PRE_SYNC, 59); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("addw"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* res_val = this->builder.CreateAdd( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 0), + this-> get_type(32) + )); + Value* Xtmp0_val = this->gen_ext( + res_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 59); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 60: SUBW */ + std::tuple __subw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SUBW"); + + this->gen_sync(PRE_SYNC, 60); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("subw"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + Value* res_val = this->builder.CreateSub( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 0), + this-> get_type(32) + )); + Value* Xtmp0_val = this->gen_ext( + res_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 60); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 61: SLLW */ + std::tuple __sllw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SLLW"); + + this->gen_sync(PRE_SYNC, 61); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sllw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + uint32_t mask_val = 0x1f; + Value* count_val = this->builder.CreateAnd( + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, mask_val)); + Value* sh_val_val = this->builder.CreateShl( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + count_val); + Value* Xtmp0_val = this->gen_ext( + sh_val_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 61); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 62: SRLW */ + std::tuple __srlw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRLW"); + + this->gen_sync(PRE_SYNC, 62); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srlw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + uint32_t mask_val = 0x1f; + Value* count_val = this->builder.CreateAnd( + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, mask_val)); + Value* sh_val_val = this->builder.CreateLShr( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + count_val); + Value* Xtmp0_val = this->gen_ext( + sh_val_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 62); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /* instruction 63: SRAW */ + std::tuple __sraw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName("SRAW"); + + this->gen_sync(PRE_SYNC, 63); + + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sraw"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(64, pc.val); + pc=pc+4; + + if(rd != 0){ + uint32_t mask_val = 0x1f; + Value* count_val = this->builder.CreateAnd( + this->builder.CreateTrunc( + this->gen_reg_load(rs2 + traits::X0, 0), + this-> get_type(32) + ), + this->gen_const(32U, mask_val)); + Value* sh_val_val = this->builder.CreateAShr( + this->builder.CreateTrunc( + this->gen_reg_load(rs1 + traits::X0, 0), + this-> get_type(32) + ), + count_val); + Value* Xtmp0_val = this->gen_ext( + sh_val_val, + 64, + true); + this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(POST_SYNC, 63); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(CONT, bb); + } + + /**************************************************************************** + * end opcode definitions + ****************************************************************************/ + std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { + this->gen_sync(iss::PRE_SYNC, instr_descr.size()); + this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), + get_reg_ptr(traits::PC), true); + this->builder.CreateStore( + this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits::ICOUNT), true), + this->gen_const(64U, 1)), + get_reg_ptr(traits::ICOUNT), true); + pc = pc + ((instr & 3) == 3 ? 4 : 2); + this->gen_raise_trap(0, 2); // illegal instruction trap + this->gen_sync(iss::POST_SYNC, instr_descr.size()); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(BRANCH, nullptr); + } +}; + +template void debug_fn(CODE_WORD insn) { + volatile CODE_WORD x = insn; + insn = 2 * x; +} + +template vm_impl::vm_impl() { this(new ARCH()); } + +template +vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) +: vm_base(core, core_id, cluster_id) { + qlut[0] = lut_00.data(); + qlut[1] = lut_01.data(); + qlut[2] = lut_10.data(); + qlut[3] = lut_11.data(); + for (auto instr : instr_descr) { + auto quantrant = instr.value & 0x3; + expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + } +} + +template +std::tuple +vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { + // we fetch at max 4 byte, alignment is 2 + enum {TRAP_ID=1<<16}; + code_word_t insn = 0; + const typename traits::addr_t upper_bits = ~traits::PGMASK; + phys_addr_t paddr(pc); + auto *const data = (uint8_t *)&insn; + paddr = this->core.v2p(pc); + if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary + auto res = this->core.read(paddr, 2, data); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if ((insn & 0x3) == 0x3) { // this is a 32bit instruction + res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); + } + } else { + auto res = this->core.read(paddr, 4, data); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + } + if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + // curr pc on stack + ++inst_cnt; + auto lut_val = extract_fields(insn); + auto f = qlut[insn & 0x3][lut_val]; + if (f == nullptr) { + f = &this_class::illegal_intruction; + } + return (this->*f)(pc, insn, this_block); +} + +template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { + this->builder.SetInsertPoint(leave_blk); + this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); +} + +template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { + auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); + this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); +} + +template void vm_impl::gen_leave_trap(unsigned lvl) { + std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) }; + this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); + auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); +} + +template void vm_impl::gen_wait(unsigned type) { + std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) }; + this->builder.CreateCall(this->mod->getFunction("wait"), args); +} + +template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { + this->builder.SetInsertPoint(trap_blk); + auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), + get_reg_ptr(traits::LAST_BRANCH), false); + std::vector args{this->core_ptr, this->adj_to64(trap_state_val), + this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; + this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); + auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateRet(trap_addr_val); +} + +template inline void vm_impl::gen_trap_check(BasicBlock *bb) { + auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_EQ, v, + ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), + bb, this->trap_blk, 1); +} + +} // namespace rv64i + +template <> +std::unique_ptr create(arch::rv64i *core, unsigned short port, bool dump) { + auto ret = new rv64i::vm_impl(*core, dump); + if (port != 0) debugger::server::run_server(ret, port); + return std::unique_ptr(ret); +} + +} // namespace iss diff --git a/riscv/src/internal/vm_rv64ia.cpp b/riscv/src/internal/vm_rv64ia.cpp deleted file mode 100644 index 60c603e..0000000 --- a/riscv/src/internal/vm_rv64ia.cpp +++ /dev/null @@ -1,4335 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// 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 -#include -#include -#include -#include -#include - -#include - -#include -#include - -namespace iss { -namespace vm { -namespace fp_impl{ -void add_fp_functions_2_module(llvm::Module *, unsigned); -} -} - -namespace rv64ia { -using namespace iss::arch; -using namespace llvm; -using namespace iss::debugger; - -template class vm_impl : public vm::vm_base { -public: - using super = typename vm::vm_base; - using virt_addr_t = typename super::virt_addr_t; - using phys_addr_t = typename super::phys_addr_t; - using code_word_t = typename super::code_word_t; - using addr_t = typename super::addr_t; - - vm_impl(); - - vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); - - void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } - - target_adapter_if *accquire_target_adapter(server_if *srv) { - debugger_if::dbg_enabled = true; - if (vm::vm_base::tgt_adapter == nullptr) - vm::vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm::vm_base::tgt_adapter; - } - -protected: - using vm::vm_base::get_reg_ptr; - - template inline llvm::ConstantInt *size(T type) { - return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); - } - - void setup_module(llvm::Module* m) override { - super::setup_module(m); - vm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE); - } - - inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, unsigned size) { - return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); - } - - std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, - llvm::BasicBlock *) override; - - void gen_leave_behavior(llvm::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(llvm::BasicBlock *) override; - - void gen_trap_check(llvm::BasicBlock *bb); - - inline llvm::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) { - llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); - this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); - } - - // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; - - using this_class = vm_impl; - using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, - code_word_t instr, - llvm::BasicBlock *bb); - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = { { EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32 } }; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } - -private: - /**************************************************************************** - * start opcode definitions - ****************************************************************************/ - struct InstructionDesriptor { - size_t length; - uint32_t value; - uint32_t mask; - compile_func op; - }; - - const std::array instr_descr = {{ - /* entries are: size, valid value, valid mask, function ptr */ - /* instruction LWU */ - {32, 0b00000000000000000110000000000011, 0b00000000000000000111000001111111, &this_class::__lwu}, - /* instruction LD */ - {32, 0b00000000000000000011000000000011, 0b00000000000000000111000001111111, &this_class::__ld}, - /* instruction SD */ - {32, 0b00000000000000000011000000100011, 0b00000000000000000111000001111111, &this_class::__sd}, - /* 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 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 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 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 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 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 definitions */ - /* instruction 0: LWU */ - std::tuple __lwu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LWU"); - - this->gen_sync(iss::PRE_SYNC, 0); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LWU x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 0); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 1: LD */ - std::tuple __ld(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LD"); - - this->gen_sync(iss::PRE_SYNC, 1); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LD x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 1); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 2: SD */ - std::tuple __sd(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SD"); - - this->gen_sync(iss::PRE_SYNC, 2); - - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SD x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 2); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 3: SLLI */ - std::tuple __slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLLI"); - - this->gen_sync(iss::PRE_SYNC, 3); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLLI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 0); - } else { - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(64U, fld_shamt_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 3); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 4: SRLI */ - std::tuple __srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRLI"); - - this->gen_sync(iss::PRE_SYNC, 4); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRLI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 0); - } else { - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(64U, fld_shamt_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 4); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 5: SRAI */ - std::tuple __srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRAI"); - - this->gen_sync(iss::PRE_SYNC, 5); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRAI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_shamt_val > 31){ - this->gen_raise_trap(0, 0); - } else { - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(64U, fld_shamt_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 5); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 6: ADDIW */ - std::tuple __addiw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ADDIW"); - - this->gen_sync(iss::PRE_SYNC, 6); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ADDIW x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder.CreateAdd( - this->gen_ext( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this-> get_type(32) - ), - 32, true), - this->gen_const(32U, fld_imm_val)); - Value* Xtmp0_val = this->gen_ext( - res_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 6); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 7: SLLIW */ - std::tuple __slliw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLLIW"); - - this->gen_sync(iss::PRE_SYNC, 7); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLLIW x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* sh_val_val = this->builder.CreateShl( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, fld_shamt_val)); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 7); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 8: SRLIW */ - std::tuple __srliw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRLIW"); - - this->gen_sync(iss::PRE_SYNC, 8); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRLIW x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* sh_val_val = this->builder.CreateLShr( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, fld_shamt_val)); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 8); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 9: SRAIW */ - std::tuple __sraiw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRAIW"); - - this->gen_sync(iss::PRE_SYNC, 9); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_shamt_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRAIW x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* sh_val_val = this->builder.CreateAShr( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this-> get_type(32) - ), - this->gen_const(32U, fld_shamt_val)); - Value* Xtmp0_val = this->gen_ext( - sh_val_val, - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 9); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 10: ADDW */ - std::tuple __addw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ADDW"); - - this->gen_sync(iss::PRE_SYNC, 10); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((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(fld_rd_val != 0){ - Value* res_val = this->builder.CreateAdd( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 10); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 11: SUBW */ - std::tuple __subw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SUBW"); - - this->gen_sync(iss::PRE_SYNC, 11); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((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(fld_rd_val != 0){ - Value* res_val = this->builder.CreateSub( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this-> get_type(32) - ), - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 11); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 12: SLLW */ - std::tuple __sllw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLLW"); - - this->gen_sync(iss::PRE_SYNC, 12); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLLW x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - uint32_t mask_val = 0x1f; - Value* count_val = this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + 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(fld_rs1_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 12); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 13: SRLW */ - std::tuple __srlw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRLW"); - - this->gen_sync(iss::PRE_SYNC, 13); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRLW x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - uint32_t mask_val = 0x1f; - Value* count_val = this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + 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(fld_rs1_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 13); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 14: SRAW */ - std::tuple __sraw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRAW"); - - this->gen_sync(iss::PRE_SYNC, 14); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRAW x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - uint32_t mask_val = 0x1f; - Value* count_val = this->builder.CreateAnd( - this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val + 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(fld_rs1_val + 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 14); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 15: LUI */ - std::tuple __lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LUI"); - - this->gen_sync(iss::PRE_SYNC, 15); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - int32_t fld_imm_val = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LUI x%1$d, 0x%2$05x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_const(64U, fld_imm_val); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 15); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 16: AUIPC */ - std::tuple __auipc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AUIPC"); - - this->gen_sync(iss::PRE_SYNC, 16); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - int32_t fld_imm_val = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AUIPC x%1%, 0x%2$08x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 16); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 17: JAL */ - std::tuple __jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("JAL"); - - this->gen_sync(iss::PRE_SYNC, 17); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - int32_t fld_imm_val = 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 */ - boost::format ins_fmter("JAL x%1$d, 0x%2$x"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, fld_imm_val)); - 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(iss::POST_SYNC, 17); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 18: JALR */ - std::tuple __jalr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("JALR"); - - this->gen_sync(iss::PRE_SYNC, 18); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("JALR x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - Value* align_val = this->builder.CreateAnd( - new_pc_val, - this->gen_const(64U, 0x2)); - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::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(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(iss::POST_SYNC, 18); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 19: BEQ */ - std::tuple __beq(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BEQ"); - - this->gen_sync(iss::PRE_SYNC, 19); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BEQ x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, fld_imm_val)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(iss::POST_SYNC, 19); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 20: BNE */ - std::tuple __bne(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BNE"); - - this->gen_sync(iss::PRE_SYNC, 20); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BNE x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, fld_imm_val)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(iss::POST_SYNC, 20); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 21: BLT */ - std::tuple __blt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BLT"); - - this->gen_sync(iss::PRE_SYNC, 21); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BLT x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 64, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, fld_imm_val)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(iss::POST_SYNC, 21); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 22: BGE */ - std::tuple __bge(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BGE"); - - this->gen_sync(iss::PRE_SYNC, 22); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BGE x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGE, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 64, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, fld_imm_val)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(iss::POST_SYNC, 22); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 23: BLTU */ - std::tuple __bltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BLTU"); - - this->gen_sync(iss::PRE_SYNC, 23); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BLTU x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, fld_imm_val)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(iss::POST_SYNC, 23); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 24: BGEU */ - std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("BGEU"); - - this->gen_sync(iss::PRE_SYNC, 24); - - int16_t fld_imm_val = 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 fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("BGEU x%1$d, x%2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGE, - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 64, true), - this->gen_const(64U, fld_imm_val)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(64U, 4)), - 64); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(64U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(iss::POST_SYNC, 24); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 25: LB */ - std::tuple __lb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LB"); - - this->gen_sync(iss::PRE_SYNC, 25); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LB x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 25); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 26: LH */ - std::tuple __lh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LH"); - - this->gen_sync(iss::PRE_SYNC, 26); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LH x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 64, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 26); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 27: LW */ - std::tuple __lw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LW"); - - this->gen_sync(iss::PRE_SYNC, 27); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LW x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 27); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 28: LBU */ - std::tuple __lbu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LBU"); - - this->gen_sync(iss::PRE_SYNC, 28); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LBU x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 28); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 29: LHU */ - std::tuple __lhu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LHU"); - - this->gen_sync(iss::PRE_SYNC, 29); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LHU x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 64, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 29); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 30: SB */ - std::tuple __sb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SB"); - - this->gen_sync(iss::PRE_SYNC, 30); - - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SB x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 30); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 31: SH */ - std::tuple __sh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SH"); - - this->gen_sync(iss::PRE_SYNC, 31); - - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SH x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 31); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 32: SW */ - std::tuple __sw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SW"); - - this->gen_sync(iss::PRE_SYNC, 32); - - int16_t fld_imm_val = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SW x%1$d, %2%(x%3$d)"); - ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - Value* MEMtmp0_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 32); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 33: ADDI */ - std::tuple __addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ADDI"); - - this->gen_sync(iss::PRE_SYNC, 33); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ADDI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 33); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 34: SLTI */ - std::tuple __slti(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLTI"); - - this->gen_sync(iss::PRE_SYNC, 34); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLTI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_const(64U, fld_imm_val)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 34); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 35: SLTIU */ - std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLTIU"); - - this->gen_sync(iss::PRE_SYNC, 35); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLTIU x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - int64_t full_imm_val = fld_imm_val; - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(64U, full_imm_val)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 35); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 36: XORI */ - std::tuple __xori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("XORI"); - - this->gen_sync(iss::PRE_SYNC, 36); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("XORI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(64U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 36); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 37: ORI */ - std::tuple __ori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ORI"); - - this->gen_sync(iss::PRE_SYNC, 37); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ORI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(64U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 37); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 38: ANDI */ - std::tuple __andi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ANDI"); - - this->gen_sync(iss::PRE_SYNC, 38); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - int16_t fld_imm_val = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ANDI x%1$d, x%2$d, %3%"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_const(64U, fld_imm_val)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 38); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 39: ADD */ - std::tuple __add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ADD"); - - this->gen_sync(iss::PRE_SYNC, 39); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("ADD x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 39); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 40: SUB */ - std::tuple __sub(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SUB"); - - this->gen_sync(iss::PRE_SYNC, 40); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SUB x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 40); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 41: SLL */ - std::tuple __sll(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLL"); - - this->gen_sync(iss::PRE_SYNC, 41); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLL x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - this->gen_const(64U, 0x1f))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 41); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 42: SLT */ - std::tuple __slt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLT"); - - this->gen_sync(iss::PRE_SYNC, 42); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLT x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 64, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 64, true)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 42); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 43: SLTU */ - std::tuple __sltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SLTU"); - - this->gen_sync(iss::PRE_SYNC, 43); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SLTU x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - 64, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 64, - false)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 43); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 44: XOR */ - std::tuple __xor(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("XOR"); - - this->gen_sync(iss::PRE_SYNC, 44); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("XOR x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 44); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 45: SRL */ - std::tuple __srl(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRL"); - - this->gen_sync(iss::PRE_SYNC, 45); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRL x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - this->gen_const(64U, 0x1f))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 45); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 46: SRA */ - std::tuple __sra(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRA"); - - this->gen_sync(iss::PRE_SYNC, 46); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SRA x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - this->gen_const(64U, 0x1f))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 46); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 47: OR */ - std::tuple __or(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("OR"); - - this->gen_sync(iss::PRE_SYNC, 47); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("OR x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 47); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 48: AND */ - std::tuple __and(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AND"); - - this->gen_sync(iss::PRE_SYNC, 48); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AND x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(fld_rs1_val + traits::X0, 0), - this->gen_reg_load(fld_rs2_val + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 48); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 49: FENCE */ - std::tuple __fence(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FENCE"); - - this->gen_sync(iss::PRE_SYNC, 49); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_succ_val = ((bit_sub<20,4>(instr))); - uint8_t fld_pred_val = ((bit_sub<24,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("FENCE"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(64U, fld_pred_val), - this->gen_const(64U, 4)), - this->gen_const(64U, fld_succ_val)); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 0), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 49); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 50: FENCE_I */ - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("FENCE_I"); - - this->gen_sync(iss::PRE_SYNC, 50); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_imm_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("FENCE_I"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(64U, fld_imm_val); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 1), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 50); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::FLUSH, nullptr); - } - - /* instruction 51: ECALL */ - std::tuple __ecall(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("ECALL"); - - this->gen_sync(iss::PRE_SYNC, 51); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ECALL"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 11); - this->gen_sync(iss::POST_SYNC, 51); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 52: EBREAK */ - std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("EBREAK"); - - this->gen_sync(iss::PRE_SYNC, 52); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("EBREAK"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 3); - this->gen_sync(iss::POST_SYNC, 52); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 53: URET */ - std::tuple __uret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("URET"); - - this->gen_sync(iss::PRE_SYNC, 53); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("URET"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_leave_trap(0); - this->gen_sync(iss::POST_SYNC, 53); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 54: SRET */ - std::tuple __sret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SRET"); - - this->gen_sync(iss::PRE_SYNC, 54); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("SRET"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_leave_trap(1); - this->gen_sync(iss::POST_SYNC, 54); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 55: MRET */ - std::tuple __mret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("MRET"); - - this->gen_sync(iss::PRE_SYNC, 55); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("MRET"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_leave_trap(3); - this->gen_sync(iss::POST_SYNC, 55); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } - - /* instruction 56: WFI */ - std::tuple __wfi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("WFI"); - - this->gen_sync(iss::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("WFI"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - this->gen_wait(1); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 56); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 57: SFENCE.VMA */ - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SFENCE.VMA"); - - this->gen_sync(iss::PRE_SYNC, 57); - - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("SFENCE.VMA"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(64U, fld_rs1_val); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 2), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(64))); - Value* FENCEtmp1_val = this->gen_const(64U, fld_rs2_val); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 3), - this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 57); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 58: CSRRW */ - std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRW"); - - this->gen_sync(iss::PRE_SYNC, 58); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRW x%1$d, %2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* rs_val_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, fld_csr_val), 64/8); - Value* CSRtmp0_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(64))); - Value* Xtmp1_val = csr_val_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } else { - Value* CSRtmp2_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(64))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 58); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 59: CSRRS */ - std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRS"); - - this->gen_sync(iss::PRE_SYNC, 59); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRS x%1$d, %2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, fld_csr_val), 64/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - if(fld_rs1_val != 0){ - Value* CSRtmp1_val = this->builder.CreateOr( - xrd_val, - xrs1_val); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 59); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 60: CSRRC */ - std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRC"); - - this->gen_sync(iss::PRE_SYNC, 60); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRC x%1$d, %2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, fld_csr_val), 64/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - if(fld_rs1_val != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - xrd_val, - this->builder.CreateNot(xrs1_val)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 60); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 61: CSRRWI */ - std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRWI"); - - this->gen_sync(iss::PRE_SYNC, 61); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_zimm_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRWI x%1$d, %2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, fld_csr_val), 64/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* CSRtmp1_val = this->gen_ext( - this->gen_const(64U, fld_zimm_val), - 64, - false); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 61); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 62: CSRRSI */ - std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRSI"); - - this->gen_sync(iss::PRE_SYNC, 62); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_zimm_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRSI x%1$d, %2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, fld_csr_val), 64/8); - if(fld_zimm_val != 0){ - Value* CSRtmp0_val = this->builder.CreateOr( - res_val, - this->gen_ext( - this->gen_const(64U, fld_zimm_val), - 64, - false)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(64))); - } - if(fld_rd_val != 0){ - Value* Xtmp1_val = res_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 62); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 63: CSRRCI */ - std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("CSRRCI"); - - this->gen_sync(iss::PRE_SYNC, 63); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_zimm_val = ((bit_sub<15,5>(instr))); - uint16_t fld_csr_val = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("CSRRCI x%1$d, %2$d, 0x%3$x"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, fld_csr_val), 64/8); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - if(fld_zimm_val != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - res_val, - this->builder.CreateNot(this->gen_ext( - this->gen_const(64U, fld_zimm_val), - 64, - false))); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, fld_csr_val), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(64))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 63); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 64: LR.D */ - std::tuple __lr_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LR.D"); - - this->gen_sync(iss::PRE_SYNC, 64); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LR.D x%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* offs_val = this->gen_reg_load(fld_rs1_val + 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(fld_rd_val + 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(iss::POST_SYNC, 64); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 65: SC.D */ - std::tuple __sc_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SC.D"); - - this->gen_sync(iss::PRE_SYNC, 65); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SC.D x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res_val = this->gen_read_mem(traits::RES, offs_val, 8/8); - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - llvm::BasicBlock* bb_else = llvm::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(fld_rs2_val + traits::X0, 1); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(64)));if(fld_rd_val != 0){ - Value* Xtmp1_val = this->gen_const(64U, 0); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - if(fld_rd_val != 0){ - Value* Xtmp2_val = this->gen_const(64U, 1); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 65); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 66: AMOSWAP.D */ - std::tuple __amoswap_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOSWAP.D"); - - this->gen_sync(iss::PRE_SYNC, 66); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOSWAP.D x%1$d, x%2$d, x%3$d (aqu=%a,rel=%rl)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - Value* MEMtmp1_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 66); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 67: AMOADD.D */ - std::tuple __amoadd_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOADD.D"); - - this->gen_sync(iss::PRE_SYNC, 67); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOADD.D x%1$d, x%2$d, x%3$d (aqu=%a,rel=%rl)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateAdd( - res_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 67); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 68: AMOXOR.D */ - std::tuple __amoxor_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOXOR.D"); - - this->gen_sync(iss::PRE_SYNC, 68); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOXOR.D x%1$d, x%2$d, x%3$d (aqu=%a,rel=%rl)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateXor( - res_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 68); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 69: AMOAND.D */ - std::tuple __amoand_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOAND.D"); - - this->gen_sync(iss::PRE_SYNC, 69); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOAND.D x%1$d, x%2$d, x%3$d (aqu=%a,rel=%rl)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateAnd( - res_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 69); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 70: AMOOR.D */ - std::tuple __amoor_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOOR.D"); - - this->gen_sync(iss::PRE_SYNC, 70); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOOR.D x%1$d, x%2$d, x%3$d (aqu=%a,rel=%rl)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateOr( - res_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 70); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 71: AMOMIN.D */ - std::tuple __amomin_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMIN.D"); - - this->gen_sync(iss::PRE_SYNC, 71); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMIN.D x%1$d, x%2$d, x%3$d (aqu=%a,rel=%rl)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGT, - this->gen_ext( - res_val, - 64, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - 64, true)), - this->gen_reg_load(fld_rs2_val + traits::X0, 0), - res_val, - 64); - Value* MEMtmp1_val = res_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(iss::POST_SYNC, 71); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 72: AMOMAX.D */ - std::tuple __amomax_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMAX.D"); - - this->gen_sync(iss::PRE_SYNC, 72); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMAX.D x%1$d, x%2$d, x%3$d (aqu=%a,rel=%rl)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rs2_val + traits::X0, 0), - 64, true)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 72); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 73: AMOMINU.D */ - std::tuple __amominu_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMINU.D"); - - this->gen_sync(iss::PRE_SYNC, 73); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMINU.D x%1$d, x%2$d, x%3$d (aqu=%a,rel=%rl)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - false); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGT, - res_val, - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 73); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 74: AMOMAXU.D */ - std::tuple __amomaxu_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMAXU.D"); - - this->gen_sync(iss::PRE_SYNC, 74); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMAXU.D x%1$d, x%2$d, x%3$d (aqu=%a,rel=%rl)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - false); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - res_val, - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 74); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 75: LR.W */ - std::tuple __lr_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("LR.W"); - - this->gen_sync(iss::PRE_SYNC, 75); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("LR.W x%1$d, x%2$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(64, pc.val); - pc=pc+4; - - if(fld_rd_val != 0){ - Value* offs_val = this->gen_reg_load(fld_rs1_val + 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(fld_rd_val + 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(iss::POST_SYNC, 75); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 76: SC.W */ - std::tuple __sc_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("SC.W"); - - this->gen_sync(iss::PRE_SYNC, 76); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("SC.W x%1$d, x%2$d, x%3$d"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_read_mem(traits::RES, offs_val, 32/8); - { - llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - llvm::BasicBlock* bb_then = llvm::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(fld_rs2_val + 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(fld_rd_val != 0){ - Value* Xtmp1_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - res1_val, - this->gen_const(64U, 0)), - this->gen_const(64U, 0), - this->gen_const(64U, 1), - 64); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC, 76); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 77: AMOSWAP.W */ - std::tuple __amoswap_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOSWAP.W"); - - this->gen_sync(iss::PRE_SYNC, 77); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOSWAP.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - if(fld_rd_val != 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(fld_rd_val + traits::X0), false); - } - Value* MEMtmp1_val = this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 77); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 78: AMOADD.W */ - std::tuple __amoadd_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOADD.W"); - - this->gen_sync(iss::PRE_SYNC, 78); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOADD.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateAdd( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 78); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 79: AMOXOR.W */ - std::tuple __amoxor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOXOR.W"); - - this->gen_sync(iss::PRE_SYNC, 79); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOXOR.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateXor( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 79); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 80: AMOAND.W */ - std::tuple __amoand_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOAND.W"); - - this->gen_sync(iss::PRE_SYNC, 80); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOAND.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateAnd( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 80); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 81: AMOOR.W */ - std::tuple __amoor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOOR.W"); - - this->gen_sync(iss::PRE_SYNC, 81); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOOR.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->builder.CreateOr( - res1_val, - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 81); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 82: AMOMIN.W */ - std::tuple __amomin_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMIN.W"); - - this->gen_sync(iss::PRE_SYNC, 82); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMIN.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rs2_val + traits::X0, 0), - 64, true)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 82); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 83: AMOMAX.W */ - std::tuple __amomax_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMAX.W"); - - this->gen_sync(iss::PRE_SYNC, 83); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMAX.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + 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(fld_rs2_val + traits::X0, 0), - 64, true)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 83); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 84: AMOMINU.W */ - std::tuple __amominu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMINU.W"); - - this->gen_sync(iss::PRE_SYNC, 84); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMINU.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - false); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGT, - res1_val, - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 84); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /* instruction 85: AMOMAXU.W */ - std::tuple __amomaxu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - bb->setName("AMOMAXU.W"); - - this->gen_sync(iss::PRE_SYNC, 85); - - uint8_t fld_rd_val = ((bit_sub<7,5>(instr))); - uint8_t fld_rs1_val = ((bit_sub<15,5>(instr))); - uint8_t fld_rs2_val = ((bit_sub<20,5>(instr))); - uint8_t fld_rl_val = ((bit_sub<25,1>(instr))); - uint8_t fld_aq_val = ((bit_sub<26,1>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("AMOMAXU.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); - ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(ins_fmter.str()), - }; - 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(fld_rs1_val + traits::X0, 0); - Value* res1_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - false); - if(fld_rd_val != 0){ - Value* Xtmp0_val = res1_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(fld_rd_val + traits::X0), false); - } - Value* res2_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - res1_val, - this->gen_reg_load(fld_rs2_val + traits::X0, 0)), - this->gen_reg_load(fld_rs2_val + 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(iss::POST_SYNC, 85); - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, - llvm::BasicBlock *bb) { - this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); - this->builder.CreateStore( - this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits::ICOUNT), true), - this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - this->gen_raise_trap(0, 2); // illegal instruction trap - this->gen_sync(iss::POST_SYNC, instr_descr.size()); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(iss::vm::BRANCH, nullptr); - } -}; - -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; -} - -template vm_impl::vm_impl() { this(new ARCH()); } - -template -vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm::vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); - } -} - -template -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, llvm::BasicBlock *this_block) { - // we fetch at max 4 byte, alignment is 2 - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - try { - uint8_t *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(1, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(1, pc.val); - } - } catch (trap_access &ta) { - throw trap_access(ta.id, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, this_block); -} - -template void vm_impl::gen_leave_behavior(llvm::BasicBlock *leave_blk) { - this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); -} - -template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { - auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); - this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); -} - -template void vm_impl::gen_leave_trap(unsigned lvl) { - std::vector args{ - this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)), - }; - this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); - auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); -} - -template void vm_impl::gen_wait(unsigned type) { - std::vector args{ - this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)), - }; - this->builder.CreateCall(this->mod->getFunction("wait"), args); -} - -template void vm_impl::gen_trap_behavior(llvm::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(llvm::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, - llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, this->trap_blk, 1); -} - -} // namespace rv64ia - -template <> -std::unique_ptr create(arch::rv64ia *core, unsigned short port, bool dump) { - std::unique_ptr> ret = - std::make_unique>(*core, dump); - if (port != 0) debugger::server::run_server(ret.get(), port); - return ret; -} - -} // namespace iss diff --git a/riscv/src/iss/rv32gc.cpp b/riscv/src/iss/rv32gc.cpp index 0e9bb96..a5f3ce7 100644 --- a/riscv/src/iss/rv32gc.cpp +++ b/riscv/src/iss/rv32gc.cpp @@ -1,34 +1,34 @@ -//////////////////////////////////////////////////////////////////////////////// -// 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. -// -//////////////////////////////////////////////////////////////////////////////// +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ #include "util/ities.h" #include @@ -49,6 +49,11 @@ extern "C" { using namespace iss::arch; +constexpr std::array iss::arch::traits::reg_names; +constexpr std::array iss::arch::traits::reg_aliases; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; + rv32gc::rv32gc() { reg.icount=0; } diff --git a/riscv/src/iss/rv32imac.cpp b/riscv/src/iss/rv32imac.cpp index 86500d8..b9e4dd7 100644 --- a/riscv/src/iss/rv32imac.cpp +++ b/riscv/src/iss/rv32imac.cpp @@ -49,8 +49,10 @@ extern "C" { using namespace iss::arch; -constexpr std::array iss::arch::traits::RV32IMAC_reg_size; -constexpr std::array iss::arch::traits::RV32IMAC_reg_byte_offset; +constexpr std::array iss::arch::traits::reg_names; +constexpr std::array iss::arch::traits::reg_aliases; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; rv32imac::rv32imac() { reg.icount = 0; diff --git a/riscv/src/iss/rv64gc.cpp b/riscv/src/iss/rv64gc.cpp new file mode 100644 index 0000000..8d27912 --- /dev/null +++ b/riscv/src/iss/rv64gc.cpp @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + + + +#include "util/ities.h" +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#include +#ifdef __cplusplus +} +#endif +#include +#include +#include + +using namespace iss::arch; + +constexpr std::array iss::arch::traits::reg_names; +constexpr std::array iss::arch::traits::reg_aliases; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; + +rv64gc::rv64gc() { + reg.icount = 0; +} + +rv64gc::~rv64gc() = default; + +void rv64gc::reset(uint64_t address) { + for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits::reg_t),0)); + reg.PC=address; + reg.NEXT_PC=reg.PC; + reg.trap_state=0; + reg.machine_state=0x0; + reg.icount=0; +} + +uint8_t *rv64gc::get_regs_base_ptr() { + return reinterpret_cast(®); +} + +rv64gc::phys_addr_t rv64gc::virt2phys(const iss::addr_t &pc) { + return phys_addr_t(pc); // change logical address to physical address +} + diff --git a/riscv/src/iss/rv64i.cpp b/riscv/src/iss/rv64i.cpp new file mode 100644 index 0000000..0d09f20 --- /dev/null +++ b/riscv/src/iss/rv64i.cpp @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#include "util/ities.h" +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#include +#ifdef __cplusplus +} +#endif +#include +#include +#include + +using namespace iss::arch; + +constexpr std::array iss::arch::traits::reg_names; +constexpr std::array iss::arch::traits::reg_aliases; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; + +rv64i::rv64i() { + reg.icount = 0; +} + +rv64i::~rv64i() = default; + +void rv64i::reset(uint64_t address) { + for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits::reg_t),0)); + reg.PC=address; + reg.NEXT_PC=reg.PC; + reg.trap_state=0; + reg.machine_state=0x0; + reg.icount=0; +} + +uint8_t *rv64i::get_regs_base_ptr() { + return reinterpret_cast(®); +} + +rv64i::phys_addr_t rv64i::virt2phys(const iss::addr_t &pc) { + return phys_addr_t(pc); // change logical address to physical address +} + diff --git a/riscv/src/iss/rv64ia.cpp b/riscv/src/iss/rv64ia.cpp deleted file mode 100644 index f5f542e..0000000 --- a/riscv/src/iss/rv64ia.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// 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. -// -// Created on: Tue Sep 05 18:57:24 CEST 2017 -// * rv64ia.cpp Author: -// -//////////////////////////////////////////////////////////////////////////////// - -#include "util/ities.h" -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif -#include -#ifdef __cplusplus -} -#endif -#include -#include -#include - -using namespace iss::arch; - -rv64ia::rv64ia() { reg.icount = 0; reg.machine_state = 0x3;} - -rv64ia::~rv64ia(){} - -void rv64ia::reset(uint64_t address) { - for (size_t i = 0; i < traits::NUM_REGS; ++i) - set_reg(i, std::vector(sizeof(traits::reg_t), 0)); - reg.PC = address; - reg.NEXT_PC = reg.PC; - reg.trap_state = 0; - reg.machine_state = 0x3; - reg.icount=0; -} - -uint8_t *rv64ia::get_regs_base_ptr() { return reinterpret_cast(®); } - -rv64ia::phys_addr_t rv64ia::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address -} diff --git a/riscv/src/main.cpp b/riscv/src/main.cpp index 32c4650..54bb38c 100644 --- a/riscv/src/main.cpp +++ b/riscv/src/main.cpp @@ -38,8 +38,9 @@ #include #include #include -#include -#include +#include +#include +#include #include #include #include @@ -107,7 +108,11 @@ int main(int argc, char *argv[]) { std::unique_ptr cpu{nullptr}; std::string isa_opt(clim["isa"].as()); if (isa_opt=="rv64ia") { - iss::arch::rv64ia* lcpu = new iss::arch::riscv_hart_msu_vp(); + iss::arch::rv64i* lcpu = new iss::arch::riscv_hart_msu_vp(); + vm = iss::create(lcpu, clim["gdb-port"].as()); + cpu.reset(lcpu); + } else if (isa_opt=="rv64gc") { + iss::arch::rv64gc* lcpu = new iss::arch::riscv_hart_msu_vp(); vm = iss::create(lcpu, clim["gdb-port"].as()); cpu.reset(lcpu); } else if (isa_opt=="rv32imac") { diff --git a/riscv.sc/src/core_complex.cpp b/riscv/src/sysc/core_complex.cpp similarity index 100% rename from riscv.sc/src/core_complex.cpp rename to riscv/src/sysc/core_complex.cpp diff --git a/sc-components b/sc-components index 1859c34..fa2e0c8 160000 --- a/sc-components +++ b/sc-components @@ -1 +1 @@ -Subproject commit 1859c341ab0576c70f1cfbd67a18e3d300a5eb16 +Subproject commit fa2e0c899863a2ddba4982e157ec1cc91adb9a9b