diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..65300b8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,97 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +# should be in line with IndentWidth +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '$' +IndentCaseLabels: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +... + diff --git a/.cproject b/.cproject index 2021fe9..0f174bb 100644 --- a/.cproject +++ b/.cproject @@ -516,7 +516,6 @@ make - all VERBOSE=1 true true @@ -524,7 +523,6 @@ make - clean true true @@ -532,12 +530,35 @@ make - all true true true + + make + + clangformat + true + true + true + + + make + + riscv + true + true + true + + + make + + riscv.sc + true + true + true + diff --git a/CMakeLists.txt b/CMakeLists.txt index cecbbeb..916d87b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,9 @@ endif() FIND_PACKAGE(Threads) +set(PROJECT_3PARTY_DIRS external sr_report sr_signal) +include(sc-components/cmake/clang-format.cmake) + add_subdirectory(external) add_subdirectory(dbt-core) add_subdirectory(sc-components) diff --git a/dbt-core b/dbt-core index f23a45a..7902b61 160000 --- a/dbt-core +++ b/dbt-core @@ -1 +1 @@ -Subproject commit f23a45ab77d25ac42fd8df3e3f7206baad122c67 +Subproject commit 7902b61b2cb504defdbb48baf74c7facfa7c249c diff --git a/riscv.sc/incl/cli_options.h b/riscv.sc/incl/cli_options.h index 413d572..10090e3 100644 --- a/riscv.sc/incl/cli_options.h +++ b/riscv.sc/incl/cli_options.h @@ -1,21 +1,21 @@ /******************************************************************************* * 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 @@ -27,7 +27,7 @@ * 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 ******************************************************************************/ @@ -35,137 +35,139 @@ #ifndef _CLI_OPTIONS_H_ #define _CLI_OPTIONS_H_ #include -#include -#include #include +#include +#include namespace { const size_t ERROR_IN_COMMAND_LINE = 1; const size_t SUCCESS = 0; const size_t ERROR_UNHANDLED_EXCEPTION = 2; - -inline void enable_log_level(int level){ - switch(level){ - case 0: - logging::Logger::reporting_level()= logging::FATAL; - /* no break */ - case 1: - logging::Logger::reporting_level()= logging::ERROR; - /* no break */ - case 2: - logging::Logger::reporting_level()= logging::WARNING; - /* no break */ - case 3: - logging::Logger::reporting_level()= logging::INFO; - /* no break */ - case 4: - logging::Logger::reporting_level()= logging::DEBUG; - /* no break */ - case 5: - logging::Logger::reporting_level()= logging::TRACE; - /* no break */ - } +inline void enable_log_level(int level) { + switch (level) { + case 0: + logging::Logger::reporting_level() = logging::FATAL; + /* no break */ + case 1: + logging::Logger::reporting_level() = logging::ERROR; + /* no break */ + case 2: + logging::Logger::reporting_level() = logging::WARNING; + /* no break */ + case 3: + logging::Logger::reporting_level() = logging::INFO; + /* no break */ + case 4: + logging::Logger::reporting_level() = logging::DEBUG; + /* no break */ + case 5: + logging::Logger::reporting_level() = logging::TRACE; + /* no break */ + } } -inline void configure_default_logger(boost::program_options::variables_map& vm){ -// el::Configurations defaultConf; -// defaultConf.setToDefault(); -// defaultConf.set(el::Level::Error, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg"); -// defaultConf.set(el::Level::Warning, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg"); -// defaultConf.set(el::Level::Info, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg"); -// defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg"); -// defaultConf.set(el::Level::Trace, el::ConfigurationType::Format, "%datetime{%H:%m:%s.%g} %level %msg"); - if(vm.count("verbose")) - enable_log_level(vm["verbose"].as()); - if(vm.count("log-file")) - logging::Output2FILE::stream() = fopen(vm["log-file"].as().c_str(), "w"); - // default logger uses default configurations -// el::Loggers::reconfigureLogger("default", defaultConf); +inline void configure_default_logger(boost::program_options::variables_map &vm) { + // el::Configurations defaultConf; + // defaultConf.setToDefault(); + // defaultConf.set(el::Level::Error, el::ConfigurationType::Format, + //"%datetime{%H:%m:%s.%g} %level %msg"); + // defaultConf.set(el::Level::Warning, el::ConfigurationType::Format, + //"%datetime{%H:%m:%s.%g} %level %msg"); + // defaultConf.set(el::Level::Info, el::ConfigurationType::Format, + //"%datetime{%H:%m:%s.%g} %level %msg"); + // defaultConf.set(el::Level::Debug, el::ConfigurationType::Format, + //"%datetime{%H:%m:%s.%g} %level %msg"); + // defaultConf.set(el::Level::Trace, el::ConfigurationType::Format, + //"%datetime{%H:%m:%s.%g} %level %msg"); + if (vm.count("verbose")) enable_log_level(vm["verbose"].as()); + if (vm.count("log-file")) logging::Output2FILE::stream() = fopen(vm["log-file"].as().c_str(), "w"); + // default logger uses default configurations + // el::Loggers::reconfigureLogger("default", defaultConf); } inline void configure_debugger_logger() { - // configure the connection logger -// el::Logger* gdbServerLogger = el::Loggers::getLogger(connection); -// el::Configurations gdbServerConf; -// gdbServerConf.setToDefault(); -// gdbServerConf.set(el::Level::Error, el::ConfigurationType::Format, -// "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); -// gdbServerConf.set(el::Level::Warning, el::ConfigurationType::Format, -// "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); -// gdbServerConf.set(el::Level::Info, el::ConfigurationType::Format, -// "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); -// gdbServerConf.set(el::Level::Debug, el::ConfigurationType::Format, -// "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); -// gdbServerConf.set(el::Level::Trace, el::ConfigurationType::Format, -// "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); -// enable_log_level(gdbServerConf, 5); -// gdbServerLogger->configure(gdbServerConf); + // configure the connection logger + // el::Logger* gdbServerLogger = el::Loggers::getLogger(connection); + // el::Configurations gdbServerConf; + // gdbServerConf.setToDefault(); + // gdbServerConf.set(el::Level::Error, el::ConfigurationType::Format, + // "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); + // gdbServerConf.set(el::Level::Warning, el::ConfigurationType::Format, + // "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); + // gdbServerConf.set(el::Level::Info, el::ConfigurationType::Format, + // "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); + // gdbServerConf.set(el::Level::Debug, el::ConfigurationType::Format, + // "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); + // gdbServerConf.set(el::Level::Trace, el::ConfigurationType::Format, + // "%datetime{%H:%m:%s.%g} %level [%logger] %msg"); + // enable_log_level(gdbServerConf, 5); + // gdbServerLogger->configure(gdbServerConf); } -inline void configure_disass_logger(boost::program_options::variables_map& vm) { -// el::Logger* disassLogger = el::Loggers::getLogger(disass); -// el::Configurations disassConf; -// if(vm.count(disass)){ -// auto file_name=vm[disass].as(); -// disassConf.setToDefault(); -// if (file_name.length() > 0) { -// disassConf.set(el::Level::Global, el::ConfigurationType::ToFile, -// std::string("true")); -// disassConf.set(el::Level::Global, -// el::ConfigurationType::ToStandardOutput, std::string("false")); -// disassConf.set(el::Level::Global, el::ConfigurationType::Format, -// std::string("%msg")); -// disassConf.set(el::Level::Global, el::ConfigurationType::Filename, -// file_name); -// std::ofstream str(file_name); // just to clear the file -// } else { -// disassConf.set(el::Level::Global, el::ConfigurationType::Format, -// "%datetime{%H:%m:%s.%g} [%logger] %msg"); -// } -// } else { -// enable_log_level(disassConf, 0); -// } -// disassLogger->configure(disassConf); +inline void configure_disass_logger(boost::program_options::variables_map &vm) { + // el::Logger* disassLogger = el::Loggers::getLogger(disass); + // el::Configurations disassConf; + // if(vm.count(disass)){ + // auto file_name=vm[disass].as(); + // disassConf.setToDefault(); + // if (file_name.length() > 0) { + // disassConf.set(el::Level::Global, el::ConfigurationType::ToFile, + // std::string("true")); + // disassConf.set(el::Level::Global, + // el::ConfigurationType::ToStandardOutput, + // std::string("false")); + // disassConf.set(el::Level::Global, el::ConfigurationType::Format, + // std::string("%msg")); + // disassConf.set(el::Level::Global, + // el::ConfigurationType::Filename, + // file_name); + // std::ofstream str(file_name); // just to clear the file + // } else { + // disassConf.set(el::Level::Global, el::ConfigurationType::Format, + // "%datetime{%H:%m:%s.%g} [%logger] %msg"); + // } + // } else { + // enable_log_level(disassConf, 0); + // } + // disassLogger->configure(disassConf); } } // namespace -inline int parse_cli_options(boost::program_options::variables_map& vm, int argc, char *argv[]){ +inline int parse_cli_options(boost::program_options::variables_map &vm, int argc, char *argv[]) { namespace po = boost::program_options; po::options_description desc("Options"); - desc.add_options() - ("help,h", "Print help message") - ("verbose,v", po::value()->implicit_value(0), "Sets logging verbosity") - ("vmodule", po::value(),"Defines the module(s) to be logged") - ("logging-flags", po::value(),"Sets logging flag(s).") - ("log-file", po::value(),"Sets default log file.") - ("disass,d", po::value()->implicit_value(""),"Enables disassembly") - ("elf,l", po::value< std::vector >(), "ELF file(s) to load") - ("gdb-port,g", po::value(), "enable gdb server and specify port to use") - ("input,i", po::value(), "the elf file to load (instead of hex files)") - ("dump-ir", "dump the intermediate representation") - ("cycles,c", po::value()->default_value(-1), "number of cycles to run") - ("systemc,s", "Run as SystemC simulation") - ("time", po::value(), "SystemC siimulation time in ms") - ("reset,r", po::value(), "reset address") - ("trace", po::value(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX compressed text, 6=TX in SQLite")\ - ("mem,m", po::value(), "the memory input file") - ("rv64", "run RV64"); + desc.add_options()("help,h", "Print help message")("verbose,v", po::value()->implicit_value(0), + "Sets logging verbosity")("vmodule", po::value(), + "Defines the module(s) to be logged")( + "logging-flags", po::value(), "Sets logging flag(s).")("log-file", po::value(), + "Sets default log file.")( + "disass,d", po::value()->implicit_value(""), + "Enables disassembly")("elf,l", po::value>(), "ELF file(s) to load")( + "gdb-port,g", po::value(), "enable gdb server and specify port to use")( + "input,i", po::value(), "the elf file to load (instead of hex files)")( + "dump-ir", "dump the intermediate representation")("cycles,c", po::value()->default_value(-1), + "number of cycles to run")( + "systemc,s", "Run as SystemC simulation")("time", po::value(), "SystemC siimulation time in ms")( + "reset,r", po::value(), "reset address")( + "trace", po::value(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX " + "compressed text, 6=TX in SQLite")("mem,m", po::value(), + "the memory input file")("rv64", "run RV64"); try { po::store(po::parse_command_line(argc, argv, desc), vm); // can throw // --help option - if ( vm.count("help") ){ + if (vm.count("help")) { std::cout << "DBT-RISE-RiscV" << std::endl << desc << std::endl; return SUCCESS; } po::notify(vm); // throws on error, so do after help in case - } catch(po::error& e){ - // there are problems - std::cerr << "ERROR: " << e.what() << std::endl << std::endl; + } catch (po::error &e) { + // there are problems + std::cerr << "ERROR: " << e.what() << std::endl << std::endl; std::cerr << desc << std::endl; return ERROR_IN_COMMAND_LINE; } - return SUCCESS; + return SUCCESS; } #endif /* _CLI_OPTIONS_H_ */ diff --git a/riscv.sc/incl/sysc/SiFive/core_complex.h b/riscv.sc/incl/sysc/SiFive/core_complex.h index 8e6ef28..3d47de5 100644 --- a/riscv.sc/incl/sysc/SiFive/core_complex.h +++ b/riscv.sc/incl/sysc/SiFive/core_complex.h @@ -1,4 +1,4 @@ - //////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2017, MINRES Technologies GmbH // All rights reserved. // @@ -37,25 +37,21 @@ #ifndef _SYSC_SIFIVE_FE310_H_ #define _SYSC_SIFIVE_FE310_H_ -#include #include -#include +#include #include +#include namespace sysc { namespace SiFive { -class core_complex: - public iss::arch::riscv_hart_msu_vp, - public sc_core::sc_module { +class core_complex : public iss::arch::riscv_hart_msu_vp, public sc_core::sc_module { public: - tlm::tlm_initiator_socket<32> initiator; sc_core::sc_in rst_i; core_complex(sc_core::sc_module_name name); virtual ~core_complex(); - }; } /* namespace SiFive */ diff --git a/riscv.sc/incl/sysc/SiFive/gen/e300_plat_t.h b/riscv.sc/incl/sysc/SiFive/gen/e300_plat_t.h index cfb8984..402a1c3 100644 --- a/riscv.sc/incl/sysc/SiFive/gen/e300_plat_t.h +++ b/riscv.sc/incl/sysc/SiFive/gen/e300_plat_t.h @@ -1,6 +1,7 @@ #ifndef _E300_PLAT_MAP_H_ #define _E300_PLAT_MAP_H_ -// need double braces, see https://stackoverflow.com/questions/6893700/how-to-construct-stdarray-object-with-initializer-list#6894191 +// need double braces, see +// https://stackoverflow.com/questions/6893700/how-to-construct-stdarray-object-with-initializer-list#6894191 const std::array, 4> e300_plat_map = {{ {&i_plic, 0xc000000, 0x1000}, {&i_gpio, 0x10012000, 0x1000}, diff --git a/riscv.sc/incl/sysc/SiFive/gen/gpio_regs.h b/riscv.sc/incl/sysc/SiFive/gen/gpio_regs.h index 5e39a83..b036908 100644 --- a/riscv.sc/incl/sysc/SiFive/gen/gpio_regs.h +++ b/riscv.sc/incl/sysc/SiFive/gen/gpio_regs.h @@ -36,53 +36,50 @@ #ifndef _GPIO_REGS_H_ #define _GPIO_REGS_H_ -#include -#include #include #include +#include +#include namespace sysc { -class gpio_regs : - public sc_core::sc_module, - public sysc::resetable -{ +class gpio_regs : public sc_core::sc_module, public sysc::resetable { protected: // storage declarations uint32_t r_value; - + uint32_t r_input_en; - + uint32_t r_output_en; - + uint32_t r_port; - + uint32_t r_pue; - + uint32_t r_ds; - + uint32_t r_rise_ie; - + uint32_t r_rise_ip; - + uint32_t r_fall_ie; - + uint32_t r_fall_ip; - + uint32_t r_high_ie; - + uint32_t r_high_ip; - + uint32_t r_low_ie; - + uint32_t r_low_ip; - + uint32_t r_iof_en; - + uint32_t r_iof_sel; - + uint32_t r_out_xor; - + // register declarations sysc::sc_register value; sysc::sc_register input_en; @@ -101,12 +98,11 @@ protected: sysc::sc_register iof_en; sysc::sc_register iof_sel; sysc::sc_register out_xor; - + public: gpio_regs(sc_core::sc_module_name nm); - template - void registerResources(sysc::tlm_target& target); + template void registerResources(sysc::tlm_target &target); }; } ////////////////////////////////////////////////////////////////////////////// @@ -114,29 +110,14 @@ public: ////////////////////////////////////////////////////////////////////////////// inline sysc::gpio_regs::gpio_regs(sc_core::sc_module_name nm) -: sc_core::sc_module(nm) -, NAMED(value, r_value, 0, *this) -, NAMED(input_en, r_input_en, 0, *this) -, NAMED(output_en, r_output_en, 0, *this) -, NAMED(port, r_port, 0, *this) -, NAMED(pue, r_pue, 0, *this) -, NAMED(ds, r_ds, 0, *this) -, NAMED(rise_ie, r_rise_ie, 0, *this) -, NAMED(rise_ip, r_rise_ip, 0, *this) -, NAMED(fall_ie, r_fall_ie, 0, *this) -, NAMED(fall_ip, r_fall_ip, 0, *this) -, NAMED(high_ie, r_high_ie, 0, *this) -, NAMED(high_ip, r_high_ip, 0, *this) -, NAMED(low_ie, r_low_ie, 0, *this) -, NAMED(low_ip, r_low_ip, 0, *this) -, NAMED(iof_en, r_iof_en, 0, *this) -, NAMED(iof_sel, r_iof_sel, 0, *this) -, NAMED(out_xor, r_out_xor, 0, *this) -{ -} + : sc_core::sc_module(nm), NAMED(value, r_value, 0, *this), NAMED(input_en, r_input_en, 0, *this), + NAMED(output_en, r_output_en, 0, *this), NAMED(port, r_port, 0, *this), NAMED(pue, r_pue, 0, *this), + NAMED(ds, r_ds, 0, *this), NAMED(rise_ie, r_rise_ie, 0, *this), NAMED(rise_ip, r_rise_ip, 0, *this), + NAMED(fall_ie, r_fall_ie, 0, *this), NAMED(fall_ip, r_fall_ip, 0, *this), NAMED(high_ie, r_high_ie, 0, *this), + NAMED(high_ip, r_high_ip, 0, *this), NAMED(low_ie, r_low_ie, 0, *this), NAMED(low_ip, r_low_ip, 0, *this), + NAMED(iof_en, r_iof_en, 0, *this), NAMED(iof_sel, r_iof_sel, 0, *this), NAMED(out_xor, r_out_xor, 0, *this) {} -template -inline void sysc::gpio_regs::registerResources(sysc::tlm_target& target) { +template inline void sysc::gpio_regs::registerResources(sysc::tlm_target &target) { target.addResource(value, 0x0UL); target.addResource(input_en, 0x4UL); target.addResource(output_en, 0x8UL); diff --git a/riscv.sc/incl/sysc/SiFive/gen/plic_regs.h b/riscv.sc/incl/sysc/SiFive/gen/plic_regs.h index 936873c..c61d503 100644 --- a/riscv.sc/incl/sysc/SiFive/gen/plic_regs.h +++ b/riscv.sc/incl/sysc/SiFive/gen/plic_regs.h @@ -36,46 +36,42 @@ #ifndef _PLIC_REGS_H_ #define _PLIC_REGS_H_ -#include -#include #include #include +#include +#include namespace sysc { -class plic_regs : - public sc_core::sc_module, - public sysc::resetable -{ +class plic_regs : public sc_core::sc_module, public sysc::resetable { protected: // storage declarations BEGIN_BF_DECL(priority_t, uint32_t); - BF_FIELD(priority, 0, 3); - END_BF_DECL() ; + BF_FIELD(priority, 0, 3); + END_BF_DECL(); std::array r_priority; - + uint32_t r_pending; - + uint32_t r_enabled; - + BEGIN_BF_DECL(threshold_t, uint32_t); - BF_FIELD(threshold, 0, 3); + BF_FIELD(threshold, 0, 3); END_BF_DECL() r_threshold; - + uint32_t r_claim_complete; - + // register declarations sysc::sc_register_indexed priority; sysc::sc_register pending; sysc::sc_register enabled; sysc::sc_register threshold; sysc::sc_register claim_complete; - + public: plic_regs(sc_core::sc_module_name nm); - template - void registerResources(sysc::tlm_target& target); + template void registerResources(sysc::tlm_target &target); }; } ////////////////////////////////////////////////////////////////////////////// @@ -83,17 +79,11 @@ public: ////////////////////////////////////////////////////////////////////////////// inline sysc::plic_regs::plic_regs(sc_core::sc_module_name nm) -: sc_core::sc_module(nm) -, NAMED(priority, r_priority, 0, *this) -, NAMED(pending, r_pending, 0, *this) -, NAMED(enabled, r_enabled, 0, *this) -, NAMED(threshold, r_threshold, 0, *this) -, NAMED(claim_complete, r_claim_complete, 0, *this) -{ -} + : sc_core::sc_module(nm), NAMED(priority, r_priority, 0, *this), NAMED(pending, r_pending, 0, *this), + NAMED(enabled, r_enabled, 0, *this), NAMED(threshold, r_threshold, 0, *this), + NAMED(claim_complete, r_claim_complete, 0, *this) {} -template -inline void sysc::plic_regs::registerResources(sysc::tlm_target& target) { +template inline void sysc::plic_regs::registerResources(sysc::tlm_target &target) { target.addResource(priority, 0x4UL); target.addResource(pending, 0x1000UL); target.addResource(enabled, 0x2000UL); diff --git a/riscv.sc/incl/sysc/SiFive/gen/spi_regs.h b/riscv.sc/incl/sysc/SiFive/gen/spi_regs.h index 4eb38ef..945fe78 100644 --- a/riscv.sc/incl/sysc/SiFive/gen/spi_regs.h +++ b/riscv.sc/incl/sysc/SiFive/gen/spi_regs.h @@ -36,96 +36,93 @@ #ifndef _SPI_REGS_H_ #define _SPI_REGS_H_ -#include -#include #include #include +#include +#include namespace sysc { -class spi_regs : - public sc_core::sc_module, - public sysc::resetable -{ +class spi_regs : public sc_core::sc_module, public sysc::resetable { protected: // storage declarations BEGIN_BF_DECL(sckdiv_t, uint32_t); - BF_FIELD(div, 0, 12); + BF_FIELD(div, 0, 12); END_BF_DECL() r_sckdiv; - + BEGIN_BF_DECL(sckmode_t, uint32_t); - BF_FIELD(pha, 0, 1); - BF_FIELD(pol, 1, 1); + BF_FIELD(pha, 0, 1); + BF_FIELD(pol, 1, 1); END_BF_DECL() r_sckmode; - + uint32_t r_csid; - + uint32_t r_csdef; - + BEGIN_BF_DECL(csmode_t, uint32_t); - BF_FIELD(mode, 0, 2); + BF_FIELD(mode, 0, 2); END_BF_DECL() r_csmode; - + BEGIN_BF_DECL(delay0_t, uint32_t); - BF_FIELD(cssck, 0, 8); - BF_FIELD(sckcs, 16, 8); + BF_FIELD(cssck, 0, 8); + BF_FIELD(sckcs, 16, 8); END_BF_DECL() r_delay0; - + BEGIN_BF_DECL(delay1_t, uint32_t); - BF_FIELD(intercs, 0, 16); - BF_FIELD(interxfr, 16, 8); + BF_FIELD(intercs, 0, 16); + BF_FIELD(interxfr, 16, 8); END_BF_DECL() r_delay1; - + BEGIN_BF_DECL(fmt_t, uint32_t); - BF_FIELD(proto, 0, 2); - BF_FIELD(endian, 2, 1); - BF_FIELD(dir, 3, 1); - BF_FIELD(len, 16, 4); + BF_FIELD(proto, 0, 2); + BF_FIELD(endian, 2, 1); + BF_FIELD(dir, 3, 1); + BF_FIELD(len, 16, 4); END_BF_DECL() r_fmt; - + BEGIN_BF_DECL(txdata_t, uint32_t); - BF_FIELD(data, 0, 8); - BF_FIELD(full, 31, 1); + BF_FIELD(data, 0, 8); + BF_FIELD(full, 31, 1); END_BF_DECL() r_txdata; - + BEGIN_BF_DECL(rxdata_t, uint32_t); - BF_FIELD(data, 0, 8); - BF_FIELD(empty, 31, 1); + BF_FIELD(data, 0, 8); + BF_FIELD(empty, 31, 1); END_BF_DECL() r_rxdata; - + BEGIN_BF_DECL(txmark_t, uint32_t); - BF_FIELD(txmark, 0, 3); + BF_FIELD(txmark, 0, 3); END_BF_DECL() r_txmark; - + BEGIN_BF_DECL(rxmark_t, uint32_t); - BF_FIELD(rxmark, 0, 3); + BF_FIELD(rxmark, 0, 3); END_BF_DECL() r_rxmark; - + BEGIN_BF_DECL(fctrl_t, uint32_t); - BF_FIELD(en, 0, 1); + BF_FIELD(en, 0, 1); END_BF_DECL() r_fctrl; - + BEGIN_BF_DECL(ffmt_t, uint32_t); - BF_FIELD(cmd_en, 0, 1); - BF_FIELD(addr_len, 1, 2); - BF_FIELD(pad_cnt, 3, 4); - BF_FIELD(cmd_proto, 7, 2); - BF_FIELD(addr_proto, 9, 2); - BF_FIELD(data_proto, 11, 2); - BF_FIELD(cmd_code, 16, 8); - BF_FIELD(pad_code, 24, 8); + BF_FIELD(cmd_en, 0, 1); + BF_FIELD(addr_len, 1, 2); + BF_FIELD(pad_cnt, 3, 4); + BF_FIELD(cmd_proto, 7, 2); + BF_FIELD(addr_proto, 9, 2); + BF_FIELD(data_proto, 11, 2); + BF_FIELD(cmd_code, 16, 8); + BF_FIELD(pad_code, 24, 8); END_BF_DECL() r_ffmt; - + BEGIN_BF_DECL(ie_t, uint32_t); - BF_FIELD(txwm, 0, 1); - BF_FIELD(rxwm, 1, 1); + BF_FIELD(txwm, 0, 1); + BF_FIELD(rxwm, 1, 1); END_BF_DECL() r_ie; - + BEGIN_BF_DECL(ip_t, uint32_t); - BF_FIELD(txwm, 0, 1); - BF_FIELD(rxwm, 1, 1); + BF_FIELD(txwm, 0, 1); + BF_FIELD(rxwm, 1, 1); END_BF_DECL() r_ip; - + // register declarations sysc::sc_register sckdiv; sysc::sc_register sckmode; @@ -143,12 +140,11 @@ protected: sysc::sc_register ffmt; sysc::sc_register ie; sysc::sc_register ip; - + public: spi_regs(sc_core::sc_module_name nm); - template - void registerResources(sysc::tlm_target& target); + template void registerResources(sysc::tlm_target &target); }; } ////////////////////////////////////////////////////////////////////////////// @@ -156,28 +152,14 @@ public: ////////////////////////////////////////////////////////////////////////////// inline sysc::spi_regs::spi_regs(sc_core::sc_module_name nm) -: sc_core::sc_module(nm) -, NAMED(sckdiv, r_sckdiv, 0, *this) -, NAMED(sckmode, r_sckmode, 0, *this) -, NAMED(csid, r_csid, 0, *this) -, NAMED(csdef, r_csdef, 0, *this) -, NAMED(csmode, r_csmode, 0, *this) -, NAMED(delay0, r_delay0, 0, *this) -, NAMED(delay1, r_delay1, 0, *this) -, NAMED(fmt, r_fmt, 0, *this) -, NAMED(txdata, r_txdata, 0, *this) -, NAMED(rxdata, r_rxdata, 0, *this) -, NAMED(txmark, r_txmark, 0, *this) -, NAMED(rxmark, r_rxmark, 0, *this) -, NAMED(fctrl, r_fctrl, 0, *this) -, NAMED(ffmt, r_ffmt, 0, *this) -, NAMED(ie, r_ie, 0, *this) -, NAMED(ip, r_ip, 0, *this) -{ -} + : sc_core::sc_module(nm), NAMED(sckdiv, r_sckdiv, 0, *this), NAMED(sckmode, r_sckmode, 0, *this), + NAMED(csid, r_csid, 0, *this), NAMED(csdef, r_csdef, 0, *this), NAMED(csmode, r_csmode, 0, *this), + NAMED(delay0, r_delay0, 0, *this), NAMED(delay1, r_delay1, 0, *this), NAMED(fmt, r_fmt, 0, *this), + NAMED(txdata, r_txdata, 0, *this), NAMED(rxdata, r_rxdata, 0, *this), NAMED(txmark, r_txmark, 0, *this), + NAMED(rxmark, r_rxmark, 0, *this), NAMED(fctrl, r_fctrl, 0, *this), NAMED(ffmt, r_ffmt, 0, *this), + NAMED(ie, r_ie, 0, *this), NAMED(ip, r_ip, 0, *this) {} -template -inline void sysc::spi_regs::registerResources(sysc::tlm_target& target) { +template inline void sysc::spi_regs::registerResources(sysc::tlm_target &target) { target.addResource(sckdiv, 0x0UL); target.addResource(sckmode, 0x4UL); target.addResource(csid, 0x10UL); diff --git a/riscv.sc/incl/sysc/SiFive/gen/uart_regs.h b/riscv.sc/incl/sysc/SiFive/gen/uart_regs.h index 87382b4..9726e1e 100644 --- a/riscv.sc/incl/sysc/SiFive/gen/uart_regs.h +++ b/riscv.sc/incl/sysc/SiFive/gen/uart_regs.h @@ -36,56 +36,53 @@ #ifndef _UART_REGS_H_ #define _UART_REGS_H_ -#include -#include #include #include +#include +#include namespace sysc { -class uart_regs : - public sc_core::sc_module, - public sysc::resetable -{ +class uart_regs : public sc_core::sc_module, public sysc::resetable { protected: // storage declarations BEGIN_BF_DECL(txdata_t, uint32_t); - BF_FIELD(data, 0, 8); - BF_FIELD(full, 31, 1); + BF_FIELD(data, 0, 8); + BF_FIELD(full, 31, 1); END_BF_DECL() r_txdata; - + BEGIN_BF_DECL(rxdata_t, uint32_t); - BF_FIELD(data, 0, 8); - BF_FIELD(empty, 31, 1); + BF_FIELD(data, 0, 8); + BF_FIELD(empty, 31, 1); END_BF_DECL() r_rxdata; - + BEGIN_BF_DECL(txctrl_t, uint32_t); - BF_FIELD(txen, 0, 1); - BF_FIELD(nstop, 1, 1); - BF_FIELD(reserved, 2, 14); - BF_FIELD(txcnt, 16, 3); + BF_FIELD(txen, 0, 1); + BF_FIELD(nstop, 1, 1); + BF_FIELD(reserved, 2, 14); + BF_FIELD(txcnt, 16, 3); END_BF_DECL() r_txctrl; - + BEGIN_BF_DECL(rxctrl_t, uint32_t); - BF_FIELD(rxen, 0, 1); - BF_FIELD(reserved, 1, 15); - BF_FIELD(rxcnt, 16, 3); + BF_FIELD(rxen, 0, 1); + BF_FIELD(reserved, 1, 15); + BF_FIELD(rxcnt, 16, 3); END_BF_DECL() r_rxctrl; - + BEGIN_BF_DECL(ie_t, uint32_t); - BF_FIELD(txwm, 0, 1); - BF_FIELD(rxwm, 1, 1); + BF_FIELD(txwm, 0, 1); + BF_FIELD(rxwm, 1, 1); END_BF_DECL() r_ie; - + BEGIN_BF_DECL(ip_t, uint32_t); - BF_FIELD(txwm, 0, 1); - BF_FIELD(rxwm, 1, 1); + BF_FIELD(txwm, 0, 1); + BF_FIELD(rxwm, 1, 1); END_BF_DECL() r_ip; - + BEGIN_BF_DECL(div_t, uint32_t); - BF_FIELD(div, 0, 16); + BF_FIELD(div, 0, 16); END_BF_DECL() r_div; - + // register declarations sysc::sc_register txdata; sysc::sc_register rxdata; @@ -94,12 +91,11 @@ protected: sysc::sc_register ie; sysc::sc_register ip; sysc::sc_register div; - + public: uart_regs(sc_core::sc_module_name nm); - template - void registerResources(sysc::tlm_target& target); + template void registerResources(sysc::tlm_target &target); }; } ////////////////////////////////////////////////////////////////////////////// @@ -107,19 +103,11 @@ public: ////////////////////////////////////////////////////////////////////////////// inline sysc::uart_regs::uart_regs(sc_core::sc_module_name nm) -: sc_core::sc_module(nm) -, NAMED(txdata, r_txdata, 0, *this) -, NAMED(rxdata, r_rxdata, 0, *this) -, NAMED(txctrl, r_txctrl, 0, *this) -, NAMED(rxctrl, r_rxctrl, 0, *this) -, NAMED(ie, r_ie, 0, *this) -, NAMED(ip, r_ip, 0, *this) -, NAMED(div, r_div, 0, *this) -{ -} + : sc_core::sc_module(nm), NAMED(txdata, r_txdata, 0, *this), NAMED(rxdata, r_rxdata, 0, *this), + NAMED(txctrl, r_txctrl, 0, *this), NAMED(rxctrl, r_rxctrl, 0, *this), NAMED(ie, r_ie, 0, *this), + NAMED(ip, r_ip, 0, *this), NAMED(div, r_div, 0, *this) {} -template -inline void sysc::uart_regs::registerResources(sysc::tlm_target& target) { +template inline void sysc::uart_regs::registerResources(sysc::tlm_target &target) { target.addResource(txdata, 0x0UL); target.addResource(rxdata, 0x4UL); target.addResource(txctrl, 0x8UL); diff --git a/riscv.sc/incl/sysc/SiFive/gpio.h b/riscv.sc/incl/sysc/SiFive/gpio.h index 47e4644..04e1f07 100644 --- a/riscv.sc/incl/sysc/SiFive/gpio.h +++ b/riscv.sc/incl/sysc/SiFive/gpio.h @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2017 eyck@minres.com - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -23,13 +23,14 @@ namespace sysc { class gpio_regs; -class gpio: public sc_core::sc_module, public tlm_target<> { +class gpio : public sc_core::sc_module, public tlm_target<> { public: SC_HAS_PROCESS(gpio); sc_core::sc_in clk_i; - sc_core::sc_in rst_i; + sc_core::sc_in rst_i; gpio(sc_core::sc_module_name nm); virtual ~gpio(); + protected: void clock_cb(); void reset_cb(); diff --git a/riscv.sc/incl/sysc/SiFive/platform.h b/riscv.sc/incl/sysc/SiFive/platform.h index 5bf3d46..31fa95f 100644 --- a/riscv.sc/incl/sysc/SiFive/platform.h +++ b/riscv.sc/incl/sysc/SiFive/platform.h @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2017 eyck@minres.com - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -23,21 +23,20 @@ #ifndef SIMPLESYSTEM_H_ #define SIMPLESYSTEM_H_ -#include "uart.h" -#include "spi.h" #include "gpio.h" #include "plic.h" +#include "spi.h" +#include "uart.h" -#include -#include #include +#include +#include #include "core_complex.h" - namespace sysc { -class platform: public sc_core::sc_module { +class platform : public sc_core::sc_module { public: SC_HAS_PROCESS(platform); @@ -51,6 +50,7 @@ public: sc_core::sc_signal s_rst; platform(sc_core::sc_module_name nm); + protected: void gen_reset(); diff --git a/riscv.sc/incl/sysc/SiFive/plic.h b/riscv.sc/incl/sysc/SiFive/plic.h index 3ad1e5b..5ae5f25 100644 --- a/riscv.sc/incl/sysc/SiFive/plic.h +++ b/riscv.sc/incl/sysc/SiFive/plic.h @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2017 eyck@minres.com - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -23,13 +23,14 @@ namespace sysc { class plic_regs; -class plic: public sc_core::sc_module, public tlm_target<> { +class plic : public sc_core::sc_module, public tlm_target<> { public: SC_HAS_PROCESS(plic); sc_core::sc_in clk_i; - sc_core::sc_in rst_i; + sc_core::sc_in rst_i; plic(sc_core::sc_module_name nm); virtual ~plic(); + protected: void clock_cb(); void reset_cb(); diff --git a/riscv.sc/incl/sysc/SiFive/spi.h b/riscv.sc/incl/sysc/SiFive/spi.h index 9fcea1a..cdf5aee 100644 --- a/riscv.sc/incl/sysc/SiFive/spi.h +++ b/riscv.sc/incl/sysc/SiFive/spi.h @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2017 eyck@minres.com - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -23,13 +23,14 @@ namespace sysc { class spi_regs; -class spi: public sc_core::sc_module, public tlm_target<> { +class spi : public sc_core::sc_module, public tlm_target<> { public: SC_HAS_PROCESS(spi); sc_core::sc_in clk_i; - sc_core::sc_in rst_i; + sc_core::sc_in rst_i; spi(sc_core::sc_module_name nm); virtual ~spi(); + protected: void clock_cb(); void reset_cb(); diff --git a/riscv.sc/incl/sysc/SiFive/uart.h b/riscv.sc/incl/sysc/SiFive/uart.h index 4dc733e..6c80fc0 100644 --- a/riscv.sc/incl/sysc/SiFive/uart.h +++ b/riscv.sc/incl/sysc/SiFive/uart.h @@ -1,12 +1,12 @@ /******************************************************************************* * Copyright 2017 eyck@minres.com - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -23,13 +23,14 @@ namespace sysc { class uart_regs; -class uart: public sc_core::sc_module, public tlm_target<> { +class uart : public sc_core::sc_module, public tlm_target<> { public: SC_HAS_PROCESS(uart); sc_core::sc_in clk_i; - sc_core::sc_in rst_i; + sc_core::sc_in rst_i; uart(sc_core::sc_module_name nm); virtual ~uart(); + protected: void clock_cb(); void reset_cb(); diff --git a/riscv.sc/src/sc_main.cpp b/riscv.sc/src/sc_main.cpp index bad3bf4..8a35081 100644 --- a/riscv.sc/src/sc_main.cpp +++ b/riscv.sc/src/sc_main.cpp @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // Copyright 2017 eyck@minres.com -// +// // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -20,13 +20,13 @@ * Author: eyck@minres.com */ -#include -#include -#include #include -#include +#include #include #include +#include +#include +#include using namespace sysc; namespace po = boost::program_options; @@ -37,28 +37,26 @@ const size_t SUCCESS = 0; const size_t ERROR_UNHANDLED_EXCEPTION = 2; } // namespace -int sc_main(int argc, char* argv[]){ -// sc_report_handler::set_handler(my_report_handler); - sysc::Logger::reporting_level()=log::DEBUG; +int sc_main(int argc, char *argv[]) { + // sc_report_handler::set_handler(my_report_handler); + sysc::Logger::reporting_level() = log::DEBUG; /////////////////////////////////////////////////////////////////////////// // CLI argument parsing /////////////////////////////////////////////////////////////////////////// - po::options_description desc("Options");\ - desc.add_options()\ - ("help,h", "Print help message")\ - ("debug,d", po::value(), "set debug level")\ - ("trace,t", "trace SystemC signals"); + po::options_description desc("Options"); + desc.add_options()("help,h", "Print help message")("debug,d", po::value(), + "set debug level")("trace,t", "trace SystemC signals"); po::variables_map vm; try { po::store(po::parse_command_line(argc, argv, desc), vm); // can throw // --help option - if ( vm.count("help") ){ + if (vm.count("help")) { std::cout << "JIT-ISS simulator for AVR" << std::endl << desc << std::endl; return SUCCESS; } po::notify(vm); // throws on error, so do after help in case - // there are any problems - } catch(po::error& e){ + // there are any problems + } catch (po::error &e) { std::cerr << "ERROR: " << e.what() << std::endl << std::endl; std::cerr << desc << std::endl; return ERROR_IN_COMMAND_LINE; @@ -71,13 +69,13 @@ int sc_main(int argc, char* argv[]){ // instantiate top level /////////////////////////////////////////////////////////////////////////// platform i_simple_system("i_simple_system"); - //sr_report_handler::add_sc_object_to_filter(&i_simple_system.i_master, sc_core::SC_WARNING, sc_core::SC_MEDIUM); + // sr_report_handler::add_sc_object_to_filter(&i_simple_system.i_master, + // sc_core::SC_WARNING, sc_core::SC_MEDIUM); /////////////////////////////////////////////////////////////////////////// // run simulation /////////////////////////////////////////////////////////////////////////// sc_start(sc_core::sc_time(100, sc_core::SC_NS)); - if(!sc_end_of_simulation_invoked()) sc_stop(); + if (!sc_end_of_simulation_invoked()) sc_stop(); return 0; } - diff --git a/riscv.sc/src/sysc/core_complex.cpp b/riscv.sc/src/sysc/core_complex.cpp index c1acf0d..de360b0 100644 --- a/riscv.sc/src/sysc/core_complex.cpp +++ b/riscv.sc/src/sysc/core_complex.cpp @@ -39,12 +39,8 @@ namespace sysc { namespace SiFive { -core_complex::core_complex(sc_core::sc_module_name name) -:sc_core::sc_module(name) -, NAMED(initiator) -, NAMED(rst_i){ +core_complex::core_complex(sc_core::sc_module_name name) : sc_core::sc_module(name), NAMED(initiator), NAMED(rst_i) { // TODO Auto-generated constructor stub - } core_complex::~core_complex() { diff --git a/riscv.sc/src/sysc/gpio.cpp b/riscv.sc/src/sysc/gpio.cpp index 970e69c..c449ef2 100644 --- a/riscv.sc/src/sysc/gpio.cpp +++ b/riscv.sc/src/sysc/gpio.cpp @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // Copyright 2017 eyck@minres.com -// +// // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -21,27 +21,20 @@ namespace sysc { gpio::gpio(sc_core::sc_module_name nm) -: sc_core::sc_module(nm) -, tlm_target<>(clk) -, NAMED(clk_i) -, NAMED(rst_i) -, NAMEDD(gpio_regs, regs) -{ + : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(gpio_regs, regs) { regs->registerResources(*this); SC_METHOD(clock_cb); - sensitive<reset_start(); else regs->reset_stop(); diff --git a/riscv.sc/src/sysc/platform.cpp b/riscv.sc/src/sysc/platform.cpp index a18145c..26d6875 100644 --- a/riscv.sc/src/sysc/platform.cpp +++ b/riscv.sc/src/sysc/platform.cpp @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // Copyright 2017 eyck@minres.com -// +// // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -25,19 +25,11 @@ namespace sysc { platform::platform(sc_core::sc_module_name nm) -: sc_core::sc_module(nm) -, NAMED(i_master) -, NAMED(i_router, 4, 1) -, NAMED(i_uart) -, NAMED(i_spi) -, NAMED(i_gpio) -, NAMED(i_plic) -, NAMED(s_clk) -, NAMED(s_rst) -{ + : sc_core::sc_module(nm), NAMED(i_master), NAMED(i_router, 4, 1), NAMED(i_uart), NAMED(i_spi), NAMED(i_gpio), + NAMED(i_plic), NAMED(s_clk), NAMED(s_rst) { i_master.initiator(i_router.target[0]); - size_t i=0; - for(const auto& e: e300_plat_map){ + size_t i = 0; + for (const auto &e : e300_plat_map) { i_router.initiator.at(i)(e.target->socket); i_router.add_target_range(i, e.start, e.size); i++; @@ -58,9 +50,9 @@ platform::platform(sc_core::sc_module_name nm) } void platform::gen_reset() { - s_rst=true; + s_rst = true; wait(10_ns); - s_rst=false; + s_rst = false; } } /* namespace sysc */ diff --git a/riscv.sc/src/sysc/plic.cpp b/riscv.sc/src/sysc/plic.cpp index 41f980f..9b0153a 100644 --- a/riscv.sc/src/sysc/plic.cpp +++ b/riscv.sc/src/sysc/plic.cpp @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // Copyright 2017 eyck@minres.com -// +// // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -21,28 +21,20 @@ namespace sysc { plic::plic(sc_core::sc_module_name nm) -: sc_core::sc_module(nm) -, tlm_target<>(clk) -, NAMED(clk_i) -, NAMED(rst_i) -, NAMEDD(plic_regs, regs) -{ + : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(plic_regs, regs) { regs->registerResources(*this); SC_METHOD(clock_cb); - sensitive<clk=clk_i.read(); -} +void plic::clock_cb() { this->clk = clk_i.read(); } void plic::reset_cb() { - if(rst_i.read()) + if (rst_i.read()) regs->reset_start(); else regs->reset_stop(); diff --git a/riscv.sc/src/sysc/spi.cpp b/riscv.sc/src/sysc/spi.cpp index d5445ac..134cc48 100644 --- a/riscv.sc/src/sysc/spi.cpp +++ b/riscv.sc/src/sysc/spi.cpp @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // Copyright 2017 eyck@minres.com -// +// // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -21,28 +21,20 @@ namespace sysc { spi::spi(sc_core::sc_module_name nm) -: sc_core::sc_module(nm) -, tlm_target<>(clk) -, NAMED(clk_i) -, NAMED(rst_i) -, NAMEDD(spi_regs, regs) -{ + : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(spi_regs, regs) { regs->registerResources(*this); SC_METHOD(clock_cb); - sensitive<clk=clk_i.read(); -} +void spi::clock_cb() { this->clk = clk_i.read(); } void spi::reset_cb() { - if(rst_i.read()) + if (rst_i.read()) regs->reset_start(); else regs->reset_stop(); diff --git a/riscv.sc/src/sysc/uart.cpp b/riscv.sc/src/sysc/uart.cpp index 0e5df18..b68a712 100644 --- a/riscv.sc/src/sysc/uart.cpp +++ b/riscv.sc/src/sysc/uart.cpp @@ -1,12 +1,12 @@ //////////////////////////////////////////////////////////////////////////////// // Copyright 2017 eyck@minres.com -// +// // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the @@ -21,28 +21,20 @@ namespace sysc { uart::uart(sc_core::sc_module_name nm) -: sc_core::sc_module(nm) -, tlm_target<>(clk) -, NAMED(clk_i) -, NAMED(rst_i) -, NAMEDD(uart_regs, regs) -{ + : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(uart_regs, regs) { regs->registerResources(*this); SC_METHOD(clock_cb); - sensitive<clk=clk_i.read(); -} +void uart::clock_cb() { this->clk = clk_i.read(); } void uart::reset_cb() { - if(rst_i.read()) + if (rst_i.read()) regs->reset_start(); else regs->reset_stop(); diff --git a/riscv/incl/cli_options.h b/riscv/incl/cli_options.h index 76da009..cb32c73 100644 --- a/riscv/incl/cli_options.h +++ b/riscv/incl/cli_options.h @@ -1,21 +1,21 @@ /******************************************************************************* * 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 @@ -27,7 +27,7 @@ * 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 ******************************************************************************/ @@ -35,49 +35,47 @@ #ifndef _CLI_OPTIONS_H_ #define _CLI_OPTIONS_H_ #include -#include -#include #include +#include +#include const size_t ERROR_IN_COMMAND_LINE = 1; const size_t SUCCESS = 0; const size_t ERROR_UNHANDLED_EXCEPTION = 2; -inline int parse_cli_options(boost::program_options::variables_map& vm, int argc, char *argv[]){ +inline int parse_cli_options(boost::program_options::variables_map &vm, int argc, char *argv[]) { namespace po = boost::program_options; po::options_description desc("Options"); - desc.add_options() - ("help,h", "Print help message") - ("verbose,v", po::value()->implicit_value(0), "Sets logging verbosity") - ("vmodule", po::value(),"Defines the module(s) to be logged") - ("logging-flags", po::value(),"Sets logging flag(s).") - ("log-file", po::value(),"Sets default log file.") - ("disass,d", po::value()->implicit_value(""),"Enables disassembly") - ("elf,l", po::value< std::vector >(), "ELF file(s) to load") - ("gdb-port,g", po::value(), "enable gdb server and specify port to use") - ("input,i", po::value(), "the elf file to load (instead of hex files)") - ("dump-ir", "dump the intermediate representation") - ("cycles,c", po::value()->default_value(-1), "number of cycles to run") - ("systemc,s", "Run as SystemC simulation") - ("time", po::value(), "SystemC siimulation time in ms") - ("reset,r", po::value(), "reset address") - ("trace", po::value(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX compressed text, 6=TX in SQLite")\ - ("mem,m", po::value(), "the memory input file") - ("rv64", "run RV64"); + desc.add_options()("help,h", "Print help message")("verbose,v", po::value()->implicit_value(0), + "Sets logging verbosity")("vmodule", po::value(), + "Defines the module(s) to be logged")( + "logging-flags", po::value(), "Sets logging flag(s).")("log-file", po::value(), + "Sets default log file.")( + "disass,d", po::value()->implicit_value(""), + "Enables disassembly")("elf,l", po::value>(), "ELF file(s) to load")( + "gdb-port,g", po::value(), "enable gdb server and specify port to use")( + "input,i", po::value(), "the elf file to load (instead of hex files)")( + "dump-ir", "dump the intermediate representation")("cycles,c", po::value()->default_value(-1), + "number of cycles to run")( + "systemc,s", "Run as SystemC simulation")("time", po::value(), "SystemC siimulation time in ms")( + "reset,r", po::value(), "reset address")( + "trace", po::value(), "enable tracing, or cmbintation of 1=signals and 2=TX text, 4=TX " + "compressed text, 6=TX in SQLite")("mem,m", po::value(), + "the memory input file")("rv64", "run RV64"); try { po::store(po::parse_command_line(argc, argv, desc), vm); // can throw // --help option - if ( vm.count("help") ){ + if (vm.count("help")) { std::cout << "DBT-RISE-RiscV" << std::endl << desc << std::endl; return SUCCESS; } po::notify(vm); // throws on error, so do after help in case - } catch(po::error& e){ - // there are problems - std::cerr << "ERROR: " << e.what() << std::endl << std::endl; + } catch (po::error &e) { + // there are problems + std::cerr << "ERROR: " << e.what() << std::endl << std::endl; std::cerr << desc << std::endl; return ERROR_IN_COMMAND_LINE; } - return SUCCESS; + return SUCCESS; } #endif /* _CLI_OPTIONS_H_ */ diff --git a/riscv/incl/iss/arch/riscv_hart_msu_vp.h b/riscv/incl/iss/arch/riscv_hart_msu_vp.h index 1e5715d..086e111 100644 --- a/riscv/incl/iss/arch/riscv_hart_msu_vp.h +++ b/riscv/incl/iss/arch/riscv_hart_msu_vp.h @@ -1,21 +1,21 @@ /******************************************************************************* * 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 @@ -27,7 +27,7 @@ * 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 ******************************************************************************/ @@ -35,203 +35,186 @@ #ifndef _RISCV_CORE_H_ #define _RISCV_CORE_H_ -#include +#include +#include +#include #include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include namespace iss { namespace arch { -enum { - tohost_dflt = 0xF0001000, - fromhost_dflt = 0xF0001040 -}; +enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 }; enum csr_name { /* user-level CSR */ // User Trap Setup - ustatus=0x000, - uie=0x004, - utvec=0x005, + ustatus = 0x000, + uie = 0x004, + utvec = 0x005, // User Trap Handling - uscratch=0x040, - uepc=0x041, - ucause=0x042, - utval=0x043, - uip=0x044, + uscratch = 0x040, + uepc = 0x041, + ucause = 0x042, + utval = 0x043, + uip = 0x044, // User Floating-Point CSRs - fflags=0x001, - frm=0x002, - fcsr=0x003, + fflags = 0x001, + frm = 0x002, + fcsr = 0x003, // User Counter/Timers - cycle=0xC00, - time=0xC01, - instret=0xC02, - hpmcounter3=0xC03, - hpmcounter4=0xC04, + cycle = 0xC00, + time = 0xC01, + instret = 0xC02, + hpmcounter3 = 0xC03, + hpmcounter4 = 0xC04, /*...*/ - hpmcounter31=0xC1F, - cycleh=0xC80, - timeh=0xC81, - instreth=0xC82, - hpmcounter3h=0xC83, - hpmcounter4h=0xC84, + hpmcounter31 = 0xC1F, + cycleh = 0xC80, + timeh = 0xC81, + instreth = 0xC82, + hpmcounter3h = 0xC83, + hpmcounter4h = 0xC84, /*...*/ - hpmcounter31h=0xC9F, + hpmcounter31h = 0xC9F, /* supervisor-level CSR */ // Supervisor Trap Setup - sstatus=0x100, - sedeleg=0x102, - sideleg=0x103, - sie=0x104, - stvec=0x105, - scounteren=0x106, + sstatus = 0x100, + sedeleg = 0x102, + sideleg = 0x103, + sie = 0x104, + stvec = 0x105, + scounteren = 0x106, // Supervisor Trap Handling - sscratch=0x140, - sepc=0x141, - scause=0x142, - stval=0x143, - sip=0x144, + sscratch = 0x140, + sepc = 0x141, + scause = 0x142, + stval = 0x143, + sip = 0x144, // Supervisor Protection and Translation - satp=0x180, + satp = 0x180, /* machine-level CSR */ // Machine Information Registers - mvendorid=0xF11, - marchid=0xF12, - mimpid=0xF13, - mhartid=0xF14, + mvendorid = 0xF11, + marchid = 0xF12, + mimpid = 0xF13, + mhartid = 0xF14, // Machine Trap Setup - mstatus=0x300, - misa=0x301, - medeleg=0x302, - mideleg=0x303, - mie=0x304, - mtvec=0x305, - mcounteren=0x306, + mstatus = 0x300, + misa = 0x301, + medeleg = 0x302, + mideleg = 0x303, + mie = 0x304, + mtvec = 0x305, + mcounteren = 0x306, // Machine Trap Handling - mscratch=0x340, - mepc=0x341, - mcause=0x342, - mtval=0x343, - mip=0x344, + mscratch = 0x340, + mepc = 0x341, + mcause = 0x342, + mtval = 0x343, + mip = 0x344, // Machine Protection and Translation - pmpcfg0=0x3A0, - pmpcfg1=0x3A1, - pmpcfg2=0x3A2, - pmpcfg3=0x3A3, - pmpaddr0=0x3B0, - pmpaddr1=0x3B1, + pmpcfg0 = 0x3A0, + pmpcfg1 = 0x3A1, + pmpcfg2 = 0x3A2, + pmpcfg3 = 0x3A3, + pmpaddr0 = 0x3B0, + pmpaddr1 = 0x3B1, /*...*/ - pmpaddr15=0x3BF, + pmpaddr15 = 0x3BF, // Machine Counter/Timers - mcycle=0xB00, - minstret=0xB02, - mhpmcounter3=0xB03, - mhpmcounter4=0xB04, + mcycle = 0xB00, + minstret = 0xB02, + mhpmcounter3 = 0xB03, + mhpmcounter4 = 0xB04, /*...*/ - mhpmcounter31=0xB1F, - mcycleh=0xB80, - minstreth=0xB82, - mhpmcounter3h=0xB83, - mhpmcounter4h=0xB84, + mhpmcounter31 = 0xB1F, + mcycleh = 0xB80, + minstreth = 0xB82, + mhpmcounter3h = 0xB83, + mhpmcounter4h = 0xB84, /*...*/ - mhpmcounter31h=0xB9F, + mhpmcounter31h = 0xB9F, // Machine Counter Setup - mhpmevent3=0x323, - mhpmevent4=0x324, + mhpmevent3 = 0x323, + mhpmevent4 = 0x324, /*...*/ - mhpmevent31=0x33F, + mhpmevent31 = 0x33F, // Debug/Trace Registers (shared with Debug Mode) - tselect=0x7A0, - tdata1=0x7A1, - tdata2=0x7A2, - tdata3=0x7A3, + tselect = 0x7A0, + tdata1 = 0x7A1, + tdata2 = 0x7A2, + tdata3 = 0x7A3, // Debug Mode Registers - dcsr=0x7B0, - dpc=0x7B1, - dscratch=0x7B2 + dcsr = 0x7B0, + dpc = 0x7B1, + dscratch = 0x7B2 }; namespace { -const char lvl[]={'U', 'S', 'H', 'M'}; +const char lvl[] = {'U', 'S', 'H', 'M'}; -const char* trap_str[] = { - "Instruction address misaligned", - "Instruction access fault", - "Illegal instruction", - "Breakpoint", - "Load address misaligned", - "Load access fault", - "Store/AMO address misaligned", - "Store/AMO access fault", - "Environment call from U-mode", - "Environment call from S-mode", - "Reserved", - "Environment call from M-mode", - "Instruction page fault", - "Load page fault", - "Reserved", - "Store/AMO page fault" -}; -const char* irq_str[] = { - "User software interrupt", - "Supervisor software interrupt", - "Reserved", - "Machine software interrupt", - "User timer interrupt", - "Supervisor timer interrupt", - "Reserved", - "Machine timer interrupt", - "User external interrupt", - "Supervisor external interrupt", - "Reserved", - "Machine external interrupt" -}; +const char *trap_str[] = {"Instruction address misaligned", + "Instruction access fault", + "Illegal instruction", + "Breakpoint", + "Load address misaligned", + "Load access fault", + "Store/AMO address misaligned", + "Store/AMO access fault", + "Environment call from U-mode", + "Environment call from S-mode", + "Reserved", + "Environment call from M-mode", + "Instruction page fault", + "Load page fault", + "Reserved", + "Store/AMO page fault"}; +const char *irq_str[] = { + "User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt", + "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", + "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}; enum { - PGSHIFT=12, - PTE_PPN_SHIFT=10, + PGSHIFT = 12, + PTE_PPN_SHIFT = 10, // page table entry (PTE) fields - PTE_V = 0x001, // Valid - PTE_R = 0x002, // Read - PTE_W = 0x004, // Write - PTE_X = 0x008, // Execute - PTE_U = 0x010, // User - PTE_G = 0x020, // Global - PTE_A = 0x040, // Accessed - PTE_D = 0x080, // Dirty + PTE_V = 0x001, // Valid + PTE_R = 0x002, // Read + PTE_W = 0x004, // Write + PTE_X = 0x008, // Execute + PTE_U = 0x010, // User + PTE_G = 0x020, // Global + PTE_A = 0x040, // Accessed + PTE_D = 0x080, // Dirty PTE_SOFT = 0x300 // Reserved for Software }; -template -inline bool PTE_TABLE(T PTE){ - return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V); -} +template inline bool PTE_TABLE(T PTE) { return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V); } - -enum { PRIV_U=0, PRIV_S=1, PRIV_M=3}; +enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3 }; enum { - ISA_A=1, - ISA_B=1<<1, - ISA_C=1<<2, - ISA_D=1<<3, - ISA_E=1<<4, - ISA_F=1<<5, - ISA_G=1<<6, - ISA_I=1<<8, - ISA_M=1<<12, - ISA_N=1<<13, - ISA_Q=1<<16, - ISA_S=1<<18, - ISA_U=1<<20}; + ISA_A = 1, + ISA_B = 1 << 1, + ISA_C = 1 << 2, + ISA_D = 1 << 3, + ISA_E = 1 << 4, + ISA_F = 1 << 5, + ISA_G = 1 << 6, + ISA_I = 1 << 8, + ISA_M = 1 << 12, + ISA_N = 1 << 13, + ISA_Q = 1 << 16, + ISA_S = 1 << 18, + ISA_U = 1 << 20 +}; struct vm_info { int levels; @@ -240,165 +223,122 @@ struct vm_info { uint64_t ptbase; }; - -struct trap_load_access_fault: public trap_access { - trap_load_access_fault(uint64_t badaddr) : trap_access(5<<16, badaddr) {} +struct trap_load_access_fault : public trap_access { + trap_load_access_fault(uint64_t badaddr) : trap_access(5 << 16, badaddr) {} }; -struct illegal_instruction_fault: public trap_access { - illegal_instruction_fault(uint64_t badaddr) : trap_access(2<<16, badaddr) {} +struct illegal_instruction_fault : public trap_access { + illegal_instruction_fault(uint64_t badaddr) : trap_access(2 << 16, badaddr) {} }; -struct trap_instruction_page_fault: public trap_access { - trap_instruction_page_fault(uint64_t badaddr) : trap_access(12<<16, badaddr) {} +struct trap_instruction_page_fault : public trap_access { + trap_instruction_page_fault(uint64_t badaddr) : trap_access(12 << 16, badaddr) {} }; -struct trap_load_page_fault: public trap_access { - trap_load_page_fault(uint64_t badaddr) : trap_access(13<<16, badaddr) {} +struct trap_load_page_fault : public trap_access { + trap_load_page_fault(uint64_t badaddr) : trap_access(13 << 16, badaddr) {} }; -struct trap_store_page_fault: public trap_access { - trap_store_page_fault(uint64_t badaddr) : trap_access(15<<16, badaddr) {} +struct trap_store_page_fault : public trap_access { + trap_store_page_fault(uint64_t badaddr) : trap_access(15 << 16, badaddr) {} }; } typedef union { uint32_t val; struct /*mstatus*/ { - uint32_t - SD:1, //SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR (XS==11))) - _WPRI3:8, //unused - TSR:1, //Trap SRET - TW:1, //Timeout Wait - TVM:1, //Trap Virtual Memory - MXR:1, //Make eXecutable Readable - SUM:1, //permit Supervisor User Memory access - MPRV:1, //Modify PRiVilege - XS:2, //status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty - FS:2, //floating-point unit status Off/Initial/Clean/Dirty - MPP:2, // machine previous privilege - _WPRI2:2, // unused - SPP:1, // supervisor previous privilege - MPIE:1, //previous machine interrupt-enable - _WPRI1:1, // unused - SPIE:1, //previous supervisor interrupt-enable - UPIE:1, //previous user interrupt-enable - MIE:1, //machine interrupt-enable - _WPRI0:1, // unused - SIE:1, //supervisor interrupt-enable - UIE:1; //user interrupt-enable + uint32_t SD : 1, // SD bit is read-only and is set when either the FS or XS + // bits encode a Dirty state (i.e., SD=((FS==11) OR + // (XS==11))) + _WPRI3 : 8, // unused + TSR : 1, // Trap SRET + TW : 1, // Timeout Wait + TVM : 1, // Trap Virtual Memory + MXR : 1, // Make eXecutable Readable + SUM : 1, // permit Supervisor User Memory access + MPRV : 1, // Modify PRiVilege + XS : 2, // status of additional user-mode extensions and associated + // state, All off/None dirty or clean, some on/None dirty, some + // clean/Some dirty + FS : 2, // floating-point unit status Off/Initial/Clean/Dirty + MPP : 2, // machine previous privilege + _WPRI2 : 2, // unused + SPP : 1, // supervisor previous privilege + MPIE : 1, // previous machine interrupt-enable + _WPRI1 : 1, // unused + SPIE : 1, // previous supervisor interrupt-enable + UPIE : 1, // previous user interrupt-enable + MIE : 1, // machine interrupt-enable + _WPRI0 : 1, // unused + SIE : 1, // supervisor interrupt-enable + UIE : 1; // user interrupt-enable } m; struct /*sstatus*/ { - uint32_t - SD:1, - _WPRI4:11, - MXR:1, - SUM:1, - _WPRI3:1, - XS:2, - FS:2, - _WPRI2:4, - SPP:1, - _WPRI1:2, - SPIE:1, - UPIE:1, - _WPRI0:2, - SIE:1, - UIE:1; + uint32_t SD : 1, _WPRI4 : 11, MXR : 1, SUM : 1, _WPRI3 : 1, XS : 2, FS : 2, _WPRI2 : 4, SPP : 1, _WPRI1 : 2, + SPIE : 1, UPIE : 1, _WPRI0 : 2, SIE : 1, UIE : 1; } s; struct /*ustatus*/ { - uint32_t - SD:1, - _WPRI4:11, - MXR:1, - SUM:1, - _WPRI3:1, - XS:2, - FS:2, - _WPRI2:8, - UPIE:1, - _WPRI0:3, - UIE:1; + uint32_t SD : 1, _WPRI4 : 11, MXR : 1, SUM : 1, _WPRI3 : 1, XS : 2, FS : 2, _WPRI2 : 8, UPIE : 1, _WPRI0 : 3, + UIE : 1; } u; } mstatus32_t; typedef union { uint64_t val; struct /*mstatus*/ { - uint64_t - SD:1, // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR (XS==11))) - _WPRI4:27,// unused - SXL:2, // value of XLEN for S-mode - UXL:2, // value of XLEN for U-mode - _WPRI3:9, // unused - TSR:1, // Trap SRET - TW:1, // Timeout Wait - TVM:1, // Trap Virtual Memory - MXR:1, // Make eXecutable Readable - SUM:1, // permit Supervisor User Memory access - MPRV:1, // Modify PRiVilege - XS:2, // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty - FS:2, // floating-point unit status Off/Initial/Clean/Dirty - MPP:2, // machine previous privilege - _WPRI2:2, // unused - SPP:1, // supervisor previous privilege - MPIE:1, // previous machine interrupt-enable - _WPRI1:1, // unused - SPIE:1, // previous supervisor interrupt-enable - UPIE:1, // previous user interrupt-enable - MIE:1, // machine interrupt-enable - _WPRI0:1, // unused - SIE:1, // supervisor interrupt-enable - UIE:1; // ‚user interrupt-enable + uint64_t SD : 1, // SD bit is read-only and is set when either the FS or XS + // bits encode a Dirty state (i.e., SD=((FS==11) OR + // (XS==11))) + _WPRI4 : 27, // unused + SXL : 2, // value of XLEN for S-mode + UXL : 2, // value of XLEN for U-mode + _WPRI3 : 9, // unused + TSR : 1, // Trap SRET + TW : 1, // Timeout Wait + TVM : 1, // Trap Virtual Memory + MXR : 1, // Make eXecutable Readable + SUM : 1, // permit Supervisor User Memory access + MPRV : 1, // Modify PRiVilege + XS : 2, // status of additional user-mode extensions and associated + // state, All off/None dirty or clean, some on/None dirty, some + // clean/Some dirty + FS : 2, // floating-point unit status Off/Initial/Clean/Dirty + MPP : 2, // machine previous privilege + _WPRI2 : 2, // unused + SPP : 1, // supervisor previous privilege + MPIE : 1, // previous machine interrupt-enable + _WPRI1 : 1, // unused + SPIE : 1, // previous supervisor interrupt-enable + UPIE : 1, // previous user interrupt-enable + MIE : 1, // machine interrupt-enable + _WPRI0 : 1, // unused + SIE : 1, // supervisor interrupt-enable + UIE : 1; // ‚user interrupt-enable } m; struct /*sstatus*/ { - uint64_t - SD:1, - _WPRI5:29,// unused - UXL:2, // value of XLEN for U-mode - _WPRI4:12, - MXR:1, - SUM:1, - _WPRI3:1, - XS:2, - FS:2, - _WPRI2:4, - SPP:1, - _WPRI1:2, - SPIE:1, - UPIE:1, - _WPRI0:2, - SIE:1, - UIE:1; + uint64_t SD : 1, + _WPRI5 : 29, // unused + UXL : 2, // value of XLEN for U-mode + _WPRI4 : 12, MXR : 1, SUM : 1, _WPRI3 : 1, XS : 2, FS : 2, _WPRI2 : 4, SPP : 1, _WPRI1 : 2, SPIE : 1, + UPIE : 1, _WPRI0 : 2, SIE : 1, UIE : 1; } s; struct /*ustatus*/ { - uint32_t - SD:1, - _WPRI4:29,// unused - UXL:2, // value of XLEN for U-mode - _WPRI3:12, - MXR:1, - SUM:1, - _WPRI2:1, - XS:2, - FS:2, - _WPRI1:8, - UPIE:1, - _WPRI0:3, - UIE:1; + uint32_t SD : 1, + _WPRI4 : 29, // unused + UXL : 2, // value of XLEN for U-mode + _WPRI3 : 12, MXR : 1, SUM : 1, _WPRI2 : 1, XS : 2, FS : 2, _WPRI1 : 8, UPIE : 1, _WPRI0 : 3, UIE : 1; } u; } mstatus64_t; -template -inline vm_info decode_vm_info(uint32_t state, uint64_t sptbr); +template inline vm_info decode_vm_info(uint32_t state, uint64_t sptbr); -template<> -inline vm_info decode_vm_info<32u>(uint32_t state, uint64_t sptbr){ +template <> inline vm_info decode_vm_info<32u>(uint32_t state, uint64_t sptbr) { if (state == PRIV_M) { return {0, 0, 0, 0}; } else if (state <= PRIV_S) { - switch (bit_sub<31,1>(sptbr)) { + switch (bit_sub<31, 1>(sptbr)) { case 0: // off return {0, 0, 0, 0}; case 1: // SV32 return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; - default: abort(); + default: + abort(); } } else { abort(); @@ -406,8 +346,7 @@ inline vm_info decode_vm_info<32u>(uint32_t state, uint64_t sptbr){ return {0, 0, 0, 0}; // dummy } -template<> -inline vm_info decode_vm_info<64u>(uint32_t state, uint64_t sptbr){ +template <> inline vm_info decode_vm_info<64u>(uint32_t state, uint64_t sptbr) { if (state == PRIV_M) { return {0, 0, 0, 0}; } else if (state <= PRIV_S) { @@ -422,7 +361,8 @@ inline vm_info decode_vm_info<64u>(uint32_t state, uint64_t sptbr){ return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; case 11: // SV64 return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; - default: abort(); + default: + abort(); } } else { abort(); @@ -430,58 +370,55 @@ inline vm_info decode_vm_info<64u>(uint32_t state, uint64_t sptbr){ return {0, 0, 0, 0}; // dummy } - -constexpr uint32_t get_mask(unsigned priv_lvl, uint32_t mask){ - switch(priv_lvl){ +constexpr uint32_t get_mask(unsigned priv_lvl, uint32_t mask) { + switch (priv_lvl) { case PRIV_U: - return mask&0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 + return mask & 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 case PRIV_S: - return mask&0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011 + return mask & 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011 default: - return mask&0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011 + return mask & 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011 } } -constexpr uint64_t get_mask(unsigned priv_lvl, uint64_t mask){ - switch(priv_lvl){ +constexpr uint64_t get_mask(unsigned priv_lvl, uint64_t mask) { + switch (priv_lvl) { case PRIV_U: - return mask&0x8000000000000011ULL; //0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + return mask & 0x8000000000000011ULL; // 0b1...0 1111 0000 0000 0111 1111 + // 1111 1001 1011 1011 case PRIV_S: - return mask&0x80000003000de133ULL; //0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011 + return mask & 0x80000003000de133ULL; // 0b1...0 0011 0000 0000 0000 1101 + // 1110 0001 0011 0011 default: - return mask&0x8000000f007ff9ddULL; //0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + return mask & 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 + // 1111 1001 1011 1011 } } -constexpr uint32_t get_misa(uint32_t mask){ - return (1UL<<30)| ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M ; -} +constexpr uint32_t get_misa(uint32_t mask) { return (1UL << 30) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; } -constexpr uint64_t get_misa(uint64_t mask){ - return (2ULL<<62)| ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M ; -} +constexpr uint64_t get_misa(uint64_t mask) { return (2ULL << 62) | ISA_I | ISA_M | ISA_A | ISA_U | ISA_S | ISA_M; } -template -struct riscv_hart_msu_vp: public BASE { +template struct riscv_hart_msu_vp : public BASE { using super = BASE; using this_class = riscv_hart_msu_vp; - using virt_addr_t= typename super::virt_addr_t; - using phys_addr_t= typename super::phys_addr_t; - using reg_t = typename super::reg_t; + using virt_addr_t = typename super::virt_addr_t; + using phys_addr_t = typename super::phys_addr_t; + using reg_t = typename super::reg_t; using addr_t = typename super::addr_t; - using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t&); + using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); const typename super::reg_t PGSIZE = 1 << PGSHIFT; - const typename super::reg_t PGMASK = PGSIZE-1; + const typename super::reg_t PGMASK = PGSIZE - 1; - constexpr reg_t get_irq_mask(size_t mode){ + constexpr reg_t get_irq_mask(size_t mode) { const reg_t m[4] = { - 0b000100010001, //U mode - 0b001100110011, // S-mode - 0, - 0b101110111011 // M-mode + 0b000100010001, // U mode + 0b001100110011, // S-mode + 0, + 0b101110111011 // M-mode }; return m[mode]; } @@ -489,43 +426,44 @@ struct riscv_hart_msu_vp: public BASE { riscv_hart_msu_vp(); virtual ~riscv_hart_msu_vp(); - virtual void load_file(std::string name, int type=-1); + virtual void load_file(std::string name, int type = -1); - virtual phys_addr_t v2p(const iss::addr_t& addr); + virtual phys_addr_t v2p(const iss::addr_t &addr); - virtual iss::status read(const iss::addr_t& addr, unsigned length, uint8_t* const data) override; - virtual iss::status write(const iss::addr_t& addr, unsigned length, const uint8_t* const data) override; + virtual iss::status read(const iss::addr_t &addr, unsigned length, uint8_t *const data) override; + virtual iss::status write(const iss::addr_t &addr, unsigned length, const uint8_t *const data) override; - virtual uint64_t enter_trap(uint64_t flags) override {return riscv_hart_msu_vp::enter_trap(flags, fault_data);} + virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data); } virtual uint64_t enter_trap(uint64_t flags, uint64_t addr) override; virtual uint64_t leave_trap(uint64_t flags) override; virtual void wait_until(uint64_t flags) override; - virtual std::string get_additional_disass_info(){ + virtual std::string get_additional_disass_info() { std::stringstream s; - s<<"[p:"<reg.machine_state]<<";s:0x"<reg.icount<<"]"; + s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0') + << std::setw(sizeof(reg_t) * 2) << mstatus_r << std::dec << ";c:" << this->reg.icount << "]"; return s.str(); }; protected: - virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t* const data); - virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data); + virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data); + virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data); - virtual iss::status read_csr(unsigned addr, reg_t& val); - virtual iss::status write_csr(unsigned addr, reg_t val); + virtual iss::status read_csr(unsigned addr, reg_t &val); + virtual iss::status write_csr(unsigned addr, reg_t val); uint64_t tohost = tohost_dflt; uint64_t fromhost = fromhost_dflt; reg_t fault_data; - using mem_type = util::sparse_array; - using csr_type = util::sparse_array::reg_t, 1ULL<<12, 12>; + using mem_type = util::sparse_array; + using csr_type = util::sparse_array::reg_t, 1ULL << 12, 12>; using csr_page_type = typename csr_type::page_type; mem_type mem; csr_type csr; - reg_t& mstatus_r; - reg_t& satp_r; - unsigned to_host_wr_cnt=0; + reg_t &mstatus_r; + reg_t &satp_r; + unsigned to_host_wr_cnt = 0; std::stringstream uart_buf; std::unordered_map ptw; std::unordered_map atomic_reservation; @@ -533,90 +471,88 @@ protected: std::unordered_map csr_wr_cb; private: - iss::status read_cycle(unsigned addr, reg_t& val); - iss::status read_status(unsigned addr, reg_t& val); + iss::status read_cycle(unsigned addr, reg_t &val); + iss::status read_status(unsigned addr, reg_t &val); iss::status write_status(unsigned addr, reg_t val); - iss::status read_ie(unsigned addr, reg_t& val); + iss::status read_ie(unsigned addr, reg_t &val); iss::status write_ie(unsigned addr, reg_t val); - iss::status read_ip(unsigned addr, reg_t& val); + iss::status read_ip(unsigned addr, reg_t &val); iss::status write_ip(unsigned addr, reg_t val); - iss::status read_satp(unsigned addr, reg_t& val); + iss::status read_satp(unsigned addr, reg_t &val); iss::status write_satp(unsigned addr, reg_t val); void check_interrupt(); }; -template -riscv_hart_msu_vp::riscv_hart_msu_vp() : mstatus_r(csr[mstatus]), satp_r(csr[satp]) { - csr[misa]=traits::XLEN==32?1ULL<<(traits::XLEN-2):2ULL<<(traits::XLEN-2); +template riscv_hart_msu_vp::riscv_hart_msu_vp() : mstatus_r(csr[mstatus]), satp_r(csr[satp]) { + csr[misa] = traits::XLEN == 32 ? 1ULL << (traits::XLEN - 2) : 2ULL << (traits::XLEN - 2); uart_buf.str(""); // read-only registers - csr_wr_cb[misa]=nullptr; - for(unsigned addr=mcycle; addr<=hpmcounter31; ++addr) - csr_wr_cb[addr]=nullptr; - for(unsigned addr=mcycleh; addr<=hpmcounter31h; ++addr) - csr_wr_cb[addr]=nullptr; + csr_wr_cb[misa] = nullptr; + for (unsigned addr = mcycle; addr <= hpmcounter31; ++addr) csr_wr_cb[addr] = nullptr; + for (unsigned addr = mcycleh; addr <= hpmcounter31h; ++addr) csr_wr_cb[addr] = nullptr; // special handling - csr_rd_cb[mcycle]=&riscv_hart_msu_vp::read_cycle; - csr_rd_cb[mcycleh]=&riscv_hart_msu_vp::read_cycle; - csr_rd_cb[minstret]=&riscv_hart_msu_vp::read_cycle; - csr_rd_cb[minstreth]=&riscv_hart_msu_vp::read_cycle; - csr_rd_cb[mstatus]=&riscv_hart_msu_vp::read_status; - csr_wr_cb[mstatus]=&riscv_hart_msu_vp::write_status; - csr_rd_cb[sstatus]=&riscv_hart_msu_vp::read_status; - csr_wr_cb[sstatus]=&riscv_hart_msu_vp::write_status; - csr_rd_cb[ustatus]=&riscv_hart_msu_vp::read_status; - csr_wr_cb[ustatus]=&riscv_hart_msu_vp::write_status; - csr_rd_cb[mip]=&riscv_hart_msu_vp::read_ip; - csr_wr_cb[mip]=&riscv_hart_msu_vp::write_ip; - csr_rd_cb[sip]=&riscv_hart_msu_vp::read_ip; - csr_wr_cb[sip]=&riscv_hart_msu_vp::write_ip; - csr_rd_cb[uip]=&riscv_hart_msu_vp::read_ip; - csr_wr_cb[uip]=&riscv_hart_msu_vp::write_ip; - csr_rd_cb[mie]=&riscv_hart_msu_vp::read_ie; - csr_wr_cb[mie]=&riscv_hart_msu_vp::write_ie; - csr_rd_cb[sie]=&riscv_hart_msu_vp::read_ie; - csr_wr_cb[sie]=&riscv_hart_msu_vp::write_ie; - csr_rd_cb[uie]=&riscv_hart_msu_vp::read_ie; - csr_wr_cb[uie]=&riscv_hart_msu_vp::write_ie; - csr_rd_cb[satp]=&riscv_hart_msu_vp::read_satp; - csr_wr_cb[satp]=&riscv_hart_msu_vp::write_satp; + csr_rd_cb[mcycle] = &riscv_hart_msu_vp::read_cycle; + csr_rd_cb[mcycleh] = &riscv_hart_msu_vp::read_cycle; + csr_rd_cb[minstret] = &riscv_hart_msu_vp::read_cycle; + csr_rd_cb[minstreth] = &riscv_hart_msu_vp::read_cycle; + csr_rd_cb[mstatus] = &riscv_hart_msu_vp::read_status; + csr_wr_cb[mstatus] = &riscv_hart_msu_vp::write_status; + csr_rd_cb[sstatus] = &riscv_hart_msu_vp::read_status; + csr_wr_cb[sstatus] = &riscv_hart_msu_vp::write_status; + csr_rd_cb[ustatus] = &riscv_hart_msu_vp::read_status; + csr_wr_cb[ustatus] = &riscv_hart_msu_vp::write_status; + csr_rd_cb[mip] = &riscv_hart_msu_vp::read_ip; + csr_wr_cb[mip] = &riscv_hart_msu_vp::write_ip; + csr_rd_cb[sip] = &riscv_hart_msu_vp::read_ip; + csr_wr_cb[sip] = &riscv_hart_msu_vp::write_ip; + csr_rd_cb[uip] = &riscv_hart_msu_vp::read_ip; + csr_wr_cb[uip] = &riscv_hart_msu_vp::write_ip; + csr_rd_cb[mie] = &riscv_hart_msu_vp::read_ie; + csr_wr_cb[mie] = &riscv_hart_msu_vp::write_ie; + csr_rd_cb[sie] = &riscv_hart_msu_vp::read_ie; + csr_wr_cb[sie] = &riscv_hart_msu_vp::write_ie; + csr_rd_cb[uie] = &riscv_hart_msu_vp::read_ie; + csr_wr_cb[uie] = &riscv_hart_msu_vp::write_ie; + csr_rd_cb[satp] = &riscv_hart_msu_vp::read_satp; + csr_wr_cb[satp] = &riscv_hart_msu_vp::write_satp; } -template -riscv_hart_msu_vp::~riscv_hart_msu_vp() { -} +template riscv_hart_msu_vp::~riscv_hart_msu_vp() {} -template -void riscv_hart_msu_vp::load_file(std::string name, int type) { - FILE* fp = fopen(name.c_str(), "r"); - if(fp){ +template void riscv_hart_msu_vp::load_file(std::string name, int type) { + FILE *fp = fopen(name.c_str(), "r"); + if (fp) { char buf[5]; - auto n = fread(buf, 1,4,fp); - if(n!=4) throw std::runtime_error("input file has insufficient size"); - buf[4]=0; - if(strcmp(buf+1, "ELF")==0){ + auto n = fread(buf, 1, 4, fp); + if (n != 4) throw std::runtime_error("input file has insufficient size"); + buf[4] = 0; + if (strcmp(buf + 1, "ELF") == 0) { fclose(fp); - //Create elfio reader + // Create elfio reader ELFIO::elfio reader; // Load ELF data - if ( !reader.load( name ) ) throw std::runtime_error("could not process elf file"); + if (!reader.load(name)) throw std::runtime_error("could not process elf file"); // check elf properties - //TODO: fix ELFCLASS like: - // if ( reader.get_class() != ELFCLASS32 ) throw std::runtime_error("wrong elf class in file"); - if ( reader.get_type() != ET_EXEC ) throw std::runtime_error("wrong elf type in file"); - //TODO: fix machine type like: - // if ( reader.get_machine() != EM_RISCV ) throw std::runtime_error("wrong elf machine in file"); - for (const auto pseg :reader.segments ) { - const auto fsize=pseg->get_file_size(); // 0x42c/0x0 - const auto seg_data=pseg->get_data(); - if(fsize>0){ - this->write(typed_addr_t(iss::DEBUG_WRITE, traits::MEM, pseg->get_virtual_address()), fsize, reinterpret_cast(seg_data)); + // TODO: fix ELFCLASS like: + // if ( reader.get_class() != ELFCLASS32 ) throw std::runtime_error("wrong + // elf class in file"); + if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file"); + // TODO: fix machine type like: + // if ( reader.get_machine() != EM_RISCV ) throw std::runtime_error("wrong + // elf machine in file"); + for (const auto pseg : reader.segments) { + const auto fsize = pseg->get_file_size(); // 0x42c/0x0 + const auto seg_data = pseg->get_data(); + if (fsize > 0) { + this->write( + typed_addr_t(iss::DEBUG_WRITE, traits::MEM, pseg->get_virtual_address()), fsize, + reinterpret_cast(seg_data)); } } - for (const auto sec :reader.sections ) { - if(sec->get_name() == ".tohost"){ - tohost=sec->get_address(); - fromhost=tohost+0x40; + for (const auto sec : reader.sections) { + if (sec->get_name() == ".tohost") { + tohost = sec->get_address(); + fromhost = tohost + 0x40; } } return; @@ -624,451 +560,426 @@ void riscv_hart_msu_vp::load_file(std::string name, int type) { } } -template -iss::status riscv_hart_msu_vp::read(const iss::addr_t& addr, unsigned length, uint8_t* const data){ +template +iss::status riscv_hart_msu_vp::read(const iss::addr_t &addr, unsigned length, uint8_t *const data) { #ifndef NDEBUG - if(addr.type& iss::DEBUG){ - LOG(DEBUG)<<"debug read of "<::MEM:{ - if((addr.type&(iss::ACCESS_TYPE-iss::DEBUG))==iss::FETCH && (addr.val&0x1) == 1){ - fault_data=addr.val; - if((addr.type&iss::DEBUG)) - throw trap_access(0, addr.val); - this->reg.trap_state=(1<<31); // issue trap 0 + switch (addr.space) { + case traits::MEM: { + if ((addr.type & (iss::ACCESS_TYPE - iss::DEBUG)) == iss::FETCH && (addr.val & 0x1) == 1) { + fault_data = addr.val; + if ((addr.type & iss::DEBUG)) throw trap_access(0, addr.val); + this->reg.trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { - if((addr.val&~PGMASK) != ((addr.val+length-1)&~PGMASK)){ // we may cross a page boundary + if ((addr.val & ~PGMASK) != ((addr.val + length - 1) & ~PGMASK)) { // we may cross a page boundary vm_info vm = decode_vm_info::XLEN>(this->reg.machine_state, csr[satp]); - if(vm.levels!=0){ // VM is active - auto split_addr = (addr.val+length)&~PGMASK; - auto len1=split_addr-addr.val; + if (vm.levels != 0) { // VM is active + auto split_addr = (addr.val + length) & ~PGMASK; + auto len1 = split_addr - addr.val; auto res = read(addr, len1, data); - if(res==iss::Ok) - res = read(iss::addr_t{addr.type, addr.space, split_addr}, length-len1, data+len1); + if (res == iss::Ok) + res = read(iss::addr_t{addr.type, addr.space, split_addr}, length - len1, data + len1); return res; } } - phys_addr_t paddr = (addr.type&iss::ADDRESS_TYPE)==iss::PHYSICAL?addr:v2p(addr); - if((paddr.val +length)>mem.size()) return iss::Err; - switch(paddr.val){ - case 0x0200BFF8:{ // CLINT base, mtime reg - uint64_t mtime = this->reg.icount>>12/*12*/; - std::copy((uint8_t*)&mtime, ((uint8_t*)&mtime)+length, data); + phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr); + if ((paddr.val + length) > mem.size()) return iss::Err; + switch (paddr.val) { + case 0x0200BFF8: { // CLINT base, mtime reg + uint64_t mtime = this->reg.icount >> 12 /*12*/; + std::copy((uint8_t *)&mtime, ((uint8_t *)&mtime) + length, data); + } break; + case 0x10008000: { + const mem_type::page_type &p = mem(paddr.val / mem.page_size); + uint64_t offs = paddr.val & mem.page_addr_mask; + std::copy(p.data() + offs, p.data() + offs + length, data); + if (this->reg.icount > 30000) data[3] |= 0x80; + } break; + default: { return read_mem(paddr, length, data); } } - break; - case 0x10008000:{ - const mem_type::page_type& p = mem(paddr.val/mem.page_size); - uint64_t offs=paddr.val&mem.page_addr_mask; - std::copy( - p.data() + offs, - p.data() + offs+length, - data); - if(this->reg.icount>30000) - data[3]|=0x80; - } - break; - default:{ - return read_mem(paddr, length, data); - } - } - } catch(trap_access& ta){ - this->reg.trap_state=(1<<31)|ta.id; + } catch (trap_access &ta) { + this->reg.trap_state = (1 << 31) | ta.id; return iss::Err; } - } - break; - case traits::CSR:{ - if(length!=sizeof(reg_t)) return iss::Err; - return read_csr(addr.val, *reinterpret_cast(data)); - } - break; - case traits::FENCE:{ - if((addr.val +length)>mem.size()) return iss::Err; - switch(addr.val){ - case 2: // SFENCE:VMA lower - case 3:{// SFENCE:VMA upper + } break; + case traits::CSR: { + if (length != sizeof(reg_t)) return iss::Err; + return read_csr(addr.val, *reinterpret_cast(data)); + } break; + case traits::FENCE: { + if ((addr.val + length) > mem.size()) return iss::Err; + switch (addr.val) { + case 2: // SFENCE:VMA lower + case 3: { // SFENCE:VMA upper auto status = csr[mstatus]; - auto tvm = status&(1<<20); - if(this->reg.machine_state==PRIV_S & tvm!=0){ - this->reg.trap_state=(1<<31)|(2<<16); - this->fault_data=this->reg.PC; + auto tvm = status & (1 << 20); + if (this->reg.machine_state == PRIV_S & tvm != 0) { + this->reg.trap_state = (1 << 31) | (2 << 16); + this->fault_data = this->reg.PC; return iss::Err; } return iss::Ok; } } - } - break; - case traits::RES:{ + } break; + case traits::RES: { auto it = atomic_reservation.find(addr.val); - if(it!= atomic_reservation.end() && (*it).second != 0){ + if (it != atomic_reservation.end() && (*it).second != 0) { memset(data, 0xff, length); atomic_reservation.erase(addr.val); } else memset(data, 0, length); - } - break; + } break; default: - return iss::Err; //assert("Not supported"); + return iss::Err; // assert("Not supported"); } return iss::Ok; } -template -iss::status riscv_hart_msu_vp::write(const iss::addr_t& addr, unsigned length, const uint8_t* const data){ +template +iss::status riscv_hart_msu_vp::write(const iss::addr_t &addr, unsigned length, const uint8_t *const data) { #ifndef NDEBUG - const char* prefix = addr.type & iss::DEBUG?"debug ":""; - switch(length){ + const char *prefix = addr.type & iss::DEBUG ? "debug " : ""; + switch (length) { case 8: - LOG(DEBUG)<::MEM:{ - phys_addr_t paddr = (addr.type&iss::ADDRESS_TYPE)==iss::PHYSICAL?addr:v2p(addr); - if((paddr.val +length)>mem.size()) return iss::Err; - switch(paddr.val){ + switch (addr.space) { + case traits::MEM: { + phys_addr_t paddr = (addr.type & iss::ADDRESS_TYPE) == iss::PHYSICAL ? addr : v2p(addr); + if ((paddr.val + length) > mem.size()) return iss::Err; + switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg - uart_buf<<(char)data[0]; - if(((char)data[0])=='\n' || data[0]==0){ - // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<>16)&0x3)<<" send + // '"<::CSR:{ - if(length!=sizeof(reg_t)) return iss::Err; - return write_csr(addr.val, *reinterpret_cast(data)); - } - break; - case traits::FENCE:{ - if((addr.val +length)>mem.size()) return iss::Err; - switch(addr.val){ + } break; + case traits::CSR: { + if (length != sizeof(reg_t)) return iss::Err; + return write_csr(addr.val, *reinterpret_cast(data)); + } break; + case traits::FENCE: { + if ((addr.val + length) > mem.size()) return iss::Err; + switch (addr.val) { case 2: - case 3:{ + case 3: { ptw.clear(); auto status = csr[mstatus]; - auto tvm = status&(1<<20); - if(this->reg.machine_state==PRIV_S & tvm!=0){ - this->reg.trap_state=(1<<31)|(2<<16); - this->fault_data=this->reg.PC; + auto tvm = status & (1 << 20); + if (this->reg.machine_state == PRIV_S & tvm != 0) { + this->reg.trap_state = (1 << 31) | (2 << 16); + this->fault_data = this->reg.PC; return iss::Err; } return iss::Ok; } } - } - break; - case traits::RES:{ + } break; + case traits::RES: { atomic_reservation[addr.val] = data[0]; - } - break; + } break; default: return iss::Err; } return iss::Ok; - } catch(trap_access& ta){ - this->reg.trap_state=(1<<31)|ta.id; + } catch (trap_access &ta) { + this->reg.trap_state = (1 << 31) | ta.id; return iss::Err; } } -template -iss::status riscv_hart_msu_vp::read_csr(unsigned addr, reg_t& val){ - if(addr >= csr.size()) return iss::Err; +template iss::status riscv_hart_msu_vp::read_csr(unsigned addr, reg_t &val) { + if (addr >= csr.size()) return iss::Err; auto it = csr_rd_cb.find(addr); - if(it == csr_rd_cb.end()){ - val=csr[addr&csr.page_addr_mask]; + if (it == csr_rd_cb.end()) { + val = csr[addr & csr.page_addr_mask]; return iss::Ok; } - rd_csr_f f=it->second; - if(f==nullptr) - throw illegal_instruction_fault(this->fault_data); + rd_csr_f f = it->second; + if (f == nullptr) throw illegal_instruction_fault(this->fault_data); return (this->*f)(addr, val); } -template -iss::status riscv_hart_msu_vp::write_csr(unsigned addr, reg_t val){ - if(addr>=csr.size()) return iss::Err; +template iss::status riscv_hart_msu_vp::write_csr(unsigned addr, reg_t val) { + if (addr >= csr.size()) return iss::Err; auto it = csr_wr_cb.find(addr); - if(it == csr_wr_cb.end()){ - csr[addr&csr.page_addr_mask] = val; + if (it == csr_wr_cb.end()) { + csr[addr & csr.page_addr_mask] = val; return iss::Ok; } - wr_csr_f f=it->second; - if(f==nullptr) - throw illegal_instruction_fault(this->fault_data); + wr_csr_f f = it->second; + if (f == nullptr) throw illegal_instruction_fault(this->fault_data); return (this->*f)(addr, val); - } -template -iss::status riscv_hart_msu_vp::read_cycle(unsigned addr, reg_t& val) { - if( addr== mcycle) { +template iss::status riscv_hart_msu_vp::read_cycle(unsigned addr, reg_t &val) { + if (addr == mcycle) { val = static_cast(this->reg.icount); - }else if(addr==mcycleh) { - if(sizeof(typename traits::reg_t)!=4) return iss::Err; - val = static_cast((this->reg.icount)>>32); + } else if (addr == mcycleh) { + if (sizeof(typename traits::reg_t) != 4) return iss::Err; + val = static_cast((this->reg.icount) >> 32); } return iss::Ok; } -template -iss::status riscv_hart_msu_vp::read_status(unsigned addr, reg_t& val) { - auto req_priv_lvl=addr>>8; - if(this->reg.machine_statefault_data); - auto mask = get_mask(req_priv_lvl, (reg_t) (std::numeric_limits::max())); +template iss::status riscv_hart_msu_vp::read_status(unsigned addr, reg_t &val) { + auto req_priv_lvl = addr >> 8; + if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); + auto mask = get_mask(req_priv_lvl, (reg_t)(std::numeric_limits::max())); val = csr[mstatus] & mask; return iss::Ok; } -template -iss::status riscv_hart_msu_vp::write_status(unsigned addr, reg_t val) { - auto req_priv_lvl=addr>>8; - if(this->reg.machine_statefault_data); - auto mask=get_mask(req_priv_lvl, (reg_t)std::numeric_limits::max()); - auto old_val=csr[mstatus]; - auto new_val = (old_val&~mask) |(val&mask); +template iss::status riscv_hart_msu_vp::write_status(unsigned addr, reg_t val) { + auto req_priv_lvl = addr >> 8; + if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); + auto mask = get_mask(req_priv_lvl, (reg_t)std::numeric_limits::max()); + auto old_val = csr[mstatus]; + auto new_val = (old_val & ~mask) | (val & mask); csr[mstatus] = new_val; check_interrupt(); return iss::Ok; } -template -iss::status riscv_hart_msu_vp::read_ie(unsigned addr, reg_t& val) { - auto req_priv_lvl=addr>>8; - if(this->reg.machine_statefault_data); +template iss::status riscv_hart_msu_vp::read_ie(unsigned addr, reg_t &val) { + auto req_priv_lvl = addr >> 8; + if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); val = csr[mie]; - if(addr -iss::status riscv_hart_msu_vp::write_ie(unsigned addr, reg_t val) { - auto req_priv_lvl=addr>>8; - if(this->reg.machine_statefault_data); - auto mask=get_irq_mask(req_priv_lvl); +template iss::status riscv_hart_msu_vp::write_ie(unsigned addr, reg_t val) { + auto req_priv_lvl = addr >> 8; + if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); + auto mask = get_irq_mask(req_priv_lvl); csr[mie] = (csr[mie] & ~mask) | (val & mask); check_interrupt(); return iss::Ok; } -template -iss::status riscv_hart_msu_vp::read_ip(unsigned addr, reg_t& val) { - auto req_priv_lvl=addr>>8; - if(this->reg.machine_statefault_data); +template iss::status riscv_hart_msu_vp::read_ip(unsigned addr, reg_t &val) { + auto req_priv_lvl = addr >> 8; + if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); val = csr[mie]; - if(addr -iss::status riscv_hart_msu_vp::write_ip(unsigned addr, reg_t val) { - auto req_priv_lvl=addr>>8; - if(this->reg.machine_statefault_data); - auto mask=get_irq_mask(req_priv_lvl); +template iss::status riscv_hart_msu_vp::write_ip(unsigned addr, reg_t val) { + auto req_priv_lvl = addr >> 8; + if (this->reg.machine_state < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); + auto mask = get_irq_mask(req_priv_lvl); csr[mip] = (csr[mip] & ~mask) | (val & mask); check_interrupt(); return iss::Ok; } -template -iss::status riscv_hart_msu_vp::read_satp(unsigned addr, reg_t& val){ +template iss::status riscv_hart_msu_vp::read_satp(unsigned addr, reg_t &val) { auto status = csr[mstatus]; - auto tvm = status&(1<<20); - if(this->reg.machine_state==PRIV_S & tvm!=0){ - this->reg.trap_state=(1<<31)|(2<<16); - this->fault_data=this->reg.PC; + auto tvm = status & (1 << 20); + if (this->reg.machine_state == PRIV_S & tvm != 0) { + this->reg.trap_state = (1 << 31) | (2 << 16); + this->fault_data = this->reg.PC; return iss::Err; } val = csr[satp]; return iss::Ok; } -template -iss::status riscv_hart_msu_vp::write_satp(unsigned addr, reg_t val){ +template iss::status riscv_hart_msu_vp::write_satp(unsigned addr, reg_t val) { auto status = csr[mstatus]; - auto tvm = status&(1<<20); - if(this->reg.machine_state==PRIV_S & tvm!=0){ - this->reg.trap_state=(1<<31)|(2<<16); - this->fault_data=this->reg.PC; + auto tvm = status & (1 << 20); + if (this->reg.machine_state == PRIV_S & tvm != 0) { + this->reg.trap_state = (1 << 31) | (2 << 16); + this->fault_data = this->reg.PC; return iss::Err; } csr[satp] = val; return iss::Ok; } -template -iss::status riscv_hart_msu_vp::read_mem(phys_addr_t addr, unsigned length, uint8_t* const data) { - const auto& p = mem(addr.val/mem.page_size); - auto offs=addr.val&mem.page_addr_mask; - std::copy(p.data() + offs, p.data() + offs+length, data); +template +iss::status riscv_hart_msu_vp::read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) { + const auto &p = mem(addr.val / mem.page_size); + auto offs = addr.val & mem.page_addr_mask; + std::copy(p.data() + offs, p.data() + offs + length, data); return iss::Ok; } -template -iss::status riscv_hart_msu_vp::write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data) { - mem_type::page_type& p = mem(addr.val/mem.page_size); - std::copy(data, data+length, p.data()+(addr.val&mem.page_addr_mask)); +template +iss::status riscv_hart_msu_vp::write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) { + mem_type::page_type &p = mem(addr.val / mem.page_size); + std::copy(data, data + length, p.data() + (addr.val & mem.page_addr_mask)); // tohost handling in case of riscv-test - if((addr.type & iss::DEBUG)==0){ - auto tohost_upper = (traits::XLEN==32 && addr.val == (tohost+4)) || (traits::XLEN==64 && addr.val == tohost); - auto tohost_lower = (traits::XLEN==32 && addr.val == tohost) || (traits::XLEN==64 && addr.val == tohost); - if(tohost_lower || tohost_upper){ - uint64_t hostvar = *reinterpret_cast(p.data()+(tohost&mem.page_addr_mask)); - if(tohost_upper || (tohost_lower && to_host_wr_cnt>0)){ - switch(hostvar>>48){ + if ((addr.type & iss::DEBUG) == 0) { + auto tohost_upper = + (traits::XLEN == 32 && addr.val == (tohost + 4)) || (traits::XLEN == 64 && addr.val == tohost); + auto tohost_lower = + (traits::XLEN == 32 && addr.val == tohost) || (traits::XLEN == 64 && addr.val == tohost); + if (tohost_lower || tohost_upper) { + uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); + if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { + switch (hostvar >> 48) { case 0: - if(hostvar!=0x1) - LOG(FATAL)<<"tohost value is 0x"<(hostvar & 0xff); - if(c=='\n' || c==0){ - LOG(INFO)<<"tohost send '"<::XLEN==32 && addr.val == fromhost+4) || (traits::XLEN==64 && addr.val == fromhost)){ - uint64_t fhostvar = *reinterpret_cast(p.data()+(fromhost&mem.page_addr_mask)); - *reinterpret_cast(p.data()+(tohost&mem.page_addr_mask)) = fhostvar; + } else if (tohost_lower) + to_host_wr_cnt++; + } else if ((traits::XLEN == 32 && addr.val == fromhost + 4) || + (traits::XLEN == 64 && addr.val == fromhost)) { + uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); + *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; } } return iss::Ok; } -template -void riscv_hart_msu_vp::check_interrupt(){ +template void riscv_hart_msu_vp::check_interrupt() { auto status = csr[mstatus]; auto ip = csr[mip]; auto ie = csr[mie]; auto ideleg = csr[mideleg]; - // Multiple simultaneous interrupts and traps at the same privilege level are handled in the following decreasing priority order: - // external interrupts, software interrupts, timer interrupts, then finally any synchronous traps. - auto ena_irq=ip&ie; + // Multiple simultaneous interrupts and traps at the same privilege level are + // handled in the following decreasing priority order: + // external interrupts, software interrupts, timer interrupts, then finally + // any synchronous traps. + auto ena_irq = ip & ie; - auto mie = (csr[mstatus]>>3)&1; + auto mie = (csr[mstatus] >> 3) & 1; auto m_enabled = this->reg.machine_state < PRIV_M || (this->reg.machine_state == PRIV_M && mie); - auto enabled_interrupts = m_enabled?ena_irq & ~ideleg :0; + auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0; - if (enabled_interrupts == 0){ - auto sie = (csr[mstatus]>>1)&1; + if (enabled_interrupts == 0) { + auto sie = (csr[mstatus] >> 1) & 1; auto s_enabled = this->reg.machine_state < PRIV_S || (this->reg.machine_state == PRIV_S && sie); - enabled_interrupts = s_enabled?ena_irq & ideleg : 0; + enabled_interrupts = s_enabled ? ena_irq & ideleg : 0; } - if (enabled_interrupts!=0){ + if (enabled_interrupts != 0) { int res = 0; - while ((enabled_interrupts & 1) == 0) - enabled_interrupts >>= 1, res++; - this->reg.pending_trap = res<<16 | 1; + while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++; + this->reg.pending_trap = res << 16 | 1; } - } -template -typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::v2p(const iss::addr_t& addr){ - const uint64_t tmp = reg_t(1) << (traits::XLEN-1); - const uint64_t msk = tmp | (tmp-1); +template +typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::v2p(const iss::addr_t &addr) { + const uint64_t tmp = reg_t(1) << (traits::XLEN - 1); + const uint64_t msk = tmp | (tmp - 1); - if(addr.space!=traits::MEM){ //non-memory access + if (addr.space != traits::MEM) { // non-memory access phys_addr_t ret(addr); ret.val &= msk; return ret; } - const access_type type = (access_type)(addr.getAccessType()&~iss::DEBUG); - uint32_t mode =type != iss::FETCH && bit_sub<17,1>(mstatus_r)? // MPRV - mode = bit_sub<11,2>(mstatus_r):// MPV - this->reg.machine_state; + const access_type type = (access_type)(addr.getAccessType() & ~iss::DEBUG); + uint32_t mode = type != iss::FETCH && bit_sub<17, 1>(mstatus_r) ? // MPRV + mode = bit_sub<11, 2>(mstatus_r) + : // MPV + this->reg.machine_state; const vm_info vm = decode_vm_info::XLEN>(mode, satp_r); - if (vm.levels == 0){ + if (vm.levels == 0) { phys_addr_t ret(addr); ret.val &= msk; return ret; } const bool s_mode = mode == PRIV_S; - const bool sum = bit_sub<18,1>(mstatus_r); // MSTATUS_SUM); - const bool mxr = bit_sub<19,1>(mstatus_r);// MSTATUS_MXR); + const bool sum = bit_sub<18, 1>(mstatus_r); // MSTATUS_SUM); + const bool mxr = bit_sub<19, 1>(mstatus_r); // MSTATUS_MXR); auto it = ptw.find(addr.val >> PGSHIFT); - if(it!=ptw.end()){ - const reg_t pte=it->second; + if (it != ptw.end()) { + const reg_t pte = it->second; const reg_t ad = PTE_A | ((type == iss::WRITE) * PTE_D); #ifdef RISCV_ENABLE_DIRTY // set accessed and possibly dirty bits. - *(uint32_t*)ppte |= ad; - return {addr.getAccessType(), addr.space, (pte&(~PGMASK)) | (addr.val & PGMASK)}; + *(uint32_t *)ppte |= ad; + return {addr.getAccessType(), addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)}; #else // take exception if access or possibly dirty bit is not set. if ((pte & ad) == ad) - return {addr.getAccessType(), addr.space, (pte&(~PGMASK)) | (addr.val & PGMASK)}; + return {addr.getAccessType(), addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)}; else ptw.erase(it); #endif } else { // verify bits xlen-1:va_bits-1 are all equal const int va_bits = PGSHIFT + vm.levels * vm.idxbits; - const reg_t mask = (reg_t(1) << (traits::XLEN> - (va_bits-1))) - 1; - const reg_t masked_msbs = (addr.val >> (va_bits-1)) & mask; - const int levels = (masked_msbs != 0 && masked_msbs != mask)? 0: vm.levels; + const reg_t mask = (reg_t(1) << (traits::XLEN > -(va_bits - 1))) - 1; + const reg_t masked_msbs = (addr.val >> (va_bits - 1)) & mask; + const int levels = (masked_msbs != 0 && masked_msbs != mask) ? 0 : vm.levels; reg_t base = vm.ptbase; for (int i = levels - 1; i >= 0; i--) { @@ -1077,9 +988,10 @@ typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::v2p(const // check that physical address of PTE is legal reg_t pte = 0; - const uint8_t res = this->read(phys_addr_t(addr.getAccessType(), traits::MEM, base + idx * vm.ptesize), vm.ptesize, (uint8_t*)&pte); - if (res!=0) - throw trap_load_access_fault(addr.val); + const uint8_t res = + this->read(phys_addr_t(addr.getAccessType(), traits::MEM, base + idx * vm.ptesize), vm.ptesize, + (uint8_t *)&pte); + if (res != 0) throw trap_load_access_fault(addr.val); const reg_t ppn = pte >> PTE_PPN_SHIFT; if (PTE_TABLE(pte)) { // next level of page table @@ -1088,9 +1000,9 @@ typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::v2p(const break; } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { break; - } else if (type == iss::FETCH ? !(pte & PTE_X) : - type == iss::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) : - !((pte & PTE_R) && (pte & PTE_W))) { + } else if (type == iss::FETCH ? !(pte & PTE_X) + : type == iss::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) + : !((pte & PTE_R) && (pte & PTE_W))) { break; } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { break; @@ -1098,149 +1010,151 @@ typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::v2p(const const reg_t ad = PTE_A | ((type == iss::WRITE) * PTE_D); #ifdef RISCV_ENABLE_DIRTY // set accessed and possibly dirty bits. - *(uint32_t*)ppte |= ad; + *(uint32_t *)ppte |= ad; #else // take exception if access or possibly dirty bit is not set. - if ((pte & ad) != ad) - break; + if ((pte & ad) != ad) break; #endif // for superpage mappings, make a fake leaf PTE for the TLB's benefit. const reg_t vpn = addr.val >> PGSHIFT; const reg_t value = (ppn | (vpn & ((reg_t(1) << ptshift) - 1))) << PGSHIFT; const reg_t offset = addr.val & PGMASK; - ptw[vpn]=value | (pte&0xff); + ptw[vpn] = value | (pte & 0xff); return {addr.getAccessType(), addr.space, value | offset}; } } } switch (type) { case FETCH: - this->fault_data=addr.val; + this->fault_data = addr.val; throw trap_instruction_page_fault(addr.val); case READ: - this->fault_data=addr.val; + this->fault_data = addr.val; throw trap_load_page_fault(addr.val); case WRITE: - this->fault_data=addr.val; + this->fault_data = addr.val; throw trap_store_page_fault(addr.val); - default: abort(); + default: + abort(); } } -template -uint64_t riscv_hart_msu_vp::enter_trap(uint64_t flags, uint64_t addr) { - auto cur_priv=this->reg.machine_state; +template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t flags, uint64_t addr) { + auto cur_priv = this->reg.machine_state; // calculate and write mcause val - auto trap_id=flags&0xffff; - auto cause = (flags>>16)&0x7fff; - if(trap_id==0 && cause==11) cause = 0x8+cur_priv; // adjust environment call cause + auto trap_id = flags & 0xffff; + auto cause = (flags >> 16) & 0x7fff; + if (trap_id == 0 && cause == 11) cause = 0x8 + cur_priv; // adjust environment call cause // calculate effective privilege level - auto new_priv=PRIV_M; - if(trap_id==0){ // exception - if(cur_priv!=PRIV_M && ((csr[medeleg]>>cause)&0x1)!=0) - new_priv=(csr[sedeleg]>>cause)&0x1?PRIV_U:PRIV_S; + auto new_priv = PRIV_M; + if (trap_id == 0) { // exception + if (cur_priv != PRIV_M && ((csr[medeleg] >> cause) & 0x1) != 0) + new_priv = (csr[sedeleg] >> cause) & 0x1 ? PRIV_U : PRIV_S; // store ret addr in xepc register - csr[uepc|(new_priv<<8)]=static_cast(addr); // store actual address instruction of exception + csr[uepc | (new_priv << 8)] = static_cast(addr); // store actual address instruction of exception /* * write mtval if new_priv=M_MODE, spec says: - * When a hardware breakpoint is triggered, or an instruction-fetch, load, or store address-misaligned, - * access, or page-fault exception occurs, mtval is written with the faulting effective address. + * When a hardware breakpoint is triggered, or an instruction-fetch, load, + * or store address-misaligned, + * access, or page-fault exception occurs, mtval is written with the + * faulting effective address. */ - csr[utval|(new_priv<<8)]=fault_data; - fault_data=0; - }else{ - if(cur_priv!=PRIV_M && ((csr[mideleg]>>cause)&0x1)!=0) - new_priv=(csr[sideleg]>>cause)&0x1?PRIV_U:PRIV_S; - csr[uepc|(new_priv<<8)]=this->reg.NEXT_PC; // store next address if interrupt - this->reg.pending_trap=0; + csr[utval | (new_priv << 8)] = fault_data; + fault_data = 0; + } else { + if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) + new_priv = (csr[sideleg] >> cause) & 0x1 ? PRIV_U : PRIV_S; + csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt + this->reg.pending_trap = 0; } - csr[ucause|(new_priv<<8)]=cause; + csr[ucause | (new_priv << 8)] = cause; // update mstatus - // xPP field of mstatus is written with the active privilege mode at the time of the trap; the x PIE field of mstatus - // is written with the value of the active interrupt-enable bit at the time of the trap; and the x IE field of mstatus + // xPP field of mstatus is written with the active privilege mode at the time + // of the trap; the x PIE field of mstatus + // is written with the value of the active interrupt-enable bit at the time of + // the trap; and the x IE field of mstatus // is cleared - auto status=csr[mstatus]; - auto xie = (status>>cur_priv) & 1; + auto status = csr[mstatus]; + auto xie = (status >> cur_priv) & 1; // store the actual privilege level in yPP - switch(new_priv){ + switch (new_priv) { case PRIV_M: - status&=~(3<<11); - status|=(cur_priv&0x3)<<11; + status &= ~(3 << 11); + status |= (cur_priv & 0x3) << 11; break; case PRIV_S: - status&=~(1<<8); - status|=(cur_priv&0x1)<<8; + status &= ~(1 << 8); + status |= (cur_priv & 0x1) << 8; break; default: break; } // store interrupt enable flags - status&=~(1<<(new_priv+4) | 1<reg.NEXT_PC=ivec & ~0x1UL; - if((ivec&0x1)==1 && trap_id!=0) - this->reg.NEXT_PC+=4*cause; + auto ivec = csr[utvec | (new_priv << 8)]; + // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE + // bits in mtvec + this->reg.NEXT_PC = ivec & ~0x1UL; + if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; // reset trap state - this->reg.machine_state=new_priv; - this->reg.trap_state=0; + this->reg.machine_state = new_priv; + this->reg.trap_state = 0; char buffer[32]; sprintf(buffer, "0x%016lx", addr); - CLOG(INFO, disass)<<(trap_id?"Interrupt ":"Trap ")<reg.NEXT_PC; } -template -uint64_t riscv_hart_msu_vp::leave_trap(uint64_t flags) { - auto cur_priv=this->reg.machine_state; - auto inst_priv=flags&0x3; - auto status=csr[mstatus]; - auto ppl = inst_priv; //previous privilege level +template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t flags) { + auto cur_priv = this->reg.machine_state; + auto inst_priv = flags & 0x3; + auto status = csr[mstatus]; + auto ppl = inst_priv; // previous privilege level - auto tsr = status&(1<<22); - if(cur_priv==PRIV_S && inst_priv==PRIV_S && tsr!=0){ - this->reg.trap_state=(1<<31)|(2<<16); - this->fault_data=this->reg.PC; + auto tsr = status & (1 << 22); + if (cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) { + this->reg.trap_state = (1 << 31) | (2 << 16); + this->fault_data = this->reg.PC; return this->reg.PC; } // pop the relevant lower-privilege interrupt enable and privilege mode stack - switch(inst_priv){ + switch (inst_priv) { case PRIV_M: - ppl=(status>>11)&0x3; - status&=~(0x3<<11); // clear mpp to U mode + ppl = (status >> 11) & 0x3; + status &= ~(0x3 << 11); // clear mpp to U mode break; case PRIV_S: - ppl=(status>>8)&1; - status&=~(1<<8); // clear spp to U mode + ppl = (status >> 8) & 1; + status &= ~(1 << 8); // clear spp to U mode break; case PRIV_U: - ppl=0; + ppl = 0; break; } // sets the pc to the value stored in the x epc register. - this->reg.NEXT_PC=csr[uepc|inst_priv<<8]; - status&=~(1<>(inst_priv+4))&0x1; //previous interrupt enable - status|= pie<reg.machine_state=ppl; - CLOG(INFO, disass)<<"Executing xRET , changing privilege level from "<reg.NEXT_PC = csr[uepc | inst_priv << 8]; + status &= ~(1 << ppl); // clear respective yIE + auto pie = (status >> (inst_priv + 4)) & 0x1; // previous interrupt enable + status |= pie << inst_priv; // and set the pie + csr[mstatus] = status; + this->reg.machine_state = ppl; + CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[ppl]; return this->reg.NEXT_PC; } -template -void riscv_hart_msu_vp::wait_until(uint64_t flags) { - auto status=csr[mstatus]; - auto tw = status & (1<<21); - if(this->reg.machine_state==PRIV_S && tw!=0){ - this->reg.trap_state=(1<<31)|(2<<16); - this->fault_data=this->reg.PC; +template void riscv_hart_msu_vp::wait_until(uint64_t flags) { + auto status = csr[mstatus]; + auto tw = status & (1 << 21); + if (this->reg.machine_state == PRIV_S && tw != 0) { + this->reg.trap_state = (1 << 31) | (2 << 16); + this->fault_data = this->reg.PC; } } } diff --git a/riscv/incl/iss/arch/rv32imac.h b/riscv/incl/iss/arch/rv32imac.h index 9800349..c396c98 100644 --- a/riscv/incl/iss/arch/rv32imac.h +++ b/riscv/incl/iss/arch/rv32imac.h @@ -1,21 +1,21 @@ //////////////////////////////////////////////////////////////////////////////// // 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 @@ -27,7 +27,7 @@ // 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: Thu Sep 21 17:01:54 CEST 2017 // * rv32imac.h Author: // @@ -36,19 +36,30 @@ #ifndef _RV32IMAC_H_ #define _RV32IMAC_H_ +#include #include #include -#include namespace iss { namespace arch { struct rv32imac; -template<> -struct traits { +template <> struct traits { - enum constants {XLEN=32,XLEN2=64,XLEN_BIT_MASK=31,PCLEN=32,fence=0,fencei=1,fencevmal=2,fencevmau=3,MISA_VAL=1075056897,PGSIZE=4096,PGMASK=4095}; + enum constants { + XLEN = 32, + XLEN2 = 64, + XLEN_BIT_MASK = 31, + PCLEN = 32, + fence = 0, + fencei = 1, + fencevmal = 2, + fencevmau = 3, + MISA_VAL = 1075056897, + PGSIZE = 4096, + PGMASK = 4095 + }; enum reg_e { X0, @@ -85,7 +96,7 @@ struct traits { X31, PC, NUM_REGS, - NEXT_PC=NUM_REGS, + NEXT_PC = NUM_REGS, TRAP_STATE, PENDING_TRAP, MACHINE_STATE, @@ -96,61 +107,64 @@ struct traits { typedef uint32_t addr_t; - typedef uint32_t code_word_t; //TODO: check removal + typedef uint32_t code_word_t; // TODO: check removal - typedef iss::typed_addr_t virt_addr_t; + typedef iss::typed_addr_t virt_addr_t; typedef iss::typed_addr_t phys_addr_t; constexpr static unsigned reg_bit_width(unsigned r) { - const uint32_t 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,64}; + const uint32_t 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, 64}; return RV32IMAC_reg_size[r]; } constexpr static unsigned reg_byte_offset(unsigned r) { - const uint32_t 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,152,160}; + const uint32_t 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, 152, 160}; return RV32IMAC_reg_byte_offset[r]; } - enum sreg_flag_e {FLAGS}; - - enum mem_type_e {MEM,CSR,FENCE,RES}; + enum sreg_flag_e { FLAGS }; + 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(); - virtual void reset(uint64_t address=0) override; + virtual void reset(uint64_t address = 0) override; - virtual uint8_t* get_regs_base_ptr() override; + virtual uint8_t *get_regs_base_ptr() override; /// deprecated - virtual void get_reg(short idx, std::vector& value) override {} - virtual void set_reg(short idx, const std::vector& value) override {} + virtual void get_reg(short idx, std::vector &value) override {} + virtual void set_reg(short idx, const std::vector &value) override {} /// deprecated - virtual bool get_flag(int flag) override {return false;} - virtual void set_flag(int, bool value) override {}; + virtual bool get_flag(int flag) override { return false; } + virtual void set_flag(int, bool value) override{}; /// deprecated - virtual void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; + virtual void update_flags(operations op, uint64_t opr1, uint64_t opr2) override{}; - virtual void notify_phase(exec_phase phase){ - if(phase==ISTART){ + virtual void notify_phase(exec_phase phase) { + if (phase == ISTART) { ++reg.icount; - reg.PC=reg.NEXT_PC; - reg.trap_state=reg.pending_trap; + reg.PC = reg.NEXT_PC; + reg.trap_state = reg.pending_trap; } } - uint64_t get_icount() { return reg.icount;} + uint64_t get_icount() { return reg.icount; } - virtual phys_addr_t v2p(const iss::addr_t& pc); + virtual phys_addr_t v2p(const iss::addr_t &pc); virtual iss::sync_type needed_sync() const { return iss::PRE_SYNC; } @@ -194,7 +208,6 @@ protected: uint64_t icount; } reg; }; - } -} +} #endif /* _RV32IMAC_H_ */ diff --git a/riscv/incl/iss/arch/rv64ia.h b/riscv/incl/iss/arch/rv64ia.h index c45cfe2..9fec2ba 100644 --- a/riscv/incl/iss/arch/rv64ia.h +++ b/riscv/incl/iss/arch/rv64ia.h @@ -1,21 +1,21 @@ //////////////////////////////////////////////////////////////////////////////// // 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 @@ -27,7 +27,7 @@ // 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: Thu Sep 21 17:01:54 CEST 2017 // * rv64ia.h Author: // @@ -36,19 +36,30 @@ #ifndef _RV64IA_H_ #define _RV64IA_H_ +#include #include #include -#include namespace iss { namespace arch { struct rv64ia; -template<> -struct traits { +template <> struct traits { - enum constants {XLEN=64,XLEN2=128,XLEN_BIT_MASK=63,PCLEN=64,fence=0,fencei=1,fencevmal=2,fencevmau=3,MISA_VAL=2147750144,PGSIZE=4096,PGMASK=4095}; + enum constants { + XLEN = 64, + XLEN2 = 128, + XLEN_BIT_MASK = 63, + PCLEN = 64, + fence = 0, + fencei = 1, + fencevmal = 2, + fencevmau = 3, + MISA_VAL = 2147750144, + PGSIZE = 4096, + PGMASK = 4095 + }; enum reg_e { X0, @@ -85,7 +96,7 @@ struct traits { X31, PC, NUM_REGS, - NEXT_PC=NUM_REGS, + NEXT_PC = NUM_REGS, TRAP_STATE, PENDING_TRAP, MACHINE_STATE, @@ -96,61 +107,63 @@ struct traits { typedef uint64_t addr_t; - typedef uint64_t code_word_t; //TODO: check removal + typedef uint64_t code_word_t; // TODO: check removal - typedef iss::typed_addr_t virt_addr_t; + typedef iss::typed_addr_t virt_addr_t; typedef iss::typed_addr_t phys_addr_t; constexpr static unsigned reg_bit_width(unsigned r) { - const uint32_t 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,64}; + const uint32_t 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, 64}; return RV64IA_reg_size[r]; } constexpr static unsigned reg_byte_offset(unsigned r) { - const uint32_t 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,288,296}; + const uint32_t 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, 288, 296}; return RV64IA_reg_byte_offset[r]; } - enum sreg_flag_e {FLAGS}; - - enum mem_type_e {MEM,CSR,FENCE,RES}; + enum sreg_flag_e { FLAGS }; + enum mem_type_e { MEM, CSR, FENCE, RES }; }; -struct rv64ia: public arch_if { +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 reg_t = typename traits::reg_t; using addr_t = typename traits::addr_t; rv64ia(); ~rv64ia(); - virtual void reset(uint64_t address=0) override; + virtual void reset(uint64_t address = 0) override; - virtual uint8_t* get_regs_base_ptr() override; + virtual uint8_t *get_regs_base_ptr() override; /// deprecated - virtual void get_reg(short idx, std::vector& value) override {} - virtual void set_reg(short idx, const std::vector& value) override {} + virtual void get_reg(short idx, std::vector &value) override {} + virtual void set_reg(short idx, const std::vector &value) override {} /// deprecated - virtual bool get_flag(int flag) override {return false;} - virtual void set_flag(int, bool value) override {}; + virtual bool get_flag(int flag) override { return false; } + virtual void set_flag(int, bool value) override{}; /// deprecated - virtual void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; + virtual void update_flags(operations op, uint64_t opr1, uint64_t opr2) override{}; - virtual void notify_phase(exec_phase phase){ - if(phase==ISTART){ + virtual void notify_phase(exec_phase phase) { + if (phase == ISTART) { ++reg.icount; - reg.PC=reg.NEXT_PC; - reg.trap_state=reg.pending_trap; + reg.PC = reg.NEXT_PC; + reg.trap_state = reg.pending_trap; } } - uint64_t get_icount() { return reg.icount;} + uint64_t get_icount() { return reg.icount; } - virtual phys_addr_t v2p(const iss::addr_t& pc); + virtual phys_addr_t v2p(const iss::addr_t &pc); virtual iss::sync_type needed_sync() const { return iss::PRE_SYNC; } @@ -194,7 +207,6 @@ protected: uint64_t icount; } reg; }; - } -} +} #endif /* _RV64IA_H_ */ diff --git a/riscv/src/internal/vm_riscv.in.cpp b/riscv/src/internal/vm_riscv.in.cpp index 6183a2d..c878a15 100644 --- a/riscv/src/internal/vm_riscv.in.cpp +++ b/riscv/src/internal/vm_riscv.in.cpp @@ -1,21 +1,21 @@ //////////////////////////////////////////////////////////////////////////////// // 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 @@ -27,25 +27,25 @@ // 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 "iss/vm_base.h" #include "iss/arch/CORE_DEF_NAME.h" #include "iss/debugger/server.h" +#include "iss/vm_base.h" -#include #include "iss/arch/riscv_hart_msu_vp.h" +#include namespace iss { namespace CORE_DEF_NAME { @@ -53,28 +53,22 @@ using namespace iss::arch; using namespace llvm; using namespace iss::debugger; -template -struct vm_impl; +template struct vm_impl; -template -struct target_adapter: public target_adapter_base { +template struct target_adapter : public target_adapter_base { - target_adapter(server_if* srv, vm_impl* vm) - : target_adapter_base(srv) - , vm(vm) - { - } + target_adapter(server_if *srv, vm_impl *vm) : target_adapter_base(srv), vm(vm) {} /*============== Thread Control ===============================*/ /* Set generic thread */ - status set_gen_thread(rp_thread_ref& thread) override; + status set_gen_thread(rp_thread_ref &thread) override; /* Set control thread */ - status set_ctrl_thread(rp_thread_ref& thread) override; + status set_ctrl_thread(rp_thread_ref &thread) override; /* Get thread status */ - status is_thread_alive(rp_thread_ref& thread, bool& alive) override; + status is_thread_alive(rp_thread_ref &thread, bool &alive) override; /*============= Register Access ================================*/ @@ -82,49 +76,51 @@ struct target_adapter: public target_adapter_base { target byte order. If register is not available corresponding bytes in avail_buf are 0, otherwise avail buf is 1 */ - status read_registers(std::vector& data, std::vector& avail) override; + status read_registers(std::vector &data, std::vector &avail) override; /* Write all registers. buf is 4-byte aligned and it is in target byte order */ - status write_registers(const std::vector& data) override; + status write_registers(const std::vector &data) override; /* Read one register. buf is 4-byte aligned and it is in target byte order. If register is not available corresponding bytes in avail_buf are 0, otherwise avail buf is 1 */ - status read_single_register(unsigned int reg_no, std::vector& buf, std::vector& avail_buf) override; + status read_single_register(unsigned int reg_no, std::vector &buf, + std::vector &avail_buf) override; /* Write one register. buf is 4-byte aligned and it is in target byte order */ - status write_single_register(unsigned int reg_no, const std::vector& buf) override; + status write_single_register(unsigned int reg_no, const std::vector &buf) override; /*=================== Memory Access =====================*/ /* Read memory, buf is 4-bytes aligned and it is in target byte order */ - status read_mem(uint64_t addr, std::vector& buf) override; + status read_mem(uint64_t addr, std::vector &buf) override; /* Write memory, buf is 4-bytes aligned and it is in target byte order */ - status write_mem(uint64_t addr, const std::vector& buf) override; + status write_mem(uint64_t addr, const std::vector &buf) override; - status process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) override; + status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override; - status thread_list_query(int first, const rp_thread_ref& arg, std::vector& result, size_t max_num, size_t& num, bool& done) override; + status thread_list_query(int first, const rp_thread_ref &arg, std::vector &result, size_t max_num, + size_t &num, bool &done) override; - status current_thread_query(rp_thread_ref& thread) override; + status current_thread_query(rp_thread_ref &thread) override; - status offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) override; + status offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) override; - status crc_query(uint64_t addr, size_t len, uint32_t& val) override; + status crc_query(uint64_t addr, size_t len, uint32_t &val) override; - status raw_query(std::string in_buf, std::string& out_buf) override; + status raw_query(std::string in_buf, std::string &out_buf) override; - status threadinfo_query(int first, std::string& out_buf) override; + status threadinfo_query(int first, std::string &out_buf) override; - status threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) override; + status threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) override; - status packetsize_query(std::string& out_buf) override; + status packetsize_query(std::string &out_buf) override; status add_break(int type, uint64_t addr, unsigned int length) override; @@ -133,52 +129,46 @@ struct target_adapter: public target_adapter_base { status resume_from_addr(bool step, int sig, uint64_t addr) override; protected: - static inline constexpr addr_t map_addr(const addr_t& i){ - return i; - } + static inline constexpr addr_t map_addr(const addr_t &i) { return i; } - vm_impl* vm; + vm_impl *vm; rp_thread_ref thread_idx; }; -template -struct vm_impl: public vm::vm_base { - using super = typename vm::vm_base; +template struct vm_impl : public vm::vm_base { + 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 ; + using addr_t = typename super::addr_t; vm_impl(); - vm_impl(ARCH& core, bool dump=false); + vm_impl(ARCH &core, bool dump = false); - void enableDebug(bool enable) { - super::sync_exec=super::ALL_SYNC; - } + 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 target_adapter(srv, this); + 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 target_adapter(srv, this); return vm::vm_base::tgt_adapter; } - protected: - - template inline - llvm::ConstantInt* size(T type){ + 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 { + inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, + unsigned size) const { return this->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 &, + llvm::BasicBlock *) override; - void gen_leave_behavior(llvm::BasicBlock* leave_blk) override; + void gen_leave_behavior(llvm::BasicBlock *leave_blk) override; void gen_raise_trap(uint16_t trap_id, uint16_t cause); @@ -186,113 +176,109 @@ protected: void gen_wait(unsigned type); - void gen_trap_behavior(llvm::BasicBlock*) override; + void gen_trap_behavior(llvm::BasicBlock *) override; - void gen_trap_check(llvm::BasicBlock* bb); + void gen_trap_check(llvm::BasicBlock *bb); - 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)); + 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); } - inline - llvm::Value* get_reg_ptr(unsigned i){ - void* ptr = this->core.get_regs_base_ptr()+traits::reg_byte_offset(i); - llvm::PointerType* ptrType=nullptr; - switch (traits::reg_bit_width(i)>>3) { + inline llvm::Value *get_reg_ptr(unsigned i) { + void *ptr = this->core.get_regs_base_ptr() + traits::reg_byte_offset(i); + llvm::PointerType *ptrType = nullptr; + switch (traits::reg_bit_width(i) >> 3) { case 8: - ptrType=llvm::Type::getInt64PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt64PtrTy(this->mod->getContext()); break; case 4: - ptrType=llvm::Type::getInt32PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt32PtrTy(this->mod->getContext()); break; case 2: - ptrType=llvm::Type::getInt16PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt16PtrTy(this->mod->getContext()); break; case 1: - ptrType=llvm::Type::getInt8PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt8PtrTy(this->mod->getContext()); break; default: throw std::runtime_error("unsupported access with"); break; } return llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(this->mod->getContext(), llvm::APInt( - 8/*bits*/ * sizeof(uint8_t*), - reinterpret_cast(ptr) - )), - ptrType); + llvm::ConstantInt::get(this->mod->getContext(), + llvm::APInt(8 /*bits*/ * sizeof(uint8_t *), reinterpret_cast(ptr))), + ptrType); } - inline - llvm::Value* gen_reg_load(unsigned i, unsigned level=0){ -// if(level){ - return this->builder->CreateLoad(get_reg_ptr(i), false); -// } else { -// if(!this->loaded_regs[i]) -// this->loaded_regs[i]=this->builder->CreateLoad(get_reg_ptr(i), false); -// return this->loaded_regs[i]; -// } + inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) { + // if(level){ + return this->builder->CreateLoad(get_reg_ptr(i), false); + // } else { + // if(!this->loaded_regs[i]) + // this->loaded_regs[i]=this->builder->CreateLoad(get_reg_ptr(i), + // false); + // return this->loaded_regs[i]; + // } } - inline - void gen_set_pc(virt_addr_t pc){ - llvm::Value* pc_l = this->builder->CreateSExt(this->gen_const(traits::caddr_bit_width, (unsigned)pc), this->get_type(traits::caddr_bit_width)); + inline void gen_set_pc(virt_addr_t pc) { + llvm::Value *pc_l = this->builder->CreateSExt(this->gen_const(traits::caddr_bit_width, (unsigned)pc), + this->get_type(traits::caddr_bit_width)); super::gen_set_reg(traits::PC, pc_l); } // some compile time constants - enum {MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111}; - enum {EXTR_MASK16 = MASK16>>2, EXTR_MASK32 = MASK32>>2}; - enum {LUT_SIZE = 1<< bit_count(EXTR_MASK32), LUT_SIZE_C = 1<> 2, EXTR_MASK32 = MASK32 >> 2 }; + enum { LUT_SIZE = 1 << bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << 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, + llvm::BasicBlock *bb); compile_func lut[LUT_SIZE]; std::array lut_00, lut_01, lut_10; std::array lut_11; - compile_func* qlut[4];// = {lut_00, lut_01, lut_10, lut_11}; + compile_func *qlut[4]; // = {lut_00, lut_01, lut_10, lut_11}; - const uint32_t lutmasks[4]={EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}; + const uint32_t lutmasks[4] = {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; + 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<>2, lutmasks[val&0x3], 0); - } + 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<= 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); + 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; @@ -303,7 +289,7 @@ private: * start opcode definitions ****************************************************************************/ struct InstructionDesriptor { - size_t length; + size_t length; uint32_t value; uint32_t mask; compile_func op; @@ -315,381 +301,346 @@ private: /**************************************************************************** * end opcode definitions ****************************************************************************/ - std::tuple illegal_intruction(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ - //this->gen_sync(iss::PRE_SYNC); + std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { + // this->gen_sync(iss::PRE_SYNC); + this->builder->CreateStore(this->builder->CreateLoad(get_reg_ptr(traits::NEXT_PC), true), + get_reg_ptr(traits::PC), true); 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)), + this->builder->CreateAdd(this->builder->CreateLoad(get_reg_ptr(traits::ICOUNT), true), + this->gen_const(64U, 1)), get_reg_ptr(traits::ICOUNT), true); - if(this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC); - pc=pc+((instr&3) == 3?4:2); - this->gen_raise_trap(0, 2); // illegal instruction trap + if (this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC); + pc = pc + ((instr & 3) == 3 ? 4 : 2); + this->gen_raise_trap(0, 2); // illegal instruction trap this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ 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 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() { this(new ARCH()); } -template -vm_impl::vm_impl(ARCH& core, bool dump) : vm::vm_base(core, dump) { +template vm_impl::vm_impl(ARCH &core, bool dump) : vm::vm_base(core, dump) { 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); + 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); } - this->sync_exec=static_cast(this->sync_exec|core.needed_sync()); + this->sync_exec = static_cast(this->sync_exec | core.needed_sync()); } -template -std::tuple vm_impl::gen_single_inst_behavior(virt_addr_t& pc, unsigned int& inst_cnt, llvm::BasicBlock* this_block){ +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; iss::addr_t paddr; const typename traits::addr_t upper_bits = ~traits::PGMASK; 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 + 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); + 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 { + } else { auto res = this->core.read(paddr, 4, data); - if(res!=iss::Ok) - throw trap_access(1, pc.val); + if (res != iss::Ok) throw trap_access(1, pc.val); } - } catch(trap_access& ta){ + } catch (trap_access &ta) { throw trap_access(ta.id, pc.val); } - if(insn==0x0000006f) - throw simulation_stopped(0); + if (insn == 0x0000006f) throw simulation_stopped(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; + 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){ +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 ); +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)), +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); + 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)), +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){ +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)) - }; + 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); + 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); +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 -#define CREATE_FUNCS(ARCH) \ -template<> std::unique_ptr create(ARCH* core, unsigned short port, bool dump) {\ - std::unique_ptr > ret = std::make_unique >(*core, dump);\ - debugger::server::run_server(ret.get(), port);\ - return ret;\ -}\ -template<> std::unique_ptr create(std::string inst_name, unsigned short port, bool dump) {\ - return create(new arch::riscv_hart_msu_vp(), port, dump); /* FIXME: memory leak!!!!!!! */\ -}\ -template<> std::unique_ptr create(ARCH* core, bool dump) {\ - return std::make_unique >(*core, dump); /* FIXME: memory leak!!!!!!! */ \ -}\ -template<> std::unique_ptr create(std::string inst_name, bool dump) { \ - return create(new arch::riscv_hart_msu_vp(), dump);\ -} +#define CREATE_FUNCS(ARCH) \ + template <> std::unique_ptr create(ARCH * core, unsigned short port, bool dump) { \ + std::unique_ptr> ret = \ + std::make_unique>(*core, dump); \ + debugger::server::run_server(ret.get(), port); \ + return ret; \ + } \ + template <> std::unique_ptr create(std::string inst_name, unsigned short port, bool dump) { \ + return create(new arch::riscv_hart_msu_vp(), port, dump); /* FIXME: memory leak!!!!!!! */ \ + } \ + template <> std::unique_ptr create(ARCH * core, bool dump) { \ + return std::make_unique>(*core, dump); /* FIXME: memory leak!!!!!!! */ \ + } \ + template <> std::unique_ptr create(std::string inst_name, bool dump) { \ + return create(new arch::riscv_hart_msu_vp(), dump); \ + } CREATE_FUNCS(arch::CORE_DEF_NAME) namespace CORE_DEF_NAME { - template - status target_adapter::set_gen_thread(rp_thread_ref& thread) { - thread_idx=thread; +template status target_adapter::set_gen_thread(rp_thread_ref &thread) { + thread_idx = thread; + return Ok; +} + +template status target_adapter::set_ctrl_thread(rp_thread_ref &thread) { + thread_idx = thread; + return Ok; +} + +template status target_adapter::is_thread_alive(rp_thread_ref &thread, bool &alive) { + alive = 1; + return Ok; +} + +/* List threads. If first is non-zero then start from the first thread, + * otherwise start from arg, result points to array of threads to be + * filled out, result size is number of elements in the result, + * num points to the actual number of threads found, done is + * set if all threads are processed. + */ +template +status target_adapter::thread_list_query(int first, const rp_thread_ref &arg, std::vector &result, + size_t max_num, size_t &num, bool &done) { + if (first == 0) { + result.clear(); + result.push_back(thread_idx); + num = 1; + done = true; return Ok; - } + } else + return NotSupported; +} - template - status target_adapter::set_ctrl_thread(rp_thread_ref& thread) { - thread_idx=thread; - return Ok; - } +template status target_adapter::current_thread_query(rp_thread_ref &thread) { + thread = thread_idx; + return Ok; +} - template - status target_adapter::is_thread_alive(rp_thread_ref& thread, bool& alive) { - alive=1; - return Ok; +template +status target_adapter::read_registers(std::vector &data, std::vector &avail) { + LOG(TRACE) << "reading target registers"; + // return idx<0?:; + data.clear(); + avail.clear(); + std::vector reg_data; + for (size_t reg_no = 0; reg_no < arch::traits::NUM_REGS; ++reg_no) { + auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); + auto reg_width = reg_bit_width / 8; + reg_data.resize(reg_width); + vm->get_arch()->get_reg(reg_no, reg_data); + for (size_t j = 0; j < reg_data.size(); ++j) { + data.push_back(reg_data[j]); + avail.push_back(0xff); + } } - - /* List threads. If first is non-zero then start from the first thread, - * otherwise start from arg, result points to array of threads to be - * filled out, result size is number of elements in the result, - * num points to the actual number of threads found, done is - * set if all threads are processed. - */ - template - status target_adapter::thread_list_query(int first, const rp_thread_ref& arg, std::vector& result, size_t max_num, - size_t& num, bool& done) { - if(first==0){ - result.clear(); - result.push_back(thread_idx); - num=1; - done=true; - return Ok; - } else - return NotSupported; - } - - template - status target_adapter::current_thread_query(rp_thread_ref& thread) { - thread=thread_idx; - return Ok; - } - - template - status target_adapter::read_registers(std::vector& data, std::vector& avail) { - LOG(TRACE)<<"reading target registers"; - //return idx<0?:; - data.clear(); - avail.clear(); - std::vector reg_data; - for(size_t reg_no = 0; reg_no < arch::traits::NUM_REGS; ++reg_no){ - auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); - auto reg_width=reg_bit_width/8; - reg_data.resize(reg_width); - vm->get_arch()->get_reg(reg_no, reg_data); - for(size_t j=0; j::NUM_REGS < 65) { + auto reg_width = sizeof(typename arch::traits::reg_t); + for (size_t reg_no = 0; reg_no < 33; ++reg_no) { + for (size_t j = 0; j < reg_width; ++j) { + data.push_back(0x0); + avail.push_back(0x00); } } - // work around fill with F type registers - if(arch::traits::NUM_REGS < 65){ - auto reg_width=sizeof(typename arch::traits::reg_t); - for(size_t reg_no = 0; reg_no < 33; ++reg_no){ - for(size_t j=0; j - status target_adapter::write_registers(const std::vector& data) { - size_t data_index=0; - auto reg_count=arch::traits::NUM_REGS; - std::vector reg_data; - for(size_t reg_no = 0; reg_no < reg_count; ++reg_no){ - auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); - auto reg_width=reg_bit_width/8; - vm->get_arch()->set_reg(reg_no, std::vector(data.begin()+data_index, data.begin()+data_index+reg_width)); - data_index+=reg_width; - } - return Ok; +template status target_adapter::write_registers(const std::vector &data) { + size_t data_index = 0; + auto reg_count = arch::traits::NUM_REGS; + std::vector reg_data; + for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) { + auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); + auto reg_width = reg_bit_width / 8; + vm->get_arch()->set_reg(reg_no, + std::vector(data.begin() + data_index, data.begin() + data_index + reg_width)); + data_index += reg_width; } + return Ok; +} - template - status target_adapter::read_single_register(unsigned int reg_no, std::vector& data, std::vector& avail) { - if(reg_no<65){ - //auto reg_size = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no))/8; - data.resize(0); - vm->get_arch()->get_reg(reg_no, data); - avail.resize(data.size()); - std::fill(avail.begin(), avail.end(), 0xff); - } else { - typed_addr_t a(iss::DEBUG_READ, traits::CSR, reg_no-65); - data.resize(sizeof(typename traits::reg_t)); - avail.resize(sizeof(typename traits::reg_t)); - std::fill(avail.begin(), avail.end(), 0xff); - vm->get_arch()->read(a, data.size(), data.data()); - } - return data.size()>0?Ok:Err; +template +status target_adapter::read_single_register(unsigned int reg_no, std::vector &data, + std::vector &avail) { + if (reg_no < 65) { + // auto reg_size = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no))/8; + data.resize(0); + vm->get_arch()->get_reg(reg_no, data); + avail.resize(data.size()); + std::fill(avail.begin(), avail.end(), 0xff); + } else { + typed_addr_t a(iss::DEBUG_READ, traits::CSR, reg_no - 65); + data.resize(sizeof(typename traits::reg_t)); + avail.resize(sizeof(typename traits::reg_t)); + std::fill(avail.begin(), avail.end(), 0xff); + vm->get_arch()->read(a, data.size(), data.data()); } + return data.size() > 0 ? Ok : Err; +} - template - status target_adapter::write_single_register(unsigned int reg_no, const std::vector& data) { - if(reg_no<65) - vm->get_arch()->set_reg(reg_no, data); - else { - typed_addr_t a(iss::DEBUG_WRITE, traits::CSR, reg_no-65); - vm->get_arch()->write(a, data.size(), data.data()); - } - return Ok; - } - - template - status target_adapter::read_mem(uint64_t addr, std::vector& data) { - auto a=map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); - auto f = [&]()->status { - return vm->get_arch()->read(a, data.size(), data.data()); - }; - return srv->execute_syncronized(f); - - } - - template - status target_adapter::write_mem(uint64_t addr, const std::vector& data) { - auto a=map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); - return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data()); - } - - template - status target_adapter::process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) { - return NotSupported; - } - - template - status target_adapter::offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) { - text=0; - data=0; - bss=0; - return Ok; - } - - template - status target_adapter::crc_query(uint64_t addr, size_t len, uint32_t& val) { - return NotSupported; - } - - template - status target_adapter::raw_query(std::string in_buf, std::string& out_buf) { - return NotSupported; - } - - template - status target_adapter::threadinfo_query(int first, std::string& out_buf) { - if(first){ - std::stringstream ss; - ss<<"m"< - status target_adapter::threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) { - char buf[20]; - memset(buf, 0, 20); - sprintf (buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); - out_buf=buf; - return Ok; - } - - template - status target_adapter::packetsize_query(std::string& out_buf) { - out_buf="PacketSize=1000"; - return Ok; - } - - template - status target_adapter::add_break(int type, uint64_t addr, unsigned int length) { - auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr}); - auto eaddr=map_addr({iss::CODE, iss::PHYSICAL, addr+length}); - target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val-saddr.val); - LOG(TRACE)<<"Adding breakpoint with handle "< - status target_adapter::remove_break(int type, uint64_t addr, unsigned int length) { - auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr}); - unsigned handle=target_adapter_base::bp_lut.getEntry(saddr.val); - // TODO: check length of addr range - if(handle){ - LOG(TRACE)<<"Removing breakpoint with handle "< - status target_adapter::resume_from_addr(bool step, int sig, uint64_t addr) { - unsigned reg_no = arch::traits::PC; - std::vector data(8); - *(reinterpret_cast(&data[0]))=addr; +template +status target_adapter::write_single_register(unsigned int reg_no, const std::vector &data) { + if (reg_no < 65) vm->get_arch()->set_reg(reg_no, data); - return resume_from_current(step, sig); + else { + typed_addr_t a(iss::DEBUG_WRITE, traits::CSR, reg_no - 65); + vm->get_arch()->write(a, data.size(), data.data()); } + return Ok; +} + +template status target_adapter::read_mem(uint64_t addr, std::vector &data) { + auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); + auto f = [&]() -> status { return vm->get_arch()->read(a, data.size(), data.data()); }; + return srv->execute_syncronized(f); +} + +template status target_adapter::write_mem(uint64_t addr, const std::vector &data) { + auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); + return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data()); +} + +template +status target_adapter::process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) { + return NotSupported; +} + +template status target_adapter::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) { + text = 0; + data = 0; + bss = 0; + return Ok; +} + +template status target_adapter::crc_query(uint64_t addr, size_t len, uint32_t &val) { + return NotSupported; +} + +template status target_adapter::raw_query(std::string in_buf, std::string &out_buf) { + return NotSupported; +} + +template status 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(); + } else { + out_buf = "l"; + } + return Ok; +} + +template +status target_adapter::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) { + char buf[20]; + memset(buf, 0, 20); + sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); + out_buf = buf; + return Ok; +} + +template status target_adapter::packetsize_query(std::string &out_buf) { + out_buf = "PacketSize=1000"; + return Ok; +} + +template status target_adapter::add_break(int type, uint64_t addr, unsigned int length) { + auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); + auto eaddr = map_addr({iss::CODE, iss::PHYSICAL, addr + length}); + target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); + LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex + << saddr.val << std::dec; + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Ok; +} + +template status target_adapter::remove_break(int type, uint64_t addr, unsigned int length) { + auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); + unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); + // TODO: check length of addr range + if (handle) { + LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val + << std::dec; + target_adapter_base::bp_lut.removeEntry(handle); + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Ok; + } + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Err; +} + +template status target_adapter::resume_from_addr(bool step, int sig, uint64_t addr) { + unsigned reg_no = arch::traits::PC; + std::vector data(8); + *(reinterpret_cast(&data[0])) = addr; + vm->get_arch()->set_reg(reg_no, data); + return resume_from_current(step, sig); +} } // namespace CORE_DEF_NAME } // namespace iss diff --git a/riscv/src/internal/vm_rv32imac.cpp b/riscv/src/internal/vm_rv32imac.cpp index b9fb980..9464eef 100644 --- a/riscv/src/internal/vm_rv32imac.cpp +++ b/riscv/src/internal/vm_rv32imac.cpp @@ -1,21 +1,21 @@ //////////////////////////////////////////////////////////////////////////////// // 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 @@ -27,25 +27,25 @@ // 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 "iss/vm_base.h" #include "iss/arch/rv32imac.h" #include "iss/debugger/server.h" +#include "iss/vm_base.h" -#include #include "iss/arch/riscv_hart_msu_vp.h" +#include namespace iss { namespace rv32imac { @@ -53,28 +53,22 @@ using namespace iss::arch; using namespace llvm; using namespace iss::debugger; -template -struct vm_impl; +template struct vm_impl; -template -struct target_adapter: public target_adapter_base { +template struct target_adapter : public target_adapter_base { - target_adapter(server_if* srv, vm_impl* vm) - : target_adapter_base(srv) - , vm(vm) - { - } + target_adapter(server_if *srv, vm_impl *vm) : target_adapter_base(srv), vm(vm) {} /*============== Thread Control ===============================*/ /* Set generic thread */ - status set_gen_thread(rp_thread_ref& thread) override; + status set_gen_thread(rp_thread_ref &thread) override; /* Set control thread */ - status set_ctrl_thread(rp_thread_ref& thread) override; + status set_ctrl_thread(rp_thread_ref &thread) override; /* Get thread status */ - status is_thread_alive(rp_thread_ref& thread, bool& alive) override; + status is_thread_alive(rp_thread_ref &thread, bool &alive) override; /*============= Register Access ================================*/ @@ -82,49 +76,51 @@ struct target_adapter: public target_adapter_base { target byte order. If register is not available corresponding bytes in avail_buf are 0, otherwise avail buf is 1 */ - status read_registers(std::vector& data, std::vector& avail) override; + status read_registers(std::vector &data, std::vector &avail) override; /* Write all registers. buf is 4-byte aligned and it is in target byte order */ - status write_registers(const std::vector& data) override; + status write_registers(const std::vector &data) override; /* Read one register. buf is 4-byte aligned and it is in target byte order. If register is not available corresponding bytes in avail_buf are 0, otherwise avail buf is 1 */ - status read_single_register(unsigned int reg_no, std::vector& buf, std::vector& avail_buf) override; + status read_single_register(unsigned int reg_no, std::vector &buf, + std::vector &avail_buf) override; /* Write one register. buf is 4-byte aligned and it is in target byte order */ - status write_single_register(unsigned int reg_no, const std::vector& buf) override; + status write_single_register(unsigned int reg_no, const std::vector &buf) override; /*=================== Memory Access =====================*/ /* Read memory, buf is 4-bytes aligned and it is in target byte order */ - status read_mem(uint64_t addr, std::vector& buf) override; + status read_mem(uint64_t addr, std::vector &buf) override; /* Write memory, buf is 4-bytes aligned and it is in target byte order */ - status write_mem(uint64_t addr, const std::vector& buf) override; + status write_mem(uint64_t addr, const std::vector &buf) override; - status process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) override; + status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override; - status thread_list_query(int first, const rp_thread_ref& arg, std::vector& result, size_t max_num, size_t& num, bool& done) override; + status thread_list_query(int first, const rp_thread_ref &arg, std::vector &result, size_t max_num, + size_t &num, bool &done) override; - status current_thread_query(rp_thread_ref& thread) override; + status current_thread_query(rp_thread_ref &thread) override; - status offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) override; + status offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) override; - status crc_query(uint64_t addr, size_t len, uint32_t& val) override; + status crc_query(uint64_t addr, size_t len, uint32_t &val) override; - status raw_query(std::string in_buf, std::string& out_buf) override; + status raw_query(std::string in_buf, std::string &out_buf) override; - status threadinfo_query(int first, std::string& out_buf) override; + status threadinfo_query(int first, std::string &out_buf) override; - status threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) override; + status threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) override; - status packetsize_query(std::string& out_buf) override; + status packetsize_query(std::string &out_buf) override; status add_break(int type, uint64_t addr, unsigned int length) override; @@ -133,52 +129,46 @@ struct target_adapter: public target_adapter_base { status resume_from_addr(bool step, int sig, uint64_t addr) override; protected: - static inline constexpr addr_t map_addr(const addr_t& i){ - return i; - } + static inline constexpr addr_t map_addr(const addr_t &i) { return i; } - vm_impl* vm; + vm_impl *vm; rp_thread_ref thread_idx; }; -template -struct vm_impl: public vm::vm_base { - using super = typename vm::vm_base; +template struct vm_impl : public vm::vm_base { + 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 ; + using addr_t = typename super::addr_t; vm_impl(); - vm_impl(ARCH& core, bool dump=false); + vm_impl(ARCH &core, bool dump = false); - void enableDebug(bool enable) { - super::sync_exec=super::ALL_SYNC; - } + 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 target_adapter(srv, this); + 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 target_adapter(srv, this); return vm::vm_base::tgt_adapter; } - protected: - - template inline - llvm::ConstantInt* size(T type){ + 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 { + inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, + unsigned size) const { return this->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 &, + llvm::BasicBlock *) override; - void gen_leave_behavior(llvm::BasicBlock* leave_blk) override; + void gen_leave_behavior(llvm::BasicBlock *leave_blk) override; void gen_raise_trap(uint16_t trap_id, uint16_t cause); @@ -186,113 +176,109 @@ protected: void gen_wait(unsigned type); - void gen_trap_behavior(llvm::BasicBlock*) override; + void gen_trap_behavior(llvm::BasicBlock *) override; - void gen_trap_check(llvm::BasicBlock* bb); + void gen_trap_check(llvm::BasicBlock *bb); - 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)); + 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); } - inline - llvm::Value* get_reg_ptr(unsigned i){ - void* ptr = this->core.get_regs_base_ptr()+traits::reg_byte_offset(i); - llvm::PointerType* ptrType=nullptr; - switch (traits::reg_bit_width(i)>>3) { + inline llvm::Value *get_reg_ptr(unsigned i) { + void *ptr = this->core.get_regs_base_ptr() + traits::reg_byte_offset(i); + llvm::PointerType *ptrType = nullptr; + switch (traits::reg_bit_width(i) >> 3) { case 8: - ptrType=llvm::Type::getInt64PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt64PtrTy(this->mod->getContext()); break; case 4: - ptrType=llvm::Type::getInt32PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt32PtrTy(this->mod->getContext()); break; case 2: - ptrType=llvm::Type::getInt16PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt16PtrTy(this->mod->getContext()); break; case 1: - ptrType=llvm::Type::getInt8PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt8PtrTy(this->mod->getContext()); break; default: throw std::runtime_error("unsupported access with"); break; } return llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(this->mod->getContext(), llvm::APInt( - 8/*bits*/ * sizeof(uint8_t*), - reinterpret_cast(ptr) - )), - ptrType); + llvm::ConstantInt::get(this->mod->getContext(), + llvm::APInt(8 /*bits*/ * sizeof(uint8_t *), reinterpret_cast(ptr))), + ptrType); } - inline - llvm::Value* gen_reg_load(unsigned i, unsigned level=0){ -// if(level){ - return this->builder->CreateLoad(get_reg_ptr(i), false); -// } else { -// if(!this->loaded_regs[i]) -// this->loaded_regs[i]=this->builder->CreateLoad(get_reg_ptr(i), false); -// return this->loaded_regs[i]; -// } + inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) { + // if(level){ + return this->builder->CreateLoad(get_reg_ptr(i), false); + // } else { + // if(!this->loaded_regs[i]) + // this->loaded_regs[i]=this->builder->CreateLoad(get_reg_ptr(i), + // false); + // return this->loaded_regs[i]; + // } } - inline - void gen_set_pc(virt_addr_t pc){ - llvm::Value* pc_l = this->builder->CreateSExt(this->gen_const(traits::caddr_bit_width, (unsigned)pc), this->get_type(traits::caddr_bit_width)); + inline void gen_set_pc(virt_addr_t pc) { + llvm::Value *pc_l = this->builder->CreateSExt(this->gen_const(traits::caddr_bit_width, (unsigned)pc), + this->get_type(traits::caddr_bit_width)); super::gen_set_reg(traits::PC, pc_l); } // some compile time constants - enum {MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111}; - enum {EXTR_MASK16 = MASK16>>2, EXTR_MASK32 = MASK32>>2}; - enum {LUT_SIZE = 1<< bit_count(EXTR_MASK32), LUT_SIZE_C = 1<> 2, EXTR_MASK32 = MASK32 >> 2 }; + enum { LUT_SIZE = 1 << bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << 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, + llvm::BasicBlock *bb); compile_func lut[LUT_SIZE]; std::array lut_00, lut_01, lut_10; std::array lut_11; - compile_func* qlut[4];// = {lut_00, lut_01, lut_10, lut_11}; + compile_func *qlut[4]; // = {lut_00, lut_01, lut_10, lut_11}; - const uint32_t lutmasks[4]={EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}; + const uint32_t lutmasks[4] = {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; + 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<>2, lutmasks[val&0x3], 0); - } + 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<= 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); + 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; @@ -303,7 +289,7 @@ private: * start opcode definitions ****************************************************************************/ struct InstructionDesriptor { - size_t length; + size_t length; uint32_t value; uint32_t mask; compile_func op; @@ -512,4371 +498,3821 @@ private: {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, }; // instruction LUI - std::tuple __lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lui(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LUI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - int32_t fld_imm_val = 0 | (signed_bit_sub<12,20>(instr) << 12); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + int32_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_const(32U, fld_imm_val); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_const(32U, fld_imm_val); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AUIPC - std::tuple __auipc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __auipc(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("AUIPC"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - int32_t fld_imm_val = 0 | (signed_bit_sub<12,20>(instr) << 12); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + int32_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 JAL - std::tuple __jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __jal(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("JAL"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - int32_t fld_imm_val = 0 | (bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (signed_bit_sub<31,1>(instr) << 20); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + int32_t fld_imm_val = 0 | (bit_sub<12, 8>(instr) << 12) | (bit_sub<20, 1>(instr) << 11) | + (bit_sub<21, 10>(instr) << 1) | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 4)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 4)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* PC_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)); + Value *PC_val = + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction JALR - std::tuple __jalr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __jalr(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("JALR"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 4)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 4)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* ret_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); - Value* PC_val = this->builder->CreateAnd( - ret_val, - this->builder->CreateNot(this->gen_const(32U, 1))); + Value *ret_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); + Value *PC_val = this->builder->CreateAnd(ret_val, this->builder->CreateNot(this->gen_const(32U, 1))); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BEQ - std::tuple __beq(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __beq(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("BEQ"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 4)), - 32); + pc = pc + 4; + + Value *PC_val = this->gen_choose( + this->builder->CreateICmp(ICmpInst::ICMP_EQ, this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs2_val, 0)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 4)), 32); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BNE - std::tuple __bne(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __bne(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("BNE"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 4)), - 32); + pc = pc + 4; + + Value *PC_val = this->gen_choose( + this->builder->CreateICmp(ICmpInst::ICMP_NE, this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs2_val, 0)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 4)), 32); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BLT - std::tuple __blt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __blt(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("BLT"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - 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, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 32, true)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 4)), - 32); + 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, 0), 32, true), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 32, true)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 4)), 32); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BGE - std::tuple __bge(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __bge(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("BGE"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - 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, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 32, true)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 4)), - 32); + 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, 0), 32, true), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 32, true)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 4)), 32); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BLTU - std::tuple __bltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __bltu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("BLTU"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 4)), - 32); + pc = pc + 4; + + Value *PC_val = this->gen_choose( + this->builder->CreateICmp(ICmpInst::ICMP_ULT, this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs2_val, 0)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 4)), 32); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BGEU - std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __bgeu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("BGEU"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_UGE, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 4)), - 32); + pc = pc + 4; + + Value *PC_val = this->gen_choose( + this->builder->CreateICmp(ICmpInst::ICMP_UGE, this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs2_val, 0)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 4)), 32); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction LB - std::tuple __lb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lb(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LB"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - true); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 8 / 8), 32, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LH - std::tuple __lh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lh(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LH"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - true); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 16 / 8), 32, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LW - std::tuple __lw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lw(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 32 / 8), 32, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LBU - std::tuple __lbu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lbu(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LBU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - false); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 8 / 8), 32, false); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LHU - std::tuple __lhu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lhu(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LHU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - false); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 16 / 8), 32, false); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SB - std::tuple __sb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sb(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SB"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 5>(instr)) | (signed_bit_sub<25, 7>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(8))); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(8))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SH - std::tuple __sh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sh(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SH"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 5>(instr)) | (signed_bit_sub<25, 7>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(16))); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(16))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SW - std::tuple __sw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sw(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SW"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 5>(instr)) | (signed_bit_sub<25, 7>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 ADDI - std::tuple __addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __addi(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("ADDI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLTI - std::tuple __slti(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __slti(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SLTI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 32, true), - this->gen_ext( - this->gen_const(32U, fld_imm_val), - 32, true)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->gen_choose(this->builder->CreateICmp(ICmpInst::ICMP_SLT, + this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 32, true), + this->gen_ext(this->gen_const(32U, fld_imm_val), 32, true)), + this->gen_const(32U, 1), this->gen_const(32U, 0), 32); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLTIU - std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sltiu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SLTIU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + int32_t full_imm_val = fld_imm_val; - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 32, false), - this->gen_ext( - full_imm_val, - 32, false)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); + if (fld_rd_val != 0) { + Value *X_rd_val = + this->gen_choose(this->builder->CreateICmp(ICmpInst::ICMP_ULT, + this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 32, false), + this->gen_ext(full_imm_val, 32, false)), + this->gen_const(32U, 1), this->gen_const(32U, 0), 32); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 XORI - std::tuple __xori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __xori(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("XORI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateXor( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateXor(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 ORI - std::tuple __ori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __ori(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("ORI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateOr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateOr(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 ANDI - std::tuple __andi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __andi(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("ANDI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAnd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_imm_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAnd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_imm_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLLI - std::tuple __slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __slli(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SLLI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_shamt_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateShl( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_shamt_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateShl(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_shamt_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRLI - std::tuple __srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __srli(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SRLI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_shamt_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateLShr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_shamt_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateLShr(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_shamt_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRAI - std::tuple __srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __srai(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SRAI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_shamt_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAShr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_shamt_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAShr(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_shamt_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 ADD - std::tuple __add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __add(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("ADD"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_reg_load(fld_rs2_val, 0)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SUB - std::tuple __sub(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sub(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SUB"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateSub( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateSub(this->gen_reg_load(fld_rs1_val, 0), this->gen_reg_load(fld_rs2_val, 0)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLL - std::tuple __sll(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sll(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SLL"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateShl( - this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 31)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = this->builder->CreateShl( + this->gen_reg_load(fld_rs1_val, 0), this->builder->CreateAnd(this->gen_reg_load(fld_rs2_val, 0), 31)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLT - std::tuple __slt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __slt(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SLT"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 32, true)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->gen_choose(this->builder->CreateICmp(ICmpInst::ICMP_SLT, + this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 32, true), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 32, true)), + this->gen_const(32U, 1), this->gen_const(32U, 0), 32); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLTU - std::tuple __sltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sltu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SLTU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 32, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 32, - false)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->gen_choose(this->builder->CreateICmp( + ICmpInst::ICMP_ULT, this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 32, false), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 32, false)), + this->gen_const(32U, 1), this->gen_const(32U, 0), 32); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 XOR - std::tuple __xor(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __xor(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("XOR"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateXor( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateXor(this->gen_reg_load(fld_rs1_val, 0), this->gen_reg_load(fld_rs2_val, 0)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRL - std::tuple __srl(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __srl(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SRL"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateLShr( - this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 31)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = this->builder->CreateLShr( + this->gen_reg_load(fld_rs1_val, 0), this->builder->CreateAnd(this->gen_reg_load(fld_rs2_val, 0), 31)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRA - std::tuple __sra(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sra(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SRA"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAShr( - this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 31)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = this->builder->CreateAShr( + this->gen_reg_load(fld_rs1_val, 0), this->builder->CreateAnd(this->gen_reg_load(fld_rs2_val, 0), 31)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 OR - std::tuple __or(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __or(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("OR"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateOr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateOr(this->gen_reg_load(fld_rs1_val, 0), this->gen_reg_load(fld_rs2_val, 0)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AND - std::tuple __and(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __and(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("AND"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAnd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAnd(this->gen_reg_load(fld_rs1_val, 0), this->gen_reg_load(fld_rs2_val, 0)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 FENCE - std::tuple __fence(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __fence(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("FENCE"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_succ_val = 0 | (bit_sub<20,4>(instr)); - uint8_t fld_pred_val = 0 | (bit_sub<24,4>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_succ_val = 0 | (bit_sub<20, 4>(instr)); + uint8_t fld_pred_val = 0 | (bit_sub<24, 4>(instr)); + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("FENCE"); + std::string opcode("FENCE"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* FENCE_fence_val = this->builder->CreateOr( - this->builder->CreateShl( - this->gen_const(32U, fld_pred_val), - this->gen_const(32U, 4)), + pc = pc + 4; + + Value *FENCE_fence_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, - (uint64_t)0, - this->builder->CreateZExtOrTrunc(FENCE_fence_val,this->get_type(32))); + this->gen_write_mem(traits::FENCE, (uint64_t)0, + this->builder->CreateZExtOrTrunc(FENCE_fence_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 FENCE_I - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_imm_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_imm_val = 0 | (bit_sub<20, 12>(instr)); + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("FENCE_I"); + std::string opcode("FENCE_I"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* FENCE_fencei_val = this->gen_const(32U, fld_imm_val); - this->gen_write_mem( - traits::FENCE, - (uint64_t)1, - this->builder->CreateZExtOrTrunc(FENCE_fencei_val,this->get_type(32))); + pc = pc + 4; + + Value *FENCE_fencei_val = this->gen_const(32U, fld_imm_val); + this->gen_write_mem(traits::FENCE, (uint64_t)1, + this->builder->CreateZExtOrTrunc(FENCE_fencei_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::FLUSH, nullptr); } - + // instruction ECALL - std::tuple __ecall(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __ecall(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("ECALL"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("ECALL"); + std::string opcode("ECALL"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_raise_trap(0, 11); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction EBREAK - std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __ebreak(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("EBREAK"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("EBREAK"); + std::string opcode("EBREAK"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_raise_trap(0, 3); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction URET - std::tuple __uret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __uret(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("URET"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("URET"); + std::string opcode("URET"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_leave_trap(0); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction SRET - std::tuple __sret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sret(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SRET"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("SRET"); + std::string opcode("SRET"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_leave_trap(1); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction MRET - std::tuple __mret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __mret(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("MRET"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("MRET"); + std::string opcode("MRET"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_leave_trap(3); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction WFI - std::tuple __wfi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __wfi(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("WFI"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("WFI"); + std::string opcode("WFI"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_wait(1); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SFENCE.VMA - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("SFENCE.VMA"); + std::string opcode("SFENCE.VMA"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* FENCE_fencevmal_val = this->gen_const(32U, fld_rs1_val); - this->gen_write_mem( - traits::FENCE, - (uint64_t)2, - this->builder->CreateZExtOrTrunc(FENCE_fencevmal_val,this->get_type(32))); - Value* FENCE_fencevmau_val = this->gen_const(32U, fld_rs2_val); - this->gen_write_mem( - traits::FENCE, - (uint64_t)3, - this->builder->CreateZExtOrTrunc(FENCE_fencevmau_val,this->get_type(32))); + pc = pc + 4; + + Value *FENCE_fencevmal_val = this->gen_const(32U, fld_rs1_val); + this->gen_write_mem(traits::FENCE, (uint64_t)2, + this->builder->CreateZExtOrTrunc(FENCE_fencevmal_val, this->get_type(32))); + Value *FENCE_fencevmau_val = this->gen_const(32U, fld_rs2_val); + this->gen_write_mem(traits::FENCE, (uint64_t)3, + this->builder->CreateZExtOrTrunc(FENCE_fencevmau_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRW - std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* rs_val_val = this->gen_reg_load(fld_rs1_val, 0); - if(fld_rd_val != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); - Value* CSR_csr_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); - Value* X_rd_val = csr_val_val; + pc = pc + 4; + + Value *rs_val_val = this->gen_reg_load(fld_rs1_val, 0); + if (fld_rd_val != 0) { + Value *csr_val_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32 / 8); + Value *CSR_csr_val = rs_val_val; + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(32))); + Value *X_rd_val = csr_val_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } else { - Value* CSR_csr_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + Value *CSR_csr_val = rs_val_val; + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRS - std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrs(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRS"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val, 0); - if(fld_rd_val != 0){ - Value* X_rd_val = xrd_val; + pc = pc + 4; + + Value *xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32 / 8); + Value *xrs1_val = this->gen_reg_load(fld_rs1_val, 0); + if (fld_rd_val != 0) { + Value *X_rd_val = xrd_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - if(fld_rs1_val != 0){ - Value* CSR_csr_val = this->builder->CreateOr( - xrd_val, - xrs1_val); - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + if (fld_rs1_val != 0) { + Value *CSR_csr_val = this->builder->CreateOr(xrd_val, xrs1_val); + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRC - std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrc(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRC"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val, 0); - if(fld_rd_val != 0){ - Value* X_rd_val = xrd_val; + pc = pc + 4; + + Value *xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32 / 8); + Value *xrs1_val = this->gen_reg_load(fld_rs1_val, 0); + if (fld_rd_val != 0) { + Value *X_rd_val = xrd_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - if(fld_rs1_val != 0){ - Value* CSR_csr_val = this->builder->CreateAnd( - xrd_val, - this->builder->CreateNot(xrs1_val)); - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + if (fld_rs1_val != 0) { + Value *CSR_csr_val = this->builder->CreateAnd(xrd_val, this->builder->CreateNot(xrs1_val)); + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRWI - std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrwi(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRWI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_zimm_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_zimm_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32 / 8); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* CSR_csr_val = this->gen_ext( - this->gen_const(32U, fld_zimm_val), - 32, - false); - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + Value *CSR_csr_val = this->gen_ext(this->gen_const(32U, fld_zimm_val), 32, false); + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRSI - std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrsi(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRSI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_zimm_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_zimm_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); - if(fld_zimm_val != 0){ - Value* CSR_csr_val = this->builder->CreateOr( - res_val, - this->gen_ext( - this->gen_const(32U, fld_zimm_val), - 32, - false)); - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + pc = pc + 4; + + Value *res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32 / 8); + if (fld_zimm_val != 0) { + Value *CSR_csr_val = + this->builder->CreateOr(res_val, this->gen_ext(this->gen_const(32U, fld_zimm_val), 32, false)); + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(32))); } - if(fld_rd_val != 0){ - Value* X_rd_val = res_val; + if (fld_rd_val != 0) { + Value *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRCI - std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrci(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRCI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_zimm_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_zimm_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); - if(fld_rd_val != 0){ - Value* X_rd_val = res_val; + pc = pc + 4; + + Value *res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32 / 8); + if (fld_rd_val != 0) { + Value *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - if(fld_zimm_val != 0){ - Value* CSR_csr_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, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + if (fld_zimm_val != 0) { + Value *CSR_csr_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, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 MUL - std::tuple __mul(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __mul(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("MUL"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder->CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 64, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 64, - false)); - Value* X_rd_val = this->gen_ext( - res_val, - 32, - false); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *res_val = this->builder->CreateMul(this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 64, false), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 64, false)); + Value *X_rd_val = this->gen_ext(res_val, 32, false); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 MULH - std::tuple __mulh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __mulh(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("MULH"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder->CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 64, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 64, - true)); - Value* X_rd_val = this->gen_ext( - this->builder->CreateLShr( - res_val, - 32), - 32, - false); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *res_val = this->builder->CreateMul(this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 64, true), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 64, true)); + Value *X_rd_val = this->gen_ext(this->builder->CreateLShr(res_val, 32), 32, false); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 MULHSU - std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __mulhsu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("MULHSU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder->CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 64, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 64, - false)); - Value* X_rd_val = this->gen_ext( - this->builder->CreateLShr( - res_val, - 32), - 32, - false); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *res_val = this->builder->CreateMul(this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 64, true), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 64, false)); + Value *X_rd_val = this->gen_ext(this->builder->CreateLShr(res_val, 32), 32, false); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 MULHU - std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __mulhu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("MULHU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* res_val = this->builder->CreateMul( - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 64, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 64, - false)); - Value* X_rd_val = this->gen_ext( - this->builder->CreateLShr( - res_val, - 32), - 32, - false); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *res_val = this->builder->CreateMul(this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 64, false), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 64, false)); + Value *X_rd_val = this->gen_ext(this->builder->CreateLShr(res_val, 32), 32, false); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 DIV - std::tuple __div(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __div(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("DIV"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - 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); + 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, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); + this->gen_cond_branch(this->builder->CreateICmp(ICmpInst::ICMP_NE, this->gen_reg_load(fld_rs2_val, 0), + this->gen_const(32U, 0)), + bb_then, bb_else); this->builder->SetInsertPoint(bb_then); { - Value* X_rd_val = this->builder->CreateSDiv( - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 1), - 32, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 1), - 32, - true)); + Value *X_rd_val = + this->builder->CreateSDiv(this->gen_ext(this->gen_reg_load(fld_rs1_val, 1), 32, true), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 1), 32, true)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->builder->CreateBr(bbnext); this->builder->SetInsertPoint(bb_else); { - Value* X_rd_val = this->builder->CreateNeg(this->gen_const(32U, 1)); + Value *X_rd_val = this->builder->CreateNeg(this->gen_const(32U, 1)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->builder->CreateBr(bbnext); - bb=bbnext; + bb = bbnext; this->builder->SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 DIVU - std::tuple __divu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __divu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("DIVU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - 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); + 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, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); + this->gen_cond_branch(this->builder->CreateICmp(ICmpInst::ICMP_NE, this->gen_reg_load(fld_rs2_val, 0), + this->gen_const(32U, 0)), + bb_then, bb_else); this->builder->SetInsertPoint(bb_then); { - Value* X_rd_val = this->builder->CreateUDiv( - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 1), - 32, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 1), - 32, - false)); + Value *X_rd_val = + this->builder->CreateUDiv(this->gen_ext(this->gen_reg_load(fld_rs1_val, 1), 32, false), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 1), 32, false)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->builder->CreateBr(bbnext); this->builder->SetInsertPoint(bb_else); { - Value* X_rd_val = this->builder->CreateNeg(this->gen_const(32U, 1)); + Value *X_rd_val = this->builder->CreateNeg(this->gen_const(32U, 1)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->builder->CreateBr(bbnext); - bb=bbnext; + bb = bbnext; this->builder->SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 REM - std::tuple __rem(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __rem(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("REM"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - 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); + 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, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); + this->gen_cond_branch(this->builder->CreateICmp(ICmpInst::ICMP_NE, this->gen_reg_load(fld_rs2_val, 0), + this->gen_const(32U, 0)), + bb_then, bb_else); this->builder->SetInsertPoint(bb_then); { - Value* X_rd_val = this->builder->CreateSRem( - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 1), - 32, - true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 1), - 32, - true)); + Value *X_rd_val = + this->builder->CreateSRem(this->gen_ext(this->gen_reg_load(fld_rs1_val, 1), 32, true), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 1), 32, true)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->builder->CreateBr(bbnext); this->builder->SetInsertPoint(bb_else); { - Value* X_rd_val = this->gen_reg_load(fld_rs1_val, 1); + Value *X_rd_val = this->gen_reg_load(fld_rs1_val, 1); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->builder->CreateBr(bbnext); - bb=bbnext; + bb = bbnext; this->builder->SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 REMU - std::tuple __remu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __remu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("REMU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - 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); + 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, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); + this->gen_cond_branch(this->builder->CreateICmp(ICmpInst::ICMP_NE, this->gen_reg_load(fld_rs2_val, 0), + this->gen_const(32U, 0)), + bb_then, bb_else); this->builder->SetInsertPoint(bb_then); { - Value* X_rd_val = this->builder->CreateURem( - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 1), - 32, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 1), - 32, - false)); + Value *X_rd_val = + this->builder->CreateURem(this->gen_ext(this->gen_reg_load(fld_rs1_val, 1), 32, false), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 1), 32, false)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->builder->CreateBr(bbnext); this->builder->SetInsertPoint(bb_else); { - Value* X_rd_val = this->gen_reg_load(fld_rs1_val, 1); + Value *X_rd_val = this->gen_reg_load(fld_rs1_val, 1); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->builder->CreateBr(bbnext); - bb=bbnext; + bb = bbnext; this->builder->SetInsertPoint(bb); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LR.W - std::tuple __lr_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 32 / 8), 32, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); - Value* RES_offs_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(RES_offs_val,this->get_type(32))); + Value *RES_offs_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(RES_offs_val, this->get_type(32))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SC.W - std::tuple __sc_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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); + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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->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* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 1); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 1); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); } this->builder->CreateBr(bbnext); - bb=bbnext; + bb = bbnext; this->builder->SetInsertPoint(bb); - if(fld_rd_val != 0){ - Value* X_rd_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); + if (fld_rd_val != 0) { + Value *X_rd_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(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOSWAP.W - std::tuple __amoswap_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; + 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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 0); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 32 / 8), 32, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOADD.W - std::tuple __amoadd_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; + 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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res1_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res1_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->builder->CreateAdd( - res1_val, - this->gen_reg_load(fld_rs2_val, 0)); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + Value *res2_val = this->builder->CreateAdd(res1_val, this->gen_reg_load(fld_rs2_val, 0)); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOXOR.W - std::tuple __amoxor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; + 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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res1_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res1_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->builder->CreateXor( - res1_val, - this->gen_reg_load(fld_rs2_val, 0)); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + Value *res2_val = this->builder->CreateXor(res1_val, this->gen_reg_load(fld_rs2_val, 0)); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOAND.W - std::tuple __amoand_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; + 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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res1_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res1_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->builder->CreateAnd( - res1_val, - this->gen_reg_load(fld_rs2_val, 0)); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + Value *res2_val = this->builder->CreateAnd(res1_val, this->gen_reg_load(fld_rs2_val, 0)); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOOR.W - std::tuple __amoor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; + 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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res1_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res1_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->builder->CreateOr( - res1_val, - this->gen_reg_load(fld_rs2_val, 0)); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + Value *res2_val = this->builder->CreateOr(res1_val, this->gen_reg_load(fld_rs2_val, 0)); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOMIN.W - std::tuple __amomin_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; + 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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res1_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res1_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), 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, 0), - 32, true)), - this->gen_reg_load(fld_rs2_val, 0), - res1_val, - 32); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + 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, 0), 32, true)), + this->gen_reg_load(fld_rs2_val, 0), res1_val, 32); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOMAX.W - std::tuple __amomax_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; + 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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res1_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res1_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), 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, 0), - 32, true)), - this->gen_reg_load(fld_rs2_val, 0), - res1_val, - 32); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + 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, 0), 32, true)), + this->gen_reg_load(fld_rs2_val, 0), res1_val, 32); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOMINU.W - std::tuple __amominu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; + 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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res1_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res1_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_UGT, - res1_val, - this->gen_reg_load(fld_rs2_val, 0)), - this->gen_reg_load(fld_rs2_val, 0), - res1_val, - 32); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + Value *res2_val = this->gen_choose( + this->builder->CreateICmp(ICmpInst::ICMP_UGT, res1_val, this->gen_reg_load(fld_rs2_val, 0)), + this->gen_reg_load(fld_rs2_val, 0), res1_val, 32); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOMAXU.W - std::tuple __amomaxu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; + 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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res1_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res1_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - res1_val, - 32, false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 32, false)), - this->gen_reg_load(fld_rs2_val, 0), - res1_val, - 32); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + Value *res2_val = + this->gen_choose(this->builder->CreateICmp(ICmpInst::ICMP_ULT, this->gen_ext(res1_val, 32, false), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 32, false)), + this->gen_reg_load(fld_rs2_val, 0), res1_val, 32); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.ADDI4SPN - std::tuple __c_addi4spn(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_addi4spn(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.ADDI4SPN"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<2,3>(instr)); - uint16_t fld_nzuimm_val = 0 | (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){ + + uint8_t fld_rd_val = 0 | (bit_sub<2, 3>(instr)); + uint16_t fld_nzuimm_val = 0 | (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_nzuimm_val; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - - if(fld_nzuimm_val == 0){ + pc = pc + 2; + + if (fld_nzuimm_val == 0) { this->gen_raise_trap(0, 2); } uint8_t rd_idx_val = (fld_rd_val + 8); uint8_t x2_idx_val = 2; - Value* X_rd_idx_val = this->builder->CreateAdd( - this->gen_reg_load(x2_idx_val, 0), - this->gen_const(32U, fld_nzuimm_val)); + Value *X_rd_idx_val = + this->builder->CreateAdd(this->gen_reg_load(x2_idx_val, 0), this->gen_const(32U, fld_nzuimm_val)); this->builder->CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.LW - std::tuple __c_lw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_lw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.LW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<2,3>(instr)); - uint8_t fld_uimm_val = 0 | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3); - uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<2, 3>(instr)); + uint8_t fld_uimm_val = + 0 | (bit_sub<5, 1>(instr) << 6) | (bit_sub<6, 1>(instr) << 2) | (bit_sub<10, 3>(instr) << 3); + uint8_t fld_rs1_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t rs1_idx_val = (fld_rs1_val + 8); - Value* adr_val = this->builder->CreateAdd( - this->gen_reg_load(rs1_idx_val, 0), - this->gen_const(32U, fld_uimm_val)); + Value *adr_val = + this->builder->CreateAdd(this->gen_reg_load(rs1_idx_val, 0), this->gen_const(32U, fld_uimm_val)); uint8_t rd_idx_val = (fld_rd_val + 8); - Value* X_rd_idx_val = this->gen_read_mem(traits::MEM, adr_val, 32/8); + Value *X_rd_idx_val = this->gen_read_mem(traits::MEM, adr_val, 32 / 8); this->builder->CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.SW - std::tuple __c_sw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_sw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.SW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); - uint8_t fld_uimm_val = 0 | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3); - uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rs2_val = 0 | (bit_sub<2, 3>(instr)); + uint8_t fld_uimm_val = + 0 | (bit_sub<5, 1>(instr) << 6) | (bit_sub<6, 1>(instr) << 2) | (bit_sub<10, 3>(instr) << 3); + uint8_t fld_rs1_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t rs1_idx_val = (fld_rs1_val + 8); - Value* adr_val = this->builder->CreateAdd( - this->gen_reg_load(rs1_idx_val, 0), - this->gen_const(32U, fld_uimm_val)); + Value *adr_val = + this->builder->CreateAdd(this->gen_reg_load(rs1_idx_val, 0), this->gen_const(32U, fld_uimm_val)); uint8_t rs2_idx_val = (fld_rs2_val + 8); - Value* MEM_adr_val = this->gen_reg_load(rs2_idx_val, 0); - this->gen_write_mem( - traits::MEM, - adr_val, - this->builder->CreateZExtOrTrunc(MEM_adr_val,this->get_type(32))); + Value *MEM_adr_val = this->gen_reg_load(rs2_idx_val, 0); + this->gen_write_mem(traits::MEM, adr_val, + this->builder->CreateZExtOrTrunc(MEM_adr_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.NOP - std::tuple __c_nop(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_nop(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.NOP"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ boost::format ins_fmter("C.NOP "); - ins_fmter ; + ins_fmter; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + /* TODO: describe operations for C.NOP ! */ this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.ADDI - std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_addi(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.ADDI"); - + this->gen_sync(iss::PRE_SYNC); - - int8_t fld_nzimm_val = 0 | (bit_sub<2,5>(instr)) | (signed_bit_sub<12,1>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ + + int8_t fld_nzimm_val = 0 | (bit_sub<2, 5>(instr)) | (signed_bit_sub<12, 1>(instr) << 5); + uint8_t fld_rs1_val = 0 | (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_nzimm_val; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - - if(fld_nzimm_val == 0){ + pc = pc + 2; + + if (fld_nzimm_val == 0) { this->gen_raise_trap(0, 2); } - Value* X_rs1_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_nzimm_val)); + Value *X_rs1_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_nzimm_val)); this->builder->CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.JAL - std::tuple __c_jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_jal(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.JAL"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (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) | (signed_bit_sub<12,1>(instr) << 11); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (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) | + (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t rd_val = 1; - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 2)); + Value *X_rd_val = this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 2)); this->builder->CreateStore(X_rd_val, get_reg_ptr(rd_val), false); - Value* PC_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)); + Value *PC_val = + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction C.LI - std::tuple __c_li(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_li(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.LI"); - + this->gen_sync(iss::PRE_SYNC); - - int8_t fld_imm_val = 0 | (bit_sub<2,5>(instr)) | (signed_bit_sub<12,1>(instr) << 5); - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ + + int8_t fld_imm_val = 0 | (bit_sub<2, 5>(instr)) | (signed_bit_sub<12, 1>(instr) << 5); + uint8_t fld_rd_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - - if(fld_rd_val == 0){ + pc = pc + 2; + + if (fld_rd_val == 0) { this->gen_raise_trap(0, 2); } - Value* X_rd_val = this->gen_const(32U, fld_imm_val); + Value *X_rd_val = this->gen_const(32U, fld_imm_val); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.LUI - std::tuple __c_lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_lui(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.LUI"); - + this->gen_sync(iss::PRE_SYNC); - - int32_t fld_nzimm_val = 0 | (bit_sub<2,5>(instr) << 12) | (signed_bit_sub<12,1>(instr) << 17); - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ + + int32_t fld_nzimm_val = 0 | (bit_sub<2, 5>(instr) << 12) | (signed_bit_sub<12, 1>(instr) << 17); + uint8_t fld_rd_val = 0 | (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 % (int64_t)fld_nzimm_val; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - - if(fld_rd_val == 0){ + pc = pc + 2; + + if (fld_rd_val == 0) { this->gen_raise_trap(0, 2); } - if(fld_rd_val == 2){ + if (fld_rd_val == 2) { this->gen_raise_trap(0, 2); } - if(fld_nzimm_val == 0){ + if (fld_nzimm_val == 0) { this->gen_raise_trap(0, 2); } - Value* X_rd_val = this->gen_const(32U, fld_nzimm_val); + Value *X_rd_val = this->gen_const(32U, fld_nzimm_val); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.ADDI16SP - std::tuple __c_addi16sp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_addi16sp(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.ADDI16SP"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_nzimm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (signed_bit_sub<12,1>(instr) << 9); - if(this->disass_enabled){ + + int16_t fld_nzimm_val = 0 | (bit_sub<2, 1>(instr) << 5) | (bit_sub<3, 2>(instr) << 7) | + (bit_sub<5, 1>(instr) << 6) | (bit_sub<6, 1>(instr) << 4) | + (signed_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_nzimm_val; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t x2_idx_val = 2; - Value* X_x2_idx_val = this->builder->CreateAdd( - this->gen_ext( - this->gen_reg_load(x2_idx_val, 0), - 32, true), - this->gen_const(32U, fld_nzimm_val)); + Value *X_x2_idx_val = this->builder->CreateAdd(this->gen_ext(this->gen_reg_load(x2_idx_val, 0), 32, true), + this->gen_const(32U, fld_nzimm_val)); this->builder->CreateStore(X_x2_idx_val, get_reg_ptr(x2_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.SRLI - std::tuple __c_srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_srli(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.SRLI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); - if(this->disass_enabled){ + + uint8_t fld_shamt_val = 0 | (bit_sub<2, 5>(instr)) | (bit_sub<12, 1>(instr) << 5); + uint8_t fld_rs1_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - - if(fld_shamt_val > 31){ + pc = pc + 2; + + if (fld_shamt_val > 31) { this->gen_raise_trap(0, 2); } uint8_t rs1_idx_val = (fld_rs1_val + 8); - Value* X_rs1_idx_val = this->builder->CreateLShr( - this->gen_reg_load(rs1_idx_val, 0), - this->gen_const(32U, fld_shamt_val)); + Value *X_rs1_idx_val = + this->builder->CreateLShr(this->gen_reg_load(rs1_idx_val, 0), this->gen_const(32U, fld_shamt_val)); this->builder->CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.SRAI - std::tuple __c_srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_srai(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.SRAI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); - if(this->disass_enabled){ + + uint8_t fld_shamt_val = 0 | (bit_sub<2, 5>(instr)) | (bit_sub<12, 1>(instr) << 5); + uint8_t fld_rs1_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - - if(fld_shamt_val > 31){ + pc = pc + 2; + + if (fld_shamt_val > 31) { this->gen_raise_trap(0, 2); } uint8_t rs1_idx_val = (fld_rs1_val + 8); - Value* X_rs1_idx_val = this->builder->CreateAShr( - this->gen_reg_load(rs1_idx_val, 0), - this->gen_const(32U, fld_shamt_val)); + Value *X_rs1_idx_val = + this->builder->CreateAShr(this->gen_reg_load(rs1_idx_val, 0), this->gen_const(32U, fld_shamt_val)); this->builder->CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.ANDI - std::tuple __c_andi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_andi(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.ANDI"); - + this->gen_sync(iss::PRE_SYNC); - - int8_t fld_imm_val = 0 | (bit_sub<2,5>(instr)) | (signed_bit_sub<12,1>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); - if(this->disass_enabled){ + + int8_t fld_imm_val = 0 | (bit_sub<2, 5>(instr)) | (signed_bit_sub<12, 1>(instr) << 5); + uint8_t fld_rs1_val = 0 | (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 % (int64_t)fld_imm_val; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t rs1_idx_val = (fld_rs1_val + 8); - Value* X_rs1_idx_val = this->builder->CreateAnd( - this->gen_reg_load(rs1_idx_val, 0), - this->gen_const(32U, fld_imm_val)); + Value *X_rs1_idx_val = + this->builder->CreateAnd(this->gen_reg_load(rs1_idx_val, 0), this->gen_const(32U, fld_imm_val)); this->builder->CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.SUB - std::tuple __c_sub(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_sub(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.SUB"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); - uint8_t fld_rd_val = 0 | (bit_sub<7,3>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rs2_val = 0 | (bit_sub<2, 3>(instr)); + uint8_t fld_rd_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t rd_idx_val = (fld_rd_val + 8); uint8_t rs2_idx_val = (fld_rs2_val + 8); - Value* X_rd_idx_val = this->builder->CreateSub( - this->gen_reg_load(rd_idx_val, 0), - this->gen_reg_load(rs2_idx_val, 0)); + Value *X_rd_idx_val = + this->builder->CreateSub(this->gen_reg_load(rd_idx_val, 0), this->gen_reg_load(rs2_idx_val, 0)); this->builder->CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.XOR - std::tuple __c_xor(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_xor(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.XOR"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); - uint8_t fld_rd_val = 0 | (bit_sub<7,3>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rs2_val = 0 | (bit_sub<2, 3>(instr)); + uint8_t fld_rd_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t rd_idx_val = (fld_rd_val + 8); uint8_t rs2_idx_val = (fld_rs2_val + 8); - Value* X_rd_idx_val = this->builder->CreateXor( - this->gen_reg_load(rd_idx_val, 0), - this->gen_reg_load(rs2_idx_val, 0)); + Value *X_rd_idx_val = + this->builder->CreateXor(this->gen_reg_load(rd_idx_val, 0), this->gen_reg_load(rs2_idx_val, 0)); this->builder->CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.OR - std::tuple __c_or(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_or(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.OR"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); - uint8_t fld_rd_val = 0 | (bit_sub<7,3>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rs2_val = 0 | (bit_sub<2, 3>(instr)); + uint8_t fld_rd_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t rd_idx_val = (fld_rd_val + 8); uint8_t rs2_idx_val = (fld_rs2_val + 8); - Value* X_rd_idx_val = this->builder->CreateOr( - this->gen_reg_load(rd_idx_val, 0), - this->gen_reg_load(rs2_idx_val, 0)); + Value *X_rd_idx_val = + this->builder->CreateOr(this->gen_reg_load(rd_idx_val, 0), this->gen_reg_load(rs2_idx_val, 0)); this->builder->CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.AND - std::tuple __c_and(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_and(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.AND"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); - uint8_t fld_rd_val = 0 | (bit_sub<7,3>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rs2_val = 0 | (bit_sub<2, 3>(instr)); + uint8_t fld_rd_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t rd_idx_val = (fld_rd_val + 8); uint8_t rs2_idx_val = (fld_rs2_val + 8); - Value* X_rd_idx_val = this->builder->CreateAnd( - this->gen_reg_load(rd_idx_val, 0), - this->gen_reg_load(rs2_idx_val, 0)); + Value *X_rd_idx_val = + this->builder->CreateAnd(this->gen_reg_load(rd_idx_val, 0), this->gen_reg_load(rs2_idx_val, 0)); this->builder->CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.J - std::tuple __c_j(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_j(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("C.J"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (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) | (signed_bit_sub<12,1>(instr) << 11); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (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) | + (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - - Value* PC_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)); + pc = pc + 2; + + Value *PC_val = + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction C.BEQZ - std::tuple __c_beqz(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_beqz(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.BEQZ"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (signed_bit_sub<12,1>(instr) << 8); - uint8_t fld_rs1d_val = 0 | (bit_sub<7,3>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<2, 1>(instr) << 5) | (bit_sub<3, 2>(instr) << 1) | + (bit_sub<5, 2>(instr) << 6) | (bit_sub<10, 2>(instr) << 3) | + (signed_bit_sub<12, 1>(instr) << 8); + uint8_t fld_rs1d_val = 0 | (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_rs1d_val % (int64_t)fld_imm_val; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t rs1_val = (fld_rs1d_val + 8); - Value* PC_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1_val, 0), - this->gen_const(32U, 0)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 2)), - 32); + Value *PC_val = this->gen_choose( + this->builder->CreateICmp(ICmpInst::ICMP_EQ, this->gen_reg_load(rs1_val, 0), this->gen_const(32U, 0)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 2)), 32); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction C.BNEZ - std::tuple __c_bnez(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_bnez(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.BNEZ"); - + this->gen_sync(iss::PRE_SYNC); - - uint16_t fld_imm_val = 0 | (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_rs1d_val = 0 | (bit_sub<7,3>(instr)); - if(this->disass_enabled){ + + uint16_t fld_imm_val = 0 | (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_rs1d_val = 0 | (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_rs1d_val % (uint64_t)fld_imm_val; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t rs1_val = (fld_rs1d_val + 8); - Value* PC_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1_val, 0), - this->gen_const(32U, 0)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 2)), - 32); + Value *PC_val = this->gen_choose( + this->builder->CreateICmp(ICmpInst::ICMP_NE, this->gen_reg_load(rs1_val, 0), this->gen_const(32U, 0)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 2)), 32); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction C.SLLI - std::tuple __c_slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_slli(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.SLLI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_shamt_val = 0 | (bit_sub<2, 5>(instr)) | (bit_sub<12, 1>(instr) << 5); + uint8_t fld_rs1_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - - if(fld_rs1_val == 0){ + pc = pc + 2; + + if (fld_rs1_val == 0) { this->gen_raise_trap(0, 2); } - if(fld_shamt_val > 31){ + if (fld_shamt_val > 31) { this->gen_raise_trap(0, 2); } - Value* X_rs1_val = this->builder->CreateShl( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_shamt_val)); + Value *X_rs1_val = + this->builder->CreateShl(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_shamt_val)); this->builder->CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.LQSP - std::tuple __c_lqsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_lqsp(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.LQSP"); - + this->gen_sync(iss::PRE_SYNC); - - uint16_t fld_uimm_val = 0 | (bit_sub<2,4>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 5); - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ + + uint16_t fld_uimm_val = + 0 | (bit_sub<2, 4>(instr) << 6) | (bit_sub<6, 1>(instr) << 4) | (bit_sub<12, 1>(instr) << 5); + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("C.LQSP"); + std::string opcode("C.LQSP"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + /* TODO: describe operations for C.LQSP ! */ this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.LWSP - std::tuple __c_lwsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_lwsp(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.LWSP"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_uimm_val = 0 | (bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5); - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_uimm_val = + 0 | (bit_sub<2, 2>(instr) << 6) | (bit_sub<4, 3>(instr) << 2) | (bit_sub<12, 1>(instr) << 5); + uint8_t fld_rd_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t x2_idx_val = 2; - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(x2_idx_val, 0), - this->gen_const(32U, fld_uimm_val)); - Value* X_rd_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(x2_idx_val, 0), this->gen_const(32U, fld_uimm_val)); + Value *X_rd_val = this->gen_read_mem(traits::MEM, offs_val, 32 / 8); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.MV - std::tuple __c_mv(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_mv(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.MV"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rs2_val = 0 | (bit_sub<2,5>(instr)); - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rs2_val = 0 | (bit_sub<2, 5>(instr)); + uint8_t fld_rd_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - - Value* X_rd_val = this->gen_reg_load(fld_rs2_val, 0); + pc = pc + 2; + + Value *X_rd_val = this->gen_reg_load(fld_rs2_val, 0); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.JR - std::tuple __c_jr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_jr(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.JR"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rs1_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - - Value* PC_val = this->gen_reg_load(fld_rs1_val, 0); + pc = pc + 2; + + Value *PC_val = this->gen_reg_load(fld_rs1_val, 0); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction C.EBREAK - std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_ebreak(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.EBREAK"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("C.EBREAK"); + std::string opcode("C.EBREAK"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + this->gen_raise_trap(0, 3); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction C.ADD - std::tuple __c_add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_add(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.ADD"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rs2_val = 0 | (bit_sub<2,5>(instr)); - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rs2_val = 0 | (bit_sub<2, 5>(instr)); + uint8_t fld_rd_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rd_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); + pc = pc + 2; + + Value *X_rd_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rd_val, 0), this->gen_reg_load(fld_rs2_val, 0)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 C.JALR - std::tuple __c_jalr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_jalr(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.JALR"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rs1_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t rd_val = 1; - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(32U, 2)); + Value *X_rd_val = this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(32U, 2)); this->builder->CreateStore(X_rd_val, get_reg_ptr(rd_val), false); - Value* PC_val = this->gen_reg_load(fld_rs1_val, 0); + Value *PC_val = this->gen_reg_load(fld_rs1_val, 0); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction C.SWSP - std::tuple __c_swsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __c_swsp(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("C.SWSP"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rs2_val = 0 | (bit_sub<2,5>(instr)); - uint8_t fld_uimm_val = 0 | (bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2); - if(this->disass_enabled){ + + uint8_t fld_rs2_val = 0 | (bit_sub<2, 5>(instr)); + uint8_t fld_uimm_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+2; - + pc = pc + 2; + uint8_t x2_idx_val = 2; - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(x2_idx_val, 0), - this->gen_const(32U, fld_uimm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(x2_idx_val, 0), this->gen_const(32U, fld_uimm_val)); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 generated code */ + + /* 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); + std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { + // this->gen_sync(iss::PRE_SYNC); + this->builder->CreateStore(this->builder->CreateLoad(get_reg_ptr(traits::NEXT_PC), true), + get_reg_ptr(traits::PC), true); 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)), + this->builder->CreateAdd(this->builder->CreateLoad(get_reg_ptr(traits::ICOUNT), true), + this->gen_const(64U, 1)), get_reg_ptr(traits::ICOUNT), true); - if(this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC); - pc=pc+((instr&3) == 3?4:2); - this->gen_raise_trap(0, 2); // illegal instruction trap + if (this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC); + pc = pc + ((instr & 3) == 3 ? 4 : 2); + this->gen_raise_trap(0, 2); // illegal instruction trap this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ 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 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() { this(new ARCH()); } -template -vm_impl::vm_impl(ARCH& core, bool dump) : vm::vm_base(core, dump) { +template vm_impl::vm_impl(ARCH &core, bool dump) : vm::vm_base(core, dump) { 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); + 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); } - this->sync_exec=static_cast(this->sync_exec|core.needed_sync()); + this->sync_exec = static_cast(this->sync_exec | core.needed_sync()); } -template -std::tuple vm_impl::gen_single_inst_behavior(virt_addr_t& pc, unsigned int& inst_cnt, llvm::BasicBlock* this_block){ +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; iss::addr_t paddr; const typename traits::addr_t upper_bits = ~traits::PGMASK; 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 + 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); + 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 { + } else { auto res = this->core.read(paddr, 4, data); - if(res!=iss::Ok) - throw trap_access(1, pc.val); + if (res != iss::Ok) throw trap_access(1, pc.val); } - } catch(trap_access& ta){ + } catch (trap_access &ta) { throw trap_access(ta.id, pc.val); } - if(insn==0x0000006f) - throw simulation_stopped(0); + if (insn == 0x0000006f) throw simulation_stopped(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; + 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){ +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 ); +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)), +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); + 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)), +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){ +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)) - }; + 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); + 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); +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 rv32imac -#define CREATE_FUNCS(ARCH) \ -template<> std::unique_ptr create(ARCH* core, unsigned short port, bool dump) {\ - std::unique_ptr > ret = std::make_unique >(*core, dump);\ - debugger::server::run_server(ret.get(), port);\ - return ret;\ -}\ -template<> std::unique_ptr create(std::string inst_name, unsigned short port, bool dump) {\ - return create(new arch::riscv_hart_msu_vp(), port, dump); /* FIXME: memory leak!!!!!!! */\ -}\ -template<> std::unique_ptr create(ARCH* core, bool dump) {\ - return std::make_unique >(*core, dump); /* FIXME: memory leak!!!!!!! */ \ -}\ -template<> std::unique_ptr create(std::string inst_name, bool dump) { \ - return create(new arch::riscv_hart_msu_vp(), dump);\ -} +#define CREATE_FUNCS(ARCH) \ + template <> std::unique_ptr create(ARCH * core, unsigned short port, bool dump) { \ + std::unique_ptr> ret = std::make_unique>(*core, dump); \ + debugger::server::run_server(ret.get(), port); \ + return ret; \ + } \ + template <> std::unique_ptr create(std::string inst_name, unsigned short port, bool dump) { \ + return create(new arch::riscv_hart_msu_vp(), port, dump); /* FIXME: memory leak!!!!!!! */ \ + } \ + template <> std::unique_ptr create(ARCH * core, bool dump) { \ + return std::make_unique>(*core, dump); /* FIXME: memory leak!!!!!!! */ \ + } \ + template <> std::unique_ptr create(std::string inst_name, bool dump) { \ + return create(new arch::riscv_hart_msu_vp(), dump); \ + } CREATE_FUNCS(arch::rv32imac) namespace rv32imac { - template - status target_adapter::set_gen_thread(rp_thread_ref& thread) { - thread_idx=thread; +template status target_adapter::set_gen_thread(rp_thread_ref &thread) { + thread_idx = thread; + return Ok; +} + +template status target_adapter::set_ctrl_thread(rp_thread_ref &thread) { + thread_idx = thread; + return Ok; +} + +template status target_adapter::is_thread_alive(rp_thread_ref &thread, bool &alive) { + alive = 1; + return Ok; +} + +/* List threads. If first is non-zero then start from the first thread, + * otherwise start from arg, result points to array of threads to be + * filled out, result size is number of elements in the result, + * num points to the actual number of threads found, done is + * set if all threads are processed. + */ +template +status target_adapter::thread_list_query(int first, const rp_thread_ref &arg, std::vector &result, + size_t max_num, size_t &num, bool &done) { + if (first == 0) { + result.clear(); + result.push_back(thread_idx); + num = 1; + done = true; return Ok; - } + } else + return NotSupported; +} - template - status target_adapter::set_ctrl_thread(rp_thread_ref& thread) { - thread_idx=thread; - return Ok; - } +template status target_adapter::current_thread_query(rp_thread_ref &thread) { + thread = thread_idx; + return Ok; +} - template - status target_adapter::is_thread_alive(rp_thread_ref& thread, bool& alive) { - alive=1; - return Ok; +template +status target_adapter::read_registers(std::vector &data, std::vector &avail) { + LOG(TRACE) << "reading target registers"; + // return idx<0?:; + data.clear(); + avail.clear(); + std::vector reg_data; + for (size_t reg_no = 0; reg_no < arch::traits::NUM_REGS; ++reg_no) { + auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); + auto reg_width = reg_bit_width / 8; + reg_data.resize(reg_width); + vm->get_arch()->get_reg(reg_no, reg_data); + for (size_t j = 0; j < reg_data.size(); ++j) { + data.push_back(reg_data[j]); + avail.push_back(0xff); + } } - - /* List threads. If first is non-zero then start from the first thread, - * otherwise start from arg, result points to array of threads to be - * filled out, result size is number of elements in the result, - * num points to the actual number of threads found, done is - * set if all threads are processed. - */ - template - status target_adapter::thread_list_query(int first, const rp_thread_ref& arg, std::vector& result, size_t max_num, - size_t& num, bool& done) { - if(first==0){ - result.clear(); - result.push_back(thread_idx); - num=1; - done=true; - return Ok; - } else - return NotSupported; - } - - template - status target_adapter::current_thread_query(rp_thread_ref& thread) { - thread=thread_idx; - return Ok; - } - - template - status target_adapter::read_registers(std::vector& data, std::vector& avail) { - LOG(TRACE)<<"reading target registers"; - //return idx<0?:; - data.clear(); - avail.clear(); - std::vector reg_data; - for(size_t reg_no = 0; reg_no < arch::traits::NUM_REGS; ++reg_no){ - auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); - auto reg_width=reg_bit_width/8; - reg_data.resize(reg_width); - vm->get_arch()->get_reg(reg_no, reg_data); - for(size_t j=0; j::NUM_REGS < 65) { + auto reg_width = sizeof(typename arch::traits::reg_t); + for (size_t reg_no = 0; reg_no < 33; ++reg_no) { + for (size_t j = 0; j < reg_width; ++j) { + data.push_back(0x0); + avail.push_back(0x00); } } - // work around fill with F type registers - if(arch::traits::NUM_REGS < 65){ - auto reg_width=sizeof(typename arch::traits::reg_t); - for(size_t reg_no = 0; reg_no < 33; ++reg_no){ - for(size_t j=0; j - status target_adapter::write_registers(const std::vector& data) { - size_t data_index=0; - auto reg_count=arch::traits::NUM_REGS; - std::vector reg_data; - for(size_t reg_no = 0; reg_no < reg_count; ++reg_no){ - auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); - auto reg_width=reg_bit_width/8; - vm->get_arch()->set_reg(reg_no, std::vector(data.begin()+data_index, data.begin()+data_index+reg_width)); - data_index+=reg_width; - } - return Ok; +template status target_adapter::write_registers(const std::vector &data) { + size_t data_index = 0; + auto reg_count = arch::traits::NUM_REGS; + std::vector reg_data; + for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) { + auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); + auto reg_width = reg_bit_width / 8; + vm->get_arch()->set_reg(reg_no, + std::vector(data.begin() + data_index, data.begin() + data_index + reg_width)); + data_index += reg_width; } + return Ok; +} - template - status target_adapter::read_single_register(unsigned int reg_no, std::vector& data, std::vector& avail) { - if(reg_no<65){ - //auto reg_size = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no))/8; - data.resize(0); - vm->get_arch()->get_reg(reg_no, data); - avail.resize(data.size()); - std::fill(avail.begin(), avail.end(), 0xff); - } else { - typed_addr_t a(iss::DEBUG_READ, traits::CSR, reg_no-65); - data.resize(sizeof(typename traits::reg_t)); - avail.resize(sizeof(typename traits::reg_t)); - std::fill(avail.begin(), avail.end(), 0xff); - vm->get_arch()->read(a, data.size(), data.data()); - } - return data.size()>0?Ok:Err; +template +status target_adapter::read_single_register(unsigned int reg_no, std::vector &data, + std::vector &avail) { + if (reg_no < 65) { + // auto reg_size = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no))/8; + data.resize(0); + vm->get_arch()->get_reg(reg_no, data); + avail.resize(data.size()); + std::fill(avail.begin(), avail.end(), 0xff); + } else { + typed_addr_t a(iss::DEBUG_READ, traits::CSR, reg_no - 65); + data.resize(sizeof(typename traits::reg_t)); + avail.resize(sizeof(typename traits::reg_t)); + std::fill(avail.begin(), avail.end(), 0xff); + vm->get_arch()->read(a, data.size(), data.data()); } + return data.size() > 0 ? Ok : Err; +} - template - status target_adapter::write_single_register(unsigned int reg_no, const std::vector& data) { - if(reg_no<65) - vm->get_arch()->set_reg(reg_no, data); - else { - typed_addr_t a(iss::DEBUG_WRITE, traits::CSR, reg_no-65); - vm->get_arch()->write(a, data.size(), data.data()); - } - return Ok; - } - - template - status target_adapter::read_mem(uint64_t addr, std::vector& data) { - auto a=map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); - auto f = [&]()->status { - return vm->get_arch()->read(a, data.size(), data.data()); - }; - return srv->execute_syncronized(f); - - } - - template - status target_adapter::write_mem(uint64_t addr, const std::vector& data) { - auto a=map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); - return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data()); - } - - template - status target_adapter::process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) { - return NotSupported; - } - - template - status target_adapter::offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) { - text=0; - data=0; - bss=0; - return Ok; - } - - template - status target_adapter::crc_query(uint64_t addr, size_t len, uint32_t& val) { - return NotSupported; - } - - template - status target_adapter::raw_query(std::string in_buf, std::string& out_buf) { - return NotSupported; - } - - template - status target_adapter::threadinfo_query(int first, std::string& out_buf) { - if(first){ - std::stringstream ss; - ss<<"m"< - status target_adapter::threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) { - char buf[20]; - memset(buf, 0, 20); - sprintf (buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); - out_buf=buf; - return Ok; - } - - template - status target_adapter::packetsize_query(std::string& out_buf) { - out_buf="PacketSize=1000"; - return Ok; - } - - template - status target_adapter::add_break(int type, uint64_t addr, unsigned int length) { - auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr}); - auto eaddr=map_addr({iss::CODE, iss::PHYSICAL, addr+length}); - target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val-saddr.val); - LOG(TRACE)<<"Adding breakpoint with handle "< - status target_adapter::remove_break(int type, uint64_t addr, unsigned int length) { - auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr}); - unsigned handle=target_adapter_base::bp_lut.getEntry(saddr.val); - // TODO: check length of addr range - if(handle){ - LOG(TRACE)<<"Removing breakpoint with handle "< - status target_adapter::resume_from_addr(bool step, int sig, uint64_t addr) { - unsigned reg_no = arch::traits::PC; - std::vector data(8); - *(reinterpret_cast(&data[0]))=addr; +template +status target_adapter::write_single_register(unsigned int reg_no, const std::vector &data) { + if (reg_no < 65) vm->get_arch()->set_reg(reg_no, data); - return resume_from_current(step, sig); + else { + typed_addr_t a(iss::DEBUG_WRITE, traits::CSR, reg_no - 65); + vm->get_arch()->write(a, data.size(), data.data()); } + return Ok; +} + +template status target_adapter::read_mem(uint64_t addr, std::vector &data) { + auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); + auto f = [&]() -> status { return vm->get_arch()->read(a, data.size(), data.data()); }; + return srv->execute_syncronized(f); +} + +template status target_adapter::write_mem(uint64_t addr, const std::vector &data) { + auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); + return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data()); +} + +template +status target_adapter::process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) { + return NotSupported; +} + +template status target_adapter::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) { + text = 0; + data = 0; + bss = 0; + return Ok; +} + +template status target_adapter::crc_query(uint64_t addr, size_t len, uint32_t &val) { + return NotSupported; +} + +template status target_adapter::raw_query(std::string in_buf, std::string &out_buf) { + return NotSupported; +} + +template status 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(); + } else { + out_buf = "l"; + } + return Ok; +} + +template +status target_adapter::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) { + char buf[20]; + memset(buf, 0, 20); + sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); + out_buf = buf; + return Ok; +} + +template status target_adapter::packetsize_query(std::string &out_buf) { + out_buf = "PacketSize=1000"; + return Ok; +} + +template status target_adapter::add_break(int type, uint64_t addr, unsigned int length) { + auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); + auto eaddr = map_addr({iss::CODE, iss::PHYSICAL, addr + length}); + target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); + LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex + << saddr.val << std::dec; + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Ok; +} + +template status target_adapter::remove_break(int type, uint64_t addr, unsigned int length) { + auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); + unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); + // TODO: check length of addr range + if (handle) { + LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val + << std::dec; + target_adapter_base::bp_lut.removeEntry(handle); + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Ok; + } + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Err; +} + +template status target_adapter::resume_from_addr(bool step, int sig, uint64_t addr) { + unsigned reg_no = arch::traits::PC; + std::vector data(8); + *(reinterpret_cast(&data[0])) = addr; + vm->get_arch()->set_reg(reg_no, data); + return resume_from_current(step, sig); +} } // namespace rv32imac } // namespace iss diff --git a/riscv/src/internal/vm_rv64ia.cpp b/riscv/src/internal/vm_rv64ia.cpp index 5cc27fc..6d55e51 100644 --- a/riscv/src/internal/vm_rv64ia.cpp +++ b/riscv/src/internal/vm_rv64ia.cpp @@ -1,21 +1,21 @@ //////////////////////////////////////////////////////////////////////////////// // 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 @@ -27,25 +27,25 @@ // 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 "iss/vm_base.h" #include "iss/arch/rv64ia.h" #include "iss/debugger/server.h" +#include "iss/vm_base.h" -#include #include "iss/arch/riscv_hart_msu_vp.h" +#include namespace iss { namespace rv64ia { @@ -53,28 +53,22 @@ using namespace iss::arch; using namespace llvm; using namespace iss::debugger; -template -struct vm_impl; +template struct vm_impl; -template -struct target_adapter: public target_adapter_base { +template struct target_adapter : public target_adapter_base { - target_adapter(server_if* srv, vm_impl* vm) - : target_adapter_base(srv) - , vm(vm) - { - } + target_adapter(server_if *srv, vm_impl *vm) : target_adapter_base(srv), vm(vm) {} /*============== Thread Control ===============================*/ /* Set generic thread */ - status set_gen_thread(rp_thread_ref& thread) override; + status set_gen_thread(rp_thread_ref &thread) override; /* Set control thread */ - status set_ctrl_thread(rp_thread_ref& thread) override; + status set_ctrl_thread(rp_thread_ref &thread) override; /* Get thread status */ - status is_thread_alive(rp_thread_ref& thread, bool& alive) override; + status is_thread_alive(rp_thread_ref &thread, bool &alive) override; /*============= Register Access ================================*/ @@ -82,49 +76,51 @@ struct target_adapter: public target_adapter_base { target byte order. If register is not available corresponding bytes in avail_buf are 0, otherwise avail buf is 1 */ - status read_registers(std::vector& data, std::vector& avail) override; + status read_registers(std::vector &data, std::vector &avail) override; /* Write all registers. buf is 4-byte aligned and it is in target byte order */ - status write_registers(const std::vector& data) override; + status write_registers(const std::vector &data) override; /* Read one register. buf is 4-byte aligned and it is in target byte order. If register is not available corresponding bytes in avail_buf are 0, otherwise avail buf is 1 */ - status read_single_register(unsigned int reg_no, std::vector& buf, std::vector& avail_buf) override; + status read_single_register(unsigned int reg_no, std::vector &buf, + std::vector &avail_buf) override; /* Write one register. buf is 4-byte aligned and it is in target byte order */ - status write_single_register(unsigned int reg_no, const std::vector& buf) override; + status write_single_register(unsigned int reg_no, const std::vector &buf) override; /*=================== Memory Access =====================*/ /* Read memory, buf is 4-bytes aligned and it is in target byte order */ - status read_mem(uint64_t addr, std::vector& buf) override; + status read_mem(uint64_t addr, std::vector &buf) override; /* Write memory, buf is 4-bytes aligned and it is in target byte order */ - status write_mem(uint64_t addr, const std::vector& buf) override; + status write_mem(uint64_t addr, const std::vector &buf) override; - status process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) override; + status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override; - status thread_list_query(int first, const rp_thread_ref& arg, std::vector& result, size_t max_num, size_t& num, bool& done) override; + status thread_list_query(int first, const rp_thread_ref &arg, std::vector &result, size_t max_num, + size_t &num, bool &done) override; - status current_thread_query(rp_thread_ref& thread) override; + status current_thread_query(rp_thread_ref &thread) override; - status offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) override; + status offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) override; - status crc_query(uint64_t addr, size_t len, uint32_t& val) override; + status crc_query(uint64_t addr, size_t len, uint32_t &val) override; - status raw_query(std::string in_buf, std::string& out_buf) override; + status raw_query(std::string in_buf, std::string &out_buf) override; - status threadinfo_query(int first, std::string& out_buf) override; + status threadinfo_query(int first, std::string &out_buf) override; - status threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) override; + status threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) override; - status packetsize_query(std::string& out_buf) override; + status packetsize_query(std::string &out_buf) override; status add_break(int type, uint64_t addr, unsigned int length) override; @@ -133,52 +129,46 @@ struct target_adapter: public target_adapter_base { status resume_from_addr(bool step, int sig, uint64_t addr) override; protected: - static inline constexpr addr_t map_addr(const addr_t& i){ - return i; - } + static inline constexpr addr_t map_addr(const addr_t &i) { return i; } - vm_impl* vm; + vm_impl *vm; rp_thread_ref thread_idx; }; -template -struct vm_impl: public vm::vm_base { - using super = typename vm::vm_base; +template struct vm_impl : public vm::vm_base { + 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 ; + using addr_t = typename super::addr_t; vm_impl(); - vm_impl(ARCH& core, bool dump=false); + vm_impl(ARCH &core, bool dump = false); - void enableDebug(bool enable) { - super::sync_exec=super::ALL_SYNC; - } + 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 target_adapter(srv, this); + 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 target_adapter(srv, this); return vm::vm_base::tgt_adapter; } - protected: - - template inline - llvm::ConstantInt* size(T type){ + 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 { + inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, + unsigned size) const { return this->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 &, + llvm::BasicBlock *) override; - void gen_leave_behavior(llvm::BasicBlock* leave_blk) override; + void gen_leave_behavior(llvm::BasicBlock *leave_blk) override; void gen_raise_trap(uint16_t trap_id, uint16_t cause); @@ -186,113 +176,109 @@ protected: void gen_wait(unsigned type); - void gen_trap_behavior(llvm::BasicBlock*) override; + void gen_trap_behavior(llvm::BasicBlock *) override; - void gen_trap_check(llvm::BasicBlock* bb); + void gen_trap_check(llvm::BasicBlock *bb); - 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)); + 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); } - inline - llvm::Value* get_reg_ptr(unsigned i){ - void* ptr = this->core.get_regs_base_ptr()+traits::reg_byte_offset(i); - llvm::PointerType* ptrType=nullptr; - switch (traits::reg_bit_width(i)>>3) { + inline llvm::Value *get_reg_ptr(unsigned i) { + void *ptr = this->core.get_regs_base_ptr() + traits::reg_byte_offset(i); + llvm::PointerType *ptrType = nullptr; + switch (traits::reg_bit_width(i) >> 3) { case 8: - ptrType=llvm::Type::getInt64PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt64PtrTy(this->mod->getContext()); break; case 4: - ptrType=llvm::Type::getInt32PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt32PtrTy(this->mod->getContext()); break; case 2: - ptrType=llvm::Type::getInt16PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt16PtrTy(this->mod->getContext()); break; case 1: - ptrType=llvm::Type::getInt8PtrTy(this->mod->getContext()); + ptrType = llvm::Type::getInt8PtrTy(this->mod->getContext()); break; default: throw std::runtime_error("unsupported access with"); break; } return llvm::ConstantExpr::getIntToPtr( - llvm::ConstantInt::get(this->mod->getContext(), llvm::APInt( - 8/*bits*/ * sizeof(uint8_t*), - reinterpret_cast(ptr) - )), - ptrType); + llvm::ConstantInt::get(this->mod->getContext(), + llvm::APInt(8 /*bits*/ * sizeof(uint8_t *), reinterpret_cast(ptr))), + ptrType); } - inline - llvm::Value* gen_reg_load(unsigned i, unsigned level=0){ -// if(level){ - return this->builder->CreateLoad(get_reg_ptr(i), false); -// } else { -// if(!this->loaded_regs[i]) -// this->loaded_regs[i]=this->builder->CreateLoad(get_reg_ptr(i), false); -// return this->loaded_regs[i]; -// } + inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) { + // if(level){ + return this->builder->CreateLoad(get_reg_ptr(i), false); + // } else { + // if(!this->loaded_regs[i]) + // this->loaded_regs[i]=this->builder->CreateLoad(get_reg_ptr(i), + // false); + // return this->loaded_regs[i]; + // } } - inline - void gen_set_pc(virt_addr_t pc){ - llvm::Value* pc_l = this->builder->CreateSExt(this->gen_const(traits::caddr_bit_width, (unsigned)pc), this->get_type(traits::caddr_bit_width)); + inline void gen_set_pc(virt_addr_t pc) { + llvm::Value *pc_l = this->builder->CreateSExt(this->gen_const(traits::caddr_bit_width, (unsigned)pc), + this->get_type(traits::caddr_bit_width)); super::gen_set_reg(traits::PC, pc_l); } // some compile time constants - enum {MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111}; - enum {EXTR_MASK16 = MASK16>>2, EXTR_MASK32 = MASK32>>2}; - enum {LUT_SIZE = 1<< bit_count(EXTR_MASK32), LUT_SIZE_C = 1<> 2, EXTR_MASK32 = MASK32 >> 2 }; + enum { LUT_SIZE = 1 << bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << 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, + llvm::BasicBlock *bb); compile_func lut[LUT_SIZE]; std::array lut_00, lut_01, lut_10; std::array lut_11; - compile_func* qlut[4];// = {lut_00, lut_01, lut_10, lut_11}; + compile_func *qlut[4]; // = {lut_00, lut_01, lut_10, lut_11}; - const uint32_t lutmasks[4]={EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}; + const uint32_t lutmasks[4] = {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; + 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<>2, lutmasks[val&0x3], 0); - } + 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<= 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); + 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; @@ -303,7 +289,7 @@ private: * start opcode definitions ****************************************************************************/ struct InstructionDesriptor { - size_t length; + size_t length; uint32_t value; uint32_t mask; compile_func op; @@ -464,3421 +450,2957 @@ private: {32, 0b11100000000000000011000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_d}, }; // instruction LWU - std::tuple __lwu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lwu(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LWU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - false); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 32 / 8), 64, false); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LD - std::tuple __ld(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __ld(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LD"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 64 / 8), 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SD - std::tuple __sd(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sd(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SD"); - + this->gen_sync(iss::PRE_SYNC); - - uint16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint16_t fld_imm_val = 0 | (bit_sub<7, 5>(instr)) | (signed_bit_sub<25, 7>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_ext( - this->gen_const(64U, fld_imm_val), - 64, - true)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + pc = pc + 4; + + Value *offs_val = this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), + this->gen_ext(this->gen_const(64U, fld_imm_val), 64, true)); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLLI - std::tuple __slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __slli(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SLLI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_shamt_val = 0 | (bit_sub<20,6>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_shamt_val = 0 | (bit_sub<20, 6>(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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateShl( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_shamt_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateShl(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_shamt_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRLI - std::tuple __srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __srli(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SRLI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_shamt_val = 0 | (bit_sub<20,6>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_shamt_val = 0 | (bit_sub<20, 6>(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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateLShr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_shamt_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateLShr(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_shamt_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRAI - std::tuple __srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __srai(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SRAI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_shamt_val = 0 | (bit_sub<20,6>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_shamt_val = 0 | (bit_sub<20, 6>(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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAShr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_shamt_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAShr(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_shamt_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 ADDIW - std::tuple __addiw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __addiw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("ADDIW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_ext( - this->builder->CreateTrunc( - this->gen_reg_load(fld_rs1_val, 0), - this-> get_type(32) - ), - 64, - true), - this->gen_ext( - this->gen_const(64U, fld_imm_val), - 64, - true)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = this->builder->CreateAdd( + this->gen_ext(this->builder->CreateTrunc(this->gen_reg_load(fld_rs1_val, 0), this->get_type(32)), 64, + true), + this->gen_ext(this->gen_const(64U, fld_imm_val), 64, true)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLLIW - std::tuple __slliw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __slliw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SLLIW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_shamt_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - 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, 0), - this-> get_type(32) - ), + 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, 0), this->get_type(32)), this->gen_const(32U, fld_shamt_val)); - Value* X_rd_val = this->gen_ext( - sh_val_val, - 64, - true); + Value *X_rd_val = this->gen_ext(sh_val_val, 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRLIW - std::tuple __srliw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __srliw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SRLIW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_shamt_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* sh_val_val = this->builder->CreateLShr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_shamt_val)); - Value* X_rd_val = this->gen_ext( - sh_val_val, - 64, - true); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *sh_val_val = + this->builder->CreateLShr(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_shamt_val)); + Value *X_rd_val = this->gen_ext(sh_val_val, 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRAIW - std::tuple __sraiw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sraiw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SRAIW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_shamt_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* sh_val_val = this->builder->CreateAShr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(32U, fld_shamt_val)); - Value* X_rd_val = this->gen_ext( - sh_val_val, - 64, - true); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *sh_val_val = + this->builder->CreateAShr(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(32U, fld_shamt_val)); + Value *X_rd_val = this->gen_ext(sh_val_val, 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 ADDW - std::tuple __addw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __addw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("ADDW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("ADDW"); + std::string opcode("ADDW"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + /* TODO: describe operations for ADDW ! */ this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SUBW - std::tuple __subw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __subw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SUBW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("SUBW"); + std::string opcode("SUBW"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + /* TODO: describe operations for SUBW ! */ this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLLW - std::tuple __sllw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sllw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SLLW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* sh_val_val = this->builder->CreateShl( + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *sh_val_val = this->builder->CreateShl( this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - this->gen_const(32U, 31))); - Value* X_rd_val = this->gen_ext( - sh_val_val, - 64, - true); + this->builder->CreateAnd(this->gen_reg_load(fld_rs2_val, 0), this->gen_const(32U, 31))); + Value *X_rd_val = this->gen_ext(sh_val_val, 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRLW - std::tuple __srlw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __srlw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SRLW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* sh_val_val = this->builder->CreateLShr( + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *sh_val_val = this->builder->CreateLShr( this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - this->gen_const(32U, 31))); - Value* X_rd_val = this->gen_ext( - sh_val_val, - 64, - true); + this->builder->CreateAnd(this->gen_reg_load(fld_rs2_val, 0), this->gen_const(32U, 31))); + Value *X_rd_val = this->gen_ext(sh_val_val, 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRAW - std::tuple __sraw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sraw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SRAW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* sh_val_val = this->builder->CreateAShr( + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *sh_val_val = this->builder->CreateAShr( this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - this->gen_const(32U, 31))); - Value* X_rd_val = this->gen_ext( - sh_val_val, - 64, - true); + this->builder->CreateAnd(this->gen_reg_load(fld_rs2_val, 0), this->gen_const(32U, 31))); + Value *X_rd_val = this->gen_ext(sh_val_val, 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LUI - std::tuple __lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lui(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LUI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - int32_t fld_imm_val = 0 | (signed_bit_sub<12,20>(instr) << 12); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + int32_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_const(64U, fld_imm_val); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_const(64U, fld_imm_val); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AUIPC - std::tuple __auipc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __auipc(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("AUIPC"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - int32_t fld_imm_val = 0 | (signed_bit_sub<12,20>(instr) << 12); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + int32_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, fld_imm_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, fld_imm_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 JAL - std::tuple __jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __jal(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("JAL"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - int32_t fld_imm_val = 0 | (bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (signed_bit_sub<31,1>(instr) << 20); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + int32_t fld_imm_val = 0 | (bit_sub<12, 8>(instr) << 12) | (bit_sub<20, 1>(instr) << 11) | + (bit_sub<21, 10>(instr) << 1) | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, 4)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, 4)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* PC_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, fld_imm_val)); + Value *PC_val = + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, fld_imm_val)); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction JALR - std::tuple __jalr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __jalr(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("JALR"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, 4)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, 4)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* ret_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); - Value* PC_val = this->builder->CreateAnd( - ret_val, - this->builder->CreateNot(this->gen_const(64U, 1))); + Value *ret_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); + Value *PC_val = this->builder->CreateAnd(ret_val, this->builder->CreateNot(this->gen_const(64U, 1))); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BEQ - std::tuple __beq(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __beq(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("BEQ"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, 4)), - 64); + pc = pc + 4; + + Value *PC_val = this->gen_choose( + this->builder->CreateICmp(ICmpInst::ICMP_EQ, this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs2_val, 0)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, 4)), 64); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BNE - std::tuple __bne(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __bne(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("BNE"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, 4)), - 64); + pc = pc + 4; + + Value *PC_val = this->gen_choose( + this->builder->CreateICmp(ICmpInst::ICMP_NE, this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs2_val, 0)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, 4)), 64); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BLT - std::tuple __blt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __blt(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("BLT"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - 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, 0), - 64, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 64, true)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, 4)), - 64); + 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, 0), 64, true), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 64, true)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, 4)), 64); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BGE - std::tuple __bge(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __bge(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("BGE"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - 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, 0), - 64, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 64, true)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, 4)), - 64); + 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, 0), 64, true), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 64, true)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, 4)), 64); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BLTU - std::tuple __bltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __bltu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("BLTU"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, 4)), - 64); + pc = pc + 4; + + Value *PC_val = this->gen_choose( + this->builder->CreateICmp(ICmpInst::ICMP_ULT, this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs2_val, 0)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, 4)), 64); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction BGEU - std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __bgeu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("BGEU"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 1>(instr) << 11) | (bit_sub<8, 4>(instr) << 1) | + (bit_sub<25, 6>(instr) << 5) | (signed_bit_sub<31, 1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_UGE, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, fld_imm_val)), - this->builder->CreateAdd( - this->gen_reg_load(traits::PC, 0), - this->gen_const(64U, 4)), - 64); + pc = pc + 4; + + Value *PC_val = this->gen_choose( + this->builder->CreateICmp(ICmpInst::ICMP_UGE, this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs2_val, 0)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, fld_imm_val)), + this->builder->CreateAdd(this->gen_reg_load(traits::PC, 0), this->gen_const(64U, 4)), 64); this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction LB - std::tuple __lb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lb(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LB"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 64, - true); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 8 / 8), 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LH - std::tuple __lh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lh(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LH"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 64, - true); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 16 / 8), 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LW - std::tuple __lw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lw(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 64, - true); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 32 / 8), 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LBU - std::tuple __lbu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lbu(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LBU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 64, - false); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 8 / 8), 64, false); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LHU - std::tuple __lhu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __lhu(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("LHU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 64, - false); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 16 / 8), 64, false); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SB - std::tuple __sb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sb(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SB"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 5>(instr)) | (signed_bit_sub<25, 7>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(8))); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(8))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SH - std::tuple __sh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sh(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SH"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 5>(instr)) | (signed_bit_sub<25, 7>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(16))); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(16))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SW - std::tuple __sw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sw(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SW"); - + this->gen_sync(iss::PRE_SYNC); - - int16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + int16_t fld_imm_val = 0 | (bit_sub<7, 5>(instr)) | (signed_bit_sub<25, 7>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + pc = pc + 4; + + Value *offs_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(32))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 ADDI - std::tuple __addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __addi(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("ADDI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLTI - std::tuple __slti(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __slti(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SLTI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 64, true), - this->gen_ext( - this->gen_const(64U, fld_imm_val), - 64, true)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->gen_choose(this->builder->CreateICmp(ICmpInst::ICMP_SLT, + this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 64, true), + this->gen_ext(this->gen_const(64U, fld_imm_val), 64, true)), + this->gen_const(64U, 1), this->gen_const(64U, 0), 64); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLTIU - std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sltiu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SLTIU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + int64_t full_imm_val = fld_imm_val; - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 64, false), - this->gen_ext( - full_imm_val, - 64, false)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); + if (fld_rd_val != 0) { + Value *X_rd_val = + this->gen_choose(this->builder->CreateICmp(ICmpInst::ICMP_ULT, + this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 64, false), + this->gen_ext(full_imm_val, 64, false)), + this->gen_const(64U, 1), this->gen_const(64U, 0), 64); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 XORI - std::tuple __xori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __xori(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("XORI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateXor( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateXor(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 ORI - std::tuple __ori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __ori(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("ORI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateOr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateOr(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 ANDI - std::tuple __andi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __andi(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("ANDI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + int16_t fld_imm_val = 0 | (signed_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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAnd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_const(64U, fld_imm_val)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAnd(this->gen_reg_load(fld_rs1_val, 0), this->gen_const(64U, fld_imm_val)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 ADD - std::tuple __add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __add(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("ADD"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAdd(this->gen_reg_load(fld_rs1_val, 0), this->gen_reg_load(fld_rs2_val, 0)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SUB - std::tuple __sub(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sub(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SUB"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateSub( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateSub(this->gen_reg_load(fld_rs1_val, 0), this->gen_reg_load(fld_rs2_val, 0)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLL - std::tuple __sll(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sll(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SLL"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateShl( - this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 63)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = this->builder->CreateShl( + this->gen_reg_load(fld_rs1_val, 0), this->builder->CreateAnd(this->gen_reg_load(fld_rs2_val, 0), 63)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLT - std::tuple __slt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __slt(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SLT"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 64, true), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 64, true)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->gen_choose(this->builder->CreateICmp(ICmpInst::ICMP_SLT, + this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 64, true), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 64, true)), + this->gen_const(64U, 1), this->gen_const(64U, 0), 64); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SLTU - std::tuple __sltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sltu(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SLTU"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 64, - false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 64, - false)), - this->gen_const(64U, 1), - this->gen_const(64U, 0), - 64); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->gen_choose(this->builder->CreateICmp( + ICmpInst::ICMP_ULT, this->gen_ext(this->gen_reg_load(fld_rs1_val, 0), 64, false), + this->gen_ext(this->gen_reg_load(fld_rs2_val, 0), 64, false)), + this->gen_const(64U, 1), this->gen_const(64U, 0), 64); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 XOR - std::tuple __xor(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __xor(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("XOR"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateXor( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateXor(this->gen_reg_load(fld_rs1_val, 0), this->gen_reg_load(fld_rs2_val, 0)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRL - std::tuple __srl(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __srl(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SRL"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateLShr( - this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 63)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = this->builder->CreateLShr( + this->gen_reg_load(fld_rs1_val, 0), this->builder->CreateAnd(this->gen_reg_load(fld_rs2_val, 0), 63)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SRA - std::tuple __sra(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sra(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("SRA"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAShr( - this->gen_reg_load(fld_rs1_val, 0), - this->builder->CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 63)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = this->builder->CreateAShr( + this->gen_reg_load(fld_rs1_val, 0), this->builder->CreateAnd(this->gen_reg_load(fld_rs2_val, 0), 63)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 OR - std::tuple __or(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __or(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("OR"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateOr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateOr(this->gen_reg_load(fld_rs1_val, 0), this->gen_reg_load(fld_rs2_val, 0)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AND - std::tuple __and(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __and(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("AND"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->builder->CreateAnd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = + this->builder->CreateAnd(this->gen_reg_load(fld_rs1_val, 0), this->gen_reg_load(fld_rs2_val, 0)); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 FENCE - std::tuple __fence(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __fence(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("FENCE"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_succ_val = 0 | (bit_sub<20,4>(instr)); - uint8_t fld_pred_val = 0 | (bit_sub<24,4>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_succ_val = 0 | (bit_sub<20, 4>(instr)); + uint8_t fld_pred_val = 0 | (bit_sub<24, 4>(instr)); + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("FENCE"); + std::string opcode("FENCE"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* FENCE_fence_val = this->builder->CreateOr( - this->builder->CreateShl( - this->gen_const(64U, fld_pred_val), - this->gen_const(64U, 4)), + pc = pc + 4; + + Value *FENCE_fence_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, - (uint64_t)0, - this->builder->CreateZExtOrTrunc(FENCE_fence_val,this->get_type(64))); + this->gen_write_mem(traits::FENCE, (uint64_t)0, + this->builder->CreateZExtOrTrunc(FENCE_fence_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 FENCE_I - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_imm_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_imm_val = 0 | (bit_sub<20, 12>(instr)); + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("FENCE_I"); + std::string opcode("FENCE_I"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* FENCE_fencei_val = this->gen_const(64U, fld_imm_val); - this->gen_write_mem( - traits::FENCE, - (uint64_t)1, - this->builder->CreateZExtOrTrunc(FENCE_fencei_val,this->get_type(64))); + pc = pc + 4; + + Value *FENCE_fencei_val = this->gen_const(64U, fld_imm_val); + this->gen_write_mem(traits::FENCE, (uint64_t)1, + this->builder->CreateZExtOrTrunc(FENCE_fencei_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::FLUSH, nullptr); } - + // instruction ECALL - std::tuple __ecall(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __ecall(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("ECALL"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("ECALL"); + std::string opcode("ECALL"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_raise_trap(0, 11); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction EBREAK - std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __ebreak(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("EBREAK"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("EBREAK"); + std::string opcode("EBREAK"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_raise_trap(0, 3); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction URET - std::tuple __uret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __uret(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("URET"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("URET"); + std::string opcode("URET"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_leave_trap(0); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction SRET - std::tuple __sret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __sret(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("SRET"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("SRET"); + std::string opcode("SRET"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_leave_trap(1); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction MRET - std::tuple __mret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __mret(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("MRET"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("MRET"); + std::string opcode("MRET"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_leave_trap(3); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ this->gen_trap_check(this->leave_blk); return std::make_tuple(iss::vm::BRANCH, nullptr); } - + // instruction WFI - std::tuple __wfi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __wfi(virt_addr_t &pc, code_word_t instr, llvm::BasicBlock *bb) { bb->setName("WFI"); - + this->gen_sync(iss::PRE_SYNC); - + ; - if(this->disass_enabled){ + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("WFI"); + std::string opcode("WFI"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - + pc = pc + 4; + this->gen_wait(1); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SFENCE.VMA - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + if (this->disass_enabled) { /* generate console output when executing the command */ - std::string opcode("SFENCE.VMA"); + std::string opcode("SFENCE.VMA"); boost::format fmter("0x%1$016x\t\t%2$-40s\t\t%%v"); fmter % pc.val % opcode; - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* FENCE_fencevmal_val = this->gen_const(64U, fld_rs1_val); - this->gen_write_mem( - traits::FENCE, - (uint64_t)2, - this->builder->CreateZExtOrTrunc(FENCE_fencevmal_val,this->get_type(64))); - Value* FENCE_fencevmau_val = this->gen_const(64U, fld_rs2_val); - this->gen_write_mem( - traits::FENCE, - (uint64_t)3, - this->builder->CreateZExtOrTrunc(FENCE_fencevmau_val,this->get_type(64))); + pc = pc + 4; + + Value *FENCE_fencevmal_val = this->gen_const(64U, fld_rs1_val); + this->gen_write_mem(traits::FENCE, (uint64_t)2, + this->builder->CreateZExtOrTrunc(FENCE_fencevmal_val, this->get_type(64))); + Value *FENCE_fencevmau_val = this->gen_const(64U, fld_rs2_val); + this->gen_write_mem(traits::FENCE, (uint64_t)3, + this->builder->CreateZExtOrTrunc(FENCE_fencevmau_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRW - std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrw(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRW"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* rs_val_val = this->gen_reg_load(fld_rs1_val, 0); - if(fld_rd_val != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64/8); - Value* CSR_csr_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(64))); - Value* X_rd_val = csr_val_val; + pc = pc + 4; + + Value *rs_val_val = this->gen_reg_load(fld_rs1_val, 0); + if (fld_rd_val != 0) { + Value *csr_val_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64 / 8); + Value *CSR_csr_val = rs_val_val; + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(64))); + Value *X_rd_val = csr_val_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } else { - Value* CSR_csr_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(64))); + Value *CSR_csr_val = rs_val_val; + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(64))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRS - std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrs(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRS"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val, 0); - if(fld_rd_val != 0){ - Value* X_rd_val = xrd_val; + pc = pc + 4; + + Value *xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64 / 8); + Value *xrs1_val = this->gen_reg_load(fld_rs1_val, 0); + if (fld_rd_val != 0) { + Value *X_rd_val = xrd_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - if(fld_rs1_val != 0){ - Value* CSR_csr_val = this->builder->CreateOr( - xrd_val, - xrs1_val); - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(64))); + if (fld_rs1_val != 0) { + Value *CSR_csr_val = this->builder->CreateOr(xrd_val, xrs1_val); + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(64))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRC - std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrc(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRC"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val, 0); - if(fld_rd_val != 0){ - Value* X_rd_val = xrd_val; + pc = pc + 4; + + Value *xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64 / 8); + Value *xrs1_val = this->gen_reg_load(fld_rs1_val, 0); + if (fld_rd_val != 0) { + Value *X_rd_val = xrd_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - if(fld_rs1_val != 0){ - Value* CSR_csr_val = this->builder->CreateAnd( - xrd_val, - this->builder->CreateNot(xrs1_val)); - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(64))); + if (fld_rs1_val != 0) { + Value *CSR_csr_val = this->builder->CreateAnd(xrd_val, this->builder->CreateNot(xrs1_val)); + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(64))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRWI - std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrwi(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRWI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_zimm_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_zimm_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64/8); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64 / 8); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* CSR_csr_val = this->gen_ext( - this->gen_const(64U, fld_zimm_val), - 64, - false); - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(64))); + Value *CSR_csr_val = this->gen_ext(this->gen_const(64U, fld_zimm_val), 64, false); + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRSI - std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrsi(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRSI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_zimm_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_zimm_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64/8); - if(fld_zimm_val != 0){ - Value* CSR_csr_val = this->builder->CreateOr( - res_val, - this->gen_ext( - this->gen_const(64U, fld_zimm_val), - 64, - false)); - this->gen_write_mem( - traits::CSR, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(64))); + pc = pc + 4; + + Value *res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64 / 8); + if (fld_zimm_val != 0) { + Value *CSR_csr_val = + this->builder->CreateOr(res_val, this->gen_ext(this->gen_const(64U, fld_zimm_val), 64, false)); + this->gen_write_mem(traits::CSR, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(64))); } - if(fld_rd_val != 0){ - Value* X_rd_val = res_val; + if (fld_rd_val != 0) { + Value *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 CSRRCI - std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + std::tuple __csrrci(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { bb->setName("CSRRCI"); - + this->gen_sync(iss::PRE_SYNC); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_zimm_val = 0 | (bit_sub<15,5>(instr)); - uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_zimm_val = 0 | (bit_sub<15, 5>(instr)); + uint16_t fld_csr_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64/8); - if(fld_rd_val != 0){ - Value* X_rd_val = res_val; + pc = pc + 4; + + Value *res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64 / 8); + if (fld_rd_val != 0) { + Value *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - if(fld_zimm_val != 0){ - Value* CSR_csr_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, - fld_csr_val, - this->builder->CreateZExtOrTrunc(CSR_csr_val,this->get_type(64))); + if (fld_zimm_val != 0) { + Value *CSR_csr_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, fld_csr_val, + this->builder->CreateZExtOrTrunc(CSR_csr_val, this->get_type(64))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 LR.D - std::tuple __lr_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - if(fld_rd_val != 0){ - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); + pc = pc + 4; + + if (fld_rd_val != 0) { + Value *offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 64 / 8), 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); - Value* RES_offs_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(RES_offs_val,this->get_type(64))); + Value *RES_offs_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(RES_offs_val, this->get_type(64))); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 SC.D - std::tuple __sc_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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); + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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->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* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 1); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(64)));if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_const(64U, 0); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 1); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(64))); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_const(64U, 0); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } } this->builder->CreateBr(bbnext); this->builder->SetInsertPoint(bb_else); { - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_const(64U, 1); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_const(64U, 1); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } } this->builder->CreateBr(bbnext); - bb=bbnext; + bb = bbnext; this->builder->SetInsertPoint(bb); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOSWAP.D - std::tuple __amoswap_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); - if(fld_rd_val != 0){ - Value* X_rd_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 64/8), - 64, - true); + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 0); + if (fld_rd_val != 0) { + Value *X_rd_val = this->gen_ext(this->gen_read_mem(traits::MEM, offs_val, 64 / 8), 64, true); this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + Value *MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOADD.D - std::tuple __amoadd_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->builder->CreateAdd( - res_val, - this->gen_reg_load(fld_rs2_val, 0)); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + Value *res2_val = this->builder->CreateAdd(res_val, this->gen_reg_load(fld_rs2_val, 0)); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOXOR.D - std::tuple __amoxor_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->builder->CreateXor( - res_val, - this->gen_reg_load(fld_rs2_val, 0)); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + Value *res2_val = this->builder->CreateXor(res_val, this->gen_reg_load(fld_rs2_val, 0)); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOAND.D - std::tuple __amoand_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->builder->CreateAnd( - res_val, - this->gen_reg_load(fld_rs2_val, 0)); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + Value *res2_val = this->builder->CreateAnd(res_val, this->gen_reg_load(fld_rs2_val, 0)); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOOR.D - std::tuple __amoor_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->builder->CreateOr( - res_val, - this->gen_reg_load(fld_rs2_val, 0)); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + Value *res2_val = this->builder->CreateOr(res_val, this->gen_reg_load(fld_rs2_val, 0)); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOMIN.D - std::tuple __amomin_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), 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, 0), - 64, true)), - this->gen_reg_load(fld_rs2_val, 0), - res_val, - 64); - Value* MEM_offs_val = res_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + 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, 0), 64, true)), + this->gen_reg_load(fld_rs2_val, 0), res_val, 64); + Value *MEM_offs_val = res_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOMAX.D - std::tuple __amomax_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), 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, 0), - 64, true)), - this->gen_reg_load(fld_rs2_val, 0), - res_val, - 64); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + 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, 0), 64, true)), + this->gen_reg_load(fld_rs2_val, 0), res_val, 64); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOMINU.D - std::tuple __amominu_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_UGT, - res_val, - this->gen_reg_load(fld_rs2_val, 0)), - this->gen_reg_load(fld_rs2_val, 0), - res_val, - 64); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + Value *res2_val = + this->gen_choose(this->builder->CreateICmp(ICmpInst::ICMP_UGT, res_val, this->gen_reg_load(fld_rs2_val, 0)), + this->gen_reg_load(fld_rs2_val, 0), res_val, 64); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 AMOMAXU.D - std::tuple __amomaxu_d(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + 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); - - uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); - uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); - uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); - uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); - uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); - if(this->disass_enabled){ + + uint8_t fld_rd_val = 0 | (bit_sub<7, 5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15, 5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20, 5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25, 1>(instr)); + uint8_t fld_aq_val = 0 | (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; boost::format fmter("0x%1$016x\t\t%2$-40s\t\t"); fmter % pc.val % ins_fmter.str(); - std::vector args { - this->core_ptr, - this->builder->CreateGlobalStringPtr(fmter.str()) - }; + std::vector args{this->core_ptr, this->builder->CreateGlobalStringPtr(fmter.str())}; this->builder->CreateCall(this->mod->getFunction("print_disass"), args); } - pc=pc+4; - - Value* offs_val = this->gen_reg_load(fld_rs1_val, 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* X_rd_val = res_val; + pc = pc + 4; + + Value *offs_val = this->gen_reg_load(fld_rs1_val, 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 *X_rd_val = res_val; this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); } - Value* res2_val = this->gen_choose( - this->builder->CreateICmp( - ICmpInst::ICMP_ULT, - res_val, - this->gen_reg_load(fld_rs2_val, 0)), - this->gen_reg_load(fld_rs2_val, 0), - res_val, - 64); - Value* MEM_offs_val = res2_val; - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder->CreateZExtOrTrunc(MEM_offs_val,this->get_type(64))); + Value *res2_val = + this->gen_choose(this->builder->CreateICmp(ICmpInst::ICMP_ULT, res_val, this->gen_reg_load(fld_rs2_val, 0)), + this->gen_reg_load(fld_rs2_val, 0), res_val, 64); + Value *MEM_offs_val = res2_val; + this->gen_write_mem(traits::MEM, offs_val, + this->builder->CreateZExtOrTrunc(MEM_offs_val, this->get_type(64))); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + 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 generated code */ + + /* 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); + std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { + // this->gen_sync(iss::PRE_SYNC); + this->builder->CreateStore(this->builder->CreateLoad(get_reg_ptr(traits::NEXT_PC), true), + get_reg_ptr(traits::PC), true); 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)), + this->builder->CreateAdd(this->builder->CreateLoad(get_reg_ptr(traits::ICOUNT), true), + this->gen_const(64U, 1)), get_reg_ptr(traits::ICOUNT), true); - if(this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC); - pc=pc+((instr&3) == 3?4:2); - this->gen_raise_trap(0, 2); // illegal instruction trap + if (this->debugging_enabled()) this->gen_sync(iss::PRE_SYNC); + pc = pc + ((instr & 3) == 3 ? 4 : 2); + this->gen_raise_trap(0, 2); // illegal instruction trap this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ 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 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() { this(new ARCH()); } -template -vm_impl::vm_impl(ARCH& core, bool dump) : vm::vm_base(core, dump) { +template vm_impl::vm_impl(ARCH &core, bool dump) : vm::vm_base(core, dump) { 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); + 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); } - this->sync_exec=static_cast(this->sync_exec|core.needed_sync()); + this->sync_exec = static_cast(this->sync_exec | core.needed_sync()); } -template -std::tuple vm_impl::gen_single_inst_behavior(virt_addr_t& pc, unsigned int& inst_cnt, llvm::BasicBlock* this_block){ +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; iss::addr_t paddr; const typename traits::addr_t upper_bits = ~traits::PGMASK; 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 + 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); + 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 { + } else { auto res = this->core.read(paddr, 4, data); - if(res!=iss::Ok) - throw trap_access(1, pc.val); + if (res != iss::Ok) throw trap_access(1, pc.val); } - } catch(trap_access& ta){ + } catch (trap_access &ta) { throw trap_access(ta.id, pc.val); } - if(insn==0x0000006f) - throw simulation_stopped(0); + if (insn == 0x0000006f) throw simulation_stopped(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; + 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){ +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 ); +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)), +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); + 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)), +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){ +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)) - }; + 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); + 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); +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 -#define CREATE_FUNCS(ARCH) \ -template<> std::unique_ptr create(ARCH* core, unsigned short port, bool dump) {\ - std::unique_ptr > ret = std::make_unique >(*core, dump);\ - debugger::server::run_server(ret.get(), port);\ - return ret;\ -}\ -template<> std::unique_ptr create(std::string inst_name, unsigned short port, bool dump) {\ - return create(new arch::riscv_hart_msu_vp(), port, dump); /* FIXME: memory leak!!!!!!! */\ -}\ -template<> std::unique_ptr create(ARCH* core, bool dump) {\ - return std::make_unique >(*core, dump); /* FIXME: memory leak!!!!!!! */ \ -}\ -template<> std::unique_ptr create(std::string inst_name, bool dump) { \ - return create(new arch::riscv_hart_msu_vp(), dump);\ -} +#define CREATE_FUNCS(ARCH) \ + template <> std::unique_ptr create(ARCH * core, unsigned short port, bool dump) { \ + std::unique_ptr> ret = std::make_unique>(*core, dump); \ + debugger::server::run_server(ret.get(), port); \ + return ret; \ + } \ + template <> std::unique_ptr create(std::string inst_name, unsigned short port, bool dump) { \ + return create(new arch::riscv_hart_msu_vp(), port, dump); /* FIXME: memory leak!!!!!!! */ \ + } \ + template <> std::unique_ptr create(ARCH * core, bool dump) { \ + return std::make_unique>(*core, dump); /* FIXME: memory leak!!!!!!! */ \ + } \ + template <> std::unique_ptr create(std::string inst_name, bool dump) { \ + return create(new arch::riscv_hart_msu_vp(), dump); \ + } CREATE_FUNCS(arch::rv64ia) namespace rv64ia { - template - status target_adapter::set_gen_thread(rp_thread_ref& thread) { - thread_idx=thread; +template status target_adapter::set_gen_thread(rp_thread_ref &thread) { + thread_idx = thread; + return Ok; +} + +template status target_adapter::set_ctrl_thread(rp_thread_ref &thread) { + thread_idx = thread; + return Ok; +} + +template status target_adapter::is_thread_alive(rp_thread_ref &thread, bool &alive) { + alive = 1; + return Ok; +} + +/* List threads. If first is non-zero then start from the first thread, + * otherwise start from arg, result points to array of threads to be + * filled out, result size is number of elements in the result, + * num points to the actual number of threads found, done is + * set if all threads are processed. + */ +template +status target_adapter::thread_list_query(int first, const rp_thread_ref &arg, std::vector &result, + size_t max_num, size_t &num, bool &done) { + if (first == 0) { + result.clear(); + result.push_back(thread_idx); + num = 1; + done = true; return Ok; - } + } else + return NotSupported; +} - template - status target_adapter::set_ctrl_thread(rp_thread_ref& thread) { - thread_idx=thread; - return Ok; - } +template status target_adapter::current_thread_query(rp_thread_ref &thread) { + thread = thread_idx; + return Ok; +} - template - status target_adapter::is_thread_alive(rp_thread_ref& thread, bool& alive) { - alive=1; - return Ok; +template +status target_adapter::read_registers(std::vector &data, std::vector &avail) { + LOG(TRACE) << "reading target registers"; + // return idx<0?:; + data.clear(); + avail.clear(); + std::vector reg_data; + for (size_t reg_no = 0; reg_no < arch::traits::NUM_REGS; ++reg_no) { + auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); + auto reg_width = reg_bit_width / 8; + reg_data.resize(reg_width); + vm->get_arch()->get_reg(reg_no, reg_data); + for (size_t j = 0; j < reg_data.size(); ++j) { + data.push_back(reg_data[j]); + avail.push_back(0xff); + } } - - /* List threads. If first is non-zero then start from the first thread, - * otherwise start from arg, result points to array of threads to be - * filled out, result size is number of elements in the result, - * num points to the actual number of threads found, done is - * set if all threads are processed. - */ - template - status target_adapter::thread_list_query(int first, const rp_thread_ref& arg, std::vector& result, size_t max_num, - size_t& num, bool& done) { - if(first==0){ - result.clear(); - result.push_back(thread_idx); - num=1; - done=true; - return Ok; - } else - return NotSupported; - } - - template - status target_adapter::current_thread_query(rp_thread_ref& thread) { - thread=thread_idx; - return Ok; - } - - template - status target_adapter::read_registers(std::vector& data, std::vector& avail) { - LOG(TRACE)<<"reading target registers"; - //return idx<0?:; - data.clear(); - avail.clear(); - std::vector reg_data; - for(size_t reg_no = 0; reg_no < arch::traits::NUM_REGS; ++reg_no){ - auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); - auto reg_width=reg_bit_width/8; - reg_data.resize(reg_width); - vm->get_arch()->get_reg(reg_no, reg_data); - for(size_t j=0; j::NUM_REGS < 65) { + auto reg_width = sizeof(typename arch::traits::reg_t); + for (size_t reg_no = 0; reg_no < 33; ++reg_no) { + for (size_t j = 0; j < reg_width; ++j) { + data.push_back(0x0); + avail.push_back(0x00); } } - // work around fill with F type registers - if(arch::traits::NUM_REGS < 65){ - auto reg_width=sizeof(typename arch::traits::reg_t); - for(size_t reg_no = 0; reg_no < 33; ++reg_no){ - for(size_t j=0; j - status target_adapter::write_registers(const std::vector& data) { - size_t data_index=0; - auto reg_count=arch::traits::NUM_REGS; - std::vector reg_data; - for(size_t reg_no = 0; reg_no < reg_count; ++reg_no){ - auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); - auto reg_width=reg_bit_width/8; - vm->get_arch()->set_reg(reg_no, std::vector(data.begin()+data_index, data.begin()+data_index+reg_width)); - data_index+=reg_width; - } - return Ok; +template status target_adapter::write_registers(const std::vector &data) { + size_t data_index = 0; + auto reg_count = arch::traits::NUM_REGS; + std::vector reg_data; + for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) { + auto reg_bit_width = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no)); + auto reg_width = reg_bit_width / 8; + vm->get_arch()->set_reg(reg_no, + std::vector(data.begin() + data_index, data.begin() + data_index + reg_width)); + data_index += reg_width; } + return Ok; +} - template - status target_adapter::read_single_register(unsigned int reg_no, std::vector& data, std::vector& avail) { - if(reg_no<65){ - //auto reg_size = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no))/8; - data.resize(0); - vm->get_arch()->get_reg(reg_no, data); - avail.resize(data.size()); - std::fill(avail.begin(), avail.end(), 0xff); - } else { - typed_addr_t a(iss::DEBUG_READ, traits::CSR, reg_no-65); - data.resize(sizeof(typename traits::reg_t)); - avail.resize(sizeof(typename traits::reg_t)); - std::fill(avail.begin(), avail.end(), 0xff); - vm->get_arch()->read(a, data.size(), data.data()); - } - return data.size()>0?Ok:Err; +template +status target_adapter::read_single_register(unsigned int reg_no, std::vector &data, + std::vector &avail) { + if (reg_no < 65) { + // auto reg_size = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no))/8; + data.resize(0); + vm->get_arch()->get_reg(reg_no, data); + avail.resize(data.size()); + std::fill(avail.begin(), avail.end(), 0xff); + } else { + typed_addr_t a(iss::DEBUG_READ, traits::CSR, reg_no - 65); + data.resize(sizeof(typename traits::reg_t)); + avail.resize(sizeof(typename traits::reg_t)); + std::fill(avail.begin(), avail.end(), 0xff); + vm->get_arch()->read(a, data.size(), data.data()); } + return data.size() > 0 ? Ok : Err; +} - template - status target_adapter::write_single_register(unsigned int reg_no, const std::vector& data) { - if(reg_no<65) - vm->get_arch()->set_reg(reg_no, data); - else { - typed_addr_t a(iss::DEBUG_WRITE, traits::CSR, reg_no-65); - vm->get_arch()->write(a, data.size(), data.data()); - } - return Ok; - } - - template - status target_adapter::read_mem(uint64_t addr, std::vector& data) { - auto a=map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); - auto f = [&]()->status { - return vm->get_arch()->read(a, data.size(), data.data()); - }; - return srv->execute_syncronized(f); - - } - - template - status target_adapter::write_mem(uint64_t addr, const std::vector& data) { - auto a=map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); - return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data()); - } - - template - status target_adapter::process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) { - return NotSupported; - } - - template - status target_adapter::offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) { - text=0; - data=0; - bss=0; - return Ok; - } - - template - status target_adapter::crc_query(uint64_t addr, size_t len, uint32_t& val) { - return NotSupported; - } - - template - status target_adapter::raw_query(std::string in_buf, std::string& out_buf) { - return NotSupported; - } - - template - status target_adapter::threadinfo_query(int first, std::string& out_buf) { - if(first){ - std::stringstream ss; - ss<<"m"< - status target_adapter::threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) { - char buf[20]; - memset(buf, 0, 20); - sprintf (buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); - out_buf=buf; - return Ok; - } - - template - status target_adapter::packetsize_query(std::string& out_buf) { - out_buf="PacketSize=1000"; - return Ok; - } - - template - status target_adapter::add_break(int type, uint64_t addr, unsigned int length) { - auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr}); - auto eaddr=map_addr({iss::CODE, iss::PHYSICAL, addr+length}); - target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val-saddr.val); - LOG(TRACE)<<"Adding breakpoint with handle "< - status target_adapter::remove_break(int type, uint64_t addr, unsigned int length) { - auto saddr=map_addr({iss::CODE, iss::PHYSICAL, addr}); - unsigned handle=target_adapter_base::bp_lut.getEntry(saddr.val); - // TODO: check length of addr range - if(handle){ - LOG(TRACE)<<"Removing breakpoint with handle "< - status target_adapter::resume_from_addr(bool step, int sig, uint64_t addr) { - unsigned reg_no = arch::traits::PC; - std::vector data(8); - *(reinterpret_cast(&data[0]))=addr; +template +status target_adapter::write_single_register(unsigned int reg_no, const std::vector &data) { + if (reg_no < 65) vm->get_arch()->set_reg(reg_no, data); - return resume_from_current(step, sig); + else { + typed_addr_t a(iss::DEBUG_WRITE, traits::CSR, reg_no - 65); + vm->get_arch()->write(a, data.size(), data.data()); } + return Ok; +} + +template status target_adapter::read_mem(uint64_t addr, std::vector &data) { + auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); + auto f = [&]() -> status { return vm->get_arch()->read(a, data.size(), data.data()); }; + return srv->execute_syncronized(f); +} + +template status target_adapter::write_mem(uint64_t addr, const std::vector &data) { + auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); + return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data()); +} + +template +status target_adapter::process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) { + return NotSupported; +} + +template status target_adapter::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) { + text = 0; + data = 0; + bss = 0; + return Ok; +} + +template status target_adapter::crc_query(uint64_t addr, size_t len, uint32_t &val) { + return NotSupported; +} + +template status target_adapter::raw_query(std::string in_buf, std::string &out_buf) { + return NotSupported; +} + +template status 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(); + } else { + out_buf = "l"; + } + return Ok; +} + +template +status target_adapter::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) { + char buf[20]; + memset(buf, 0, 20); + sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); + out_buf = buf; + return Ok; +} + +template status target_adapter::packetsize_query(std::string &out_buf) { + out_buf = "PacketSize=1000"; + return Ok; +} + +template status target_adapter::add_break(int type, uint64_t addr, unsigned int length) { + auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); + auto eaddr = map_addr({iss::CODE, iss::PHYSICAL, addr + length}); + target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); + LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex + << saddr.val << std::dec; + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Ok; +} + +template status target_adapter::remove_break(int type, uint64_t addr, unsigned int length) { + auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); + unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); + // TODO: check length of addr range + if (handle) { + LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val + << std::dec; + target_adapter_base::bp_lut.removeEntry(handle); + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Ok; + } + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Err; +} + +template status target_adapter::resume_from_addr(bool step, int sig, uint64_t addr) { + unsigned reg_no = arch::traits::PC; + std::vector data(8); + *(reinterpret_cast(&data[0])) = addr; + vm->get_arch()->set_reg(reg_no, data); + return resume_from_current(step, sig); +} } // namespace rv64ia } // namespace iss diff --git a/riscv/src/iss/rv32imac.cpp b/riscv/src/iss/rv32imac.cpp index 8b2e118..667450c 100644 --- a/riscv/src/iss/rv32imac.cpp +++ b/riscv/src/iss/rv32imac.cpp @@ -1,21 +1,21 @@ //////////////////////////////////////////////////////////////////////////////// // 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 @@ -27,7 +27,7 @@ // 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 Aug 29 16:45:20 CEST 2017 // * rv32imac.cpp Author: // @@ -46,31 +46,27 @@ extern "C" { #ifdef __cplusplus } #endif -#include #include #include +#include using namespace iss::arch; -rv32imac::rv32imac() { - reg.icount=0; -} +rv32imac::rv32imac() { reg.icount = 0; } -rv32imac::~rv32imac(){ -} +rv32imac::~rv32imac() {} void rv32imac::reset(uint64_t address) { - for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits::reg_t),0)); - reg.PC=address; - reg.NEXT_PC=reg.PC; - reg.trap_state=0; - reg.machine_state=0x3; + for (size_t i = 0; i < traits::NUM_REGS; ++i) + set_reg(i, std::vector(sizeof(traits::reg_t), 0)); + reg.PC = address; + reg.NEXT_PC = reg.PC; + reg.trap_state = 0; + reg.machine_state = 0x3; } -uint8_t* rv32imac::get_regs_base_ptr(){ - return reinterpret_cast(®); -} +uint8_t *rv32imac::get_regs_base_ptr() { return reinterpret_cast(®); } -rv32imac::phys_addr_t rv32imac::v2p(const iss::addr_t& pc) { - return phys_addr_t(pc); //change logical address to physical address +rv32imac::phys_addr_t rv32imac::v2p(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 index 79f11ee..9b80eb2 100644 --- a/riscv/src/iss/rv64ia.cpp +++ b/riscv/src/iss/rv64ia.cpp @@ -1,21 +1,21 @@ //////////////////////////////////////////////////////////////////////////////// // 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 @@ -27,7 +27,7 @@ // 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: // @@ -46,31 +46,27 @@ extern "C" { #ifdef __cplusplus } #endif -#include #include #include +#include using namespace iss::arch; -rv64ia::rv64ia() { - reg.icount=0; -} +rv64ia::rv64ia() { reg.icount = 0; } -rv64ia::~rv64ia(){ -} +rv64ia::~rv64ia() {} void rv64ia::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; + 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 = 0x0; } -uint8_t* rv64ia::get_regs_base_ptr(){ - return reinterpret_cast(®); -} +uint8_t *rv64ia::get_regs_base_ptr() { return reinterpret_cast(®); } -rv64ia::phys_addr_t rv64ia::v2p(const iss::addr_t& pc) { - return phys_addr_t(pc); //change logical address to physical address +rv64ia::phys_addr_t rv64ia::v2p(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 7504947..5b687bd 100644 --- a/riscv/src/main.cpp +++ b/riscv/src/main.cpp @@ -1,21 +1,21 @@ //////////////////////////////////////////////////////////////////////////////// // 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 @@ -27,37 +27,36 @@ // 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 +#include -namespace po= boost::program_options; +namespace po = boost::program_options; int main(int argc, char *argv[]) { - try{ + try { /* * Define and parse the program options */ po::variables_map vm; - if(parse_cli_options(vm, argc, argv)) return ERROR_IN_COMMAND_LINE; - if(vm.count("verbose")){ + if (parse_cli_options(vm, argc, argv)) return ERROR_IN_COMMAND_LINE; + if (vm.count("verbose")) { auto l = logging::as_log_level(vm["verbose"].as()); LOGGER(DEFAULT)::reporting_level() = l; - LOGGER(connection)::reporting_level()=l; + LOGGER(connection)::reporting_level() = l; } - if(vm.count("log-file")){ + if (vm.count("log-file")) { // configure the connection logger auto f = fopen(vm["log-file"].as().c_str(), "w"); LOG_OUTPUT(DEFAULT)::stream() = f; @@ -66,48 +65,47 @@ int main(int argc, char *argv[]) { // application code comes here // iss::init_jit(argc, argv); - bool dump=vm.count("dump-ir"); + bool dump = vm.count("dump-ir"); // instantiate the simulator std::unique_ptr cpu = nullptr; - if(vm.count("rv64")==1){ - if(vm.count("gdb-port")==1) + if (vm.count("rv64") == 1) { + if (vm.count("gdb-port") == 1) cpu = iss::create("rv64ia", vm["gdb-port"].as(), dump); else cpu = iss::create("rv64ia", dump); } else { - if(vm.count("gdb-port")==1) + if (vm.count("gdb-port") == 1) cpu = iss::create("rv32ima", vm["gdb-port"].as(), dump); else cpu = iss::create("rv32ima", dump); } - if(vm.count("elf")){ - for(std::string input: vm["elf"].as >()) - cpu->get_arch()->load_file(input); - } else if(vm.count("mem")){ - cpu->get_arch()->load_file(vm["mem"].as() , iss::arch::traits::MEM); + if (vm.count("elf")) { + for (std::string input : vm["elf"].as>()) cpu->get_arch()->load_file(input); + } else if (vm.count("mem")) { + cpu->get_arch()->load_file(vm["mem"].as(), iss::arch::traits::MEM); } - if(vm.count("disass")){ + if (vm.count("disass")) { cpu->setDisassEnabled(true); - LOGGER(disass)::reporting_level()=logging::INFO; - auto file_name=vm["disass"].as(); + LOGGER(disass)::reporting_level() = logging::INFO; + auto file_name = vm["disass"].as(); if (file_name.length() > 0) { LOG_OUTPUT(disass)::stream() = fopen(file_name.c_str(), "w"); LOGGER(disass)::print_time() = false; LOGGER(disass)::print_severity() = false; } } - if(vm.count("reset")){ + if (vm.count("reset")) { auto str = vm["reset"].as(); - auto start_address = str.find("0x")==0? std::stoull(str, 0, 16):std::stoull(str, 0, 10); + auto start_address = str.find("0x") == 0 ? std::stoull(str, 0, 16) : std::stoull(str, 0, 10); cpu->reset(start_address); } else { cpu->reset(); } return cpu->start(vm["cycles"].as()); - } catch(std::exception& e){ - LOG(ERROR) << "Unhandled Exception reached the top of main: " - << e.what() << ", application will now exit" << std::endl; + } catch (std::exception &e) { + LOG(ERROR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" + << std::endl; return ERROR_UNHANDLED_EXCEPTION; } } diff --git a/sc-components b/sc-components index 46d7950..a5c9101 160000 --- a/sc-components +++ b/sc-components @@ -1 +1 @@ -Subproject commit 46d79504a8a5a6a9541b19a6774fb8161350a0a4 +Subproject commit a5c9101b71da3824af4a54322232de270c5547de