diff --git a/dbt-core b/dbt-core index 1091afc..f23a45a 160000 --- a/dbt-core +++ b/dbt-core @@ -1 +1 @@ -Subproject commit 1091afcc3045c1bea5508a6be785eed757632452 +Subproject commit f23a45ab77d25ac42fd8df3e3f7206baad122c67 diff --git a/riscv.sc/CMakeLists.txt b/riscv.sc/CMakeLists.txt index 1e7d2f3..48a32c4 100644 --- a/riscv.sc/CMakeLists.txt +++ b/riscv.sc/CMakeLists.txt @@ -66,9 +66,9 @@ add_dependent_header(util) include_directories( ${PROJECT_SOURCE_DIR}/incl + ${PROJECT_SOURCE_DIR}/../riscv/incl ${PROJECT_SOURCE_DIR}/../external/elfio ${PROJECT_SOURCE_DIR}/../external/libGIS - ${PROJECT_SOURCE_DIR}/../riscv ${Boost_INCLUDE_DIRS} ) diff --git a/riscv.sc/incl/cli_options.h b/riscv.sc/incl/cli_options.h index 9e02585..413d572 100644 --- a/riscv.sc/incl/cli_options.h +++ b/riscv.sc/incl/cli_options.h @@ -86,7 +86,7 @@ inline void configure_default_logger(boost::program_options::variables_map& vm){ inline void configure_debugger_logger() { // configure the connection logger -// el::Logger* gdbServerLogger = el::Loggers::getLogger("connection"); +// el::Logger* gdbServerLogger = el::Loggers::getLogger(connection); // el::Configurations gdbServerConf; // gdbServerConf.setToDefault(); // gdbServerConf.set(el::Level::Error, el::ConfigurationType::Format, @@ -104,10 +104,10 @@ inline void configure_debugger_logger() { } inline void configure_disass_logger(boost::program_options::variables_map& vm) { -// el::Logger* disassLogger = el::Loggers::getLogger("disass"); +// el::Logger* disassLogger = el::Loggers::getLogger(disass); // el::Configurations disassConf; -// if(vm.count("disass")){ -// auto file_name=vm["disass"].as(); +// 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, diff --git a/riscv.sc/incl/iss/arch/riscv_hart_msu_vp.h b/riscv.sc/incl/iss/arch/riscv_hart_msu_vp.h deleted file mode 100644 index b2c5d2f..0000000 --- a/riscv.sc/incl/iss/arch/riscv_hart_msu_vp.h +++ /dev/null @@ -1,1249 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Contributors: - * eyck@minres.com - initial API and implementation - ******************************************************************************/ - -#ifndef _RISCV_CORE_H_ -#define _RISCV_CORE_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace iss { -namespace arch { - -enum { - tohost_dflt = 0xF0001000, - fromhost_dflt = 0xF0001040 -}; - -enum csr_name { - /* user-level CSR */ - // User Trap Setup - ustatus=0x000, - uie=0x004, - utvec=0x005, - // User Trap Handling - uscratch=0x040, - uepc=0x041, - ucause=0x042, - utval=0x043, - uip=0x044, - // User Floating-Point CSRs - fflags=0x001, - frm=0x002, - fcsr=0x003, - // User Counter/Timers - cycle=0xC00, - time=0xC01, - instret=0xC02, - hpmcounter3=0xC03, - hpmcounter4=0xC04, - /*...*/ - hpmcounter31=0xC1F, - cycleh=0xC80, - timeh=0xC81, - instreth=0xC82, - hpmcounter3h=0xC83, - hpmcounter4h=0xC84, - /*...*/ - hpmcounter31h=0xC9F, - /* supervisor-level CSR */ - // Supervisor Trap Setup - 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, - // Supervisor Protection and Translation - satp=0x180, - /* machine-level CSR */ - // Machine Information Registers - 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, - // Machine Trap Handling - 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, - /*...*/ - pmpaddr15=0x3BF, - // Machine Counter/Timers - mcycle=0xB00, - minstret=0xB02, - mhpmcounter3=0xB03, - mhpmcounter4=0xB04, - /*...*/ - mhpmcounter31=0xB1F, - mcycleh=0xB80, - minstreth=0xB82, - mhpmcounter3h=0xB83, - mhpmcounter4h=0xB84, - /*...*/ - mhpmcounter31h=0xB9F, - // Machine Counter Setup - mhpmevent3=0x323, - mhpmevent4=0x324, - /*...*/ - mhpmevent31=0x33F, - // Debug/Trace Registers (shared with Debug Mode) - tselect=0x7A0, - tdata1=0x7A1, - tdata2=0x7A2, - tdata3=0x7A3, - // Debug Mode Registers - dcsr=0x7B0, - dpc=0x7B1, - dscratch=0x7B2 -}; - -namespace { - -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" -}; - -enum { - 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_SOFT = 0x300 // Reserved for Software -}; - -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 { - 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; - int idxbits; - int ptesize; - uint64_t ptbase; -}; - - -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 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_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 - } 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; - } 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; - } 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 - } 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; - } 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; - } u; -} mstatus64_t; - -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){ - if (state == PRIV_M) { - return {0, 0, 0, 0}; - } else if (state <= PRIV_S) { - 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(); - } - } else { - abort(); - } - return {0, 0, 0, 0}; // dummy -} - -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) { - switch (bit_sub<60, 4>(sptbr)) { - case 0: // off - return {0, 0, 0, 0}; - case 8: // SV39 - return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; - case 9: // SV48 - return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; - case 10: // SV57 - 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(); - } - } else { - abort(); - } - return {0, 0, 0, 0}; // dummy -} - - -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 - case PRIV_S: - return mask&0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011 - default: - 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){ - case PRIV_U: - 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 - default: - 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 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 { - 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 addr_t = typename super::addr_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; - - constexpr reg_t get_irq_mask(size_t mode){ - const reg_t m[4] = { - 0b000100010001, //U mode - 0b001100110011, // S-mode - 0, - 0b101110111011 // M-mode - }; - return m[mode]; - } - - riscv_hart_msu_vp(); - virtual ~riscv_hart_msu_vp(); - - virtual void load_file(std::string name, int type=-1); - - 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 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(){ - std::stringstream s; - s<<"[p:"<reg.machine_state]<<";s:0x"<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_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 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; - std::stringstream uart_buf; - std::unordered_map ptw; - std::unordered_map atomic_reservation; - std::unordered_map csr_rd_cb; - 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 write_status(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 write_ip(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); - 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; - // 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; -} - -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){ - 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){ - fclose(fp); - //Create elfio reader - ELFIO::elfio reader; - // Load ELF data - 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)); - } - } - for (const auto sec :reader.sections ) { - if(sec->get_name() == ".tohost"){ - tohost=sec->get_address(); - fromhost=tohost+0x40; - } - } - return; - } - } -} - -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(logging::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 - return iss::Err; - } - try { - 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; - 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); - 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); - } - 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; - 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 - 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; - return iss::Err; - } - return iss::Ok; - } - } - } - break; - case traits::RES:{ - auto it = atomic_reservation.find(addr.val); - if(it!= atomic_reservation.end() && (*it).second != 0){ - memset(data, 0xff, length); - atomic_reservation.erase(addr.val); - } else - memset(data, 0, length); - } - break; - default: - 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){ -#ifndef NDEBUG - const char* prefix = addr.type & iss::DEBUG?"debug ":""; - switch(length){ - case 8: - LOG(logging::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){ - 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 '"<::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:{ - 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; - return iss::Err; - } - return iss::Ok; - } - } - } - break; - case traits::RES:{ - atomic_reservation[addr.val] = data[0]; - } - break; - default: - return iss::Err; - } - return iss::Ok; - } 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; - auto it = csr_rd_cb.find(addr); - 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); - 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; - auto it = csr_wr_cb.find(addr); - 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); - return (this->*f)(addr, val); - -} - -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); - } - 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())); - 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); - 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); - 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); - 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); - 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); - 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){ - 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; - return iss::Err; - } - val = csr[satp]; - return iss::Ok; -} - -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; - 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); - 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)); - // 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){ - case 0: - if(hostvar!=0x1) - LOG(logging::FATAL)<<"tohost value is 0x"<(hostvar & 0xff); - if(c=='\n' || c==0){ - LOG(logging::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; - } - } - return iss::Ok; -} - -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; - - 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; - - 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; - } - if (enabled_interrupts!=0){ - int res = 0; - 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); - - 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 vm_info vm = decode_vm_info::XLEN>(mode, satp_r); - - 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); - - auto it = ptw.find(addr.val >> PGSHIFT); - 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)}; -#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)}; - 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; - - reg_t base = vm.ptbase; - for (int i = levels - 1; i >= 0; i--) { - const int ptshift = i * vm.idxbits; - const reg_t idx = (addr.val >> (PGSHIFT + ptshift)) & ((1 << vm.idxbits) - 1); - - // 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 reg_t ppn = pte >> PTE_PPN_SHIFT; - - if (PTE_TABLE(pte)) { // next level of page table - base = ppn << PGSHIFT; - } else if ((pte & PTE_U) ? s_mode && (type == iss::FETCH || !sum) : !s_mode) { - 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))) { - break; - } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { - break; - } else { - 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; -#else - // take exception if access or possibly dirty bit is not set. - 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); - return {addr.getAccessType(), addr.space, value | offset}; - } - } - } - switch (type) { - case FETCH: - this->fault_data=addr.val; - throw trap_instruction_page_fault(addr.val); - case READ: - this->fault_data=addr.val; - throw trap_load_page_fault(addr.val); - case WRITE: - this->fault_data=addr.val; - throw trap_store_page_fault(addr.val); - default: abort(); - } -} - -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 - // 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; - // store ret addr in xepc register - 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. - */ - 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; - // 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 - // is cleared - auto status=csr[mstatus]; - auto xie = (status>>cur_priv) & 1; - // store the actual privilege level in yPP - switch(new_priv){ - case PRIV_M: - status&=~(3<<11); - status|=(cur_priv&0x3)<<11; - break; - case PRIV_S: - 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; - // reset trap state - this->reg.machine_state=new_priv; - this->reg.trap_state=0; - char buffer[32]; - sprintf(buffer, "0x%016lx", addr); - CLOG(logging::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 - - 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){ - case PRIV_M: - 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 - break; - case PRIV_U: - 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(logging::INFO, "disass")<<"Executing xRET , changing privilege level from "<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; - } -} -} -} - -#endif /* _RISCV_CORE_H_ */ diff --git a/riscv.sc/incl/iss/arch/rv32imac.h b/riscv.sc/incl/iss/arch/rv32imac.h deleted file mode 100644 index 9800349..0000000 --- a/riscv.sc/incl/iss/arch/rv32imac.h +++ /dev/null @@ -1,200 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017, MINRES Technologies GmbH -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Created on: Thu Sep 21 17:01:54 CEST 2017 -// * rv32imac.h Author: -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef _RV32IMAC_H_ -#define _RV32IMAC_H_ - -#include -#include -#include - -namespace iss { -namespace arch { - -struct rv32imac; - -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 reg_e { - X0, - X1, - X2, - X3, - X4, - X5, - X6, - X7, - X8, - X9, - X10, - X11, - X12, - X13, - X14, - X15, - X16, - X17, - X18, - X19, - X20, - X21, - X22, - X23, - X24, - X25, - X26, - X27, - X28, - X29, - X30, - X31, - PC, - NUM_REGS, - NEXT_PC=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - ICOUNT - }; - - typedef uint32_t reg_t; - - typedef uint32_t addr_t; - - typedef uint32_t code_word_t; //TODO: check removal - - 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}; - 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}; - return RV32IMAC_reg_byte_offset[r]; - } - - enum sreg_flag_e {FLAGS}; - - enum mem_type_e {MEM,CSR,FENCE,RES}; - -}; - -struct rv32imac: public arch_if { - - using virt_addr_t = typename traits::virt_addr_t; - using phys_addr_t = typename traits::phys_addr_t; - using reg_t = typename traits::reg_t; - using addr_t = typename traits::addr_t; - - rv32imac(); - ~rv32imac(); - - virtual void reset(uint64_t address=0) 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 {} - /// deprecated - 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 notify_phase(exec_phase phase){ - if(phase==ISTART){ - ++reg.icount; - reg.PC=reg.NEXT_PC; - reg.trap_state=reg.pending_trap; - } - } - - uint64_t get_icount() { return reg.icount;} - - virtual phys_addr_t v2p(const iss::addr_t& pc); - - virtual iss::sync_type needed_sync() const { return iss::PRE_SYNC; } - -protected: - struct RV32IMAC_regs { - uint32_t X0; - uint32_t X1; - uint32_t X2; - uint32_t X3; - uint32_t X4; - uint32_t X5; - uint32_t X6; - uint32_t X7; - uint32_t X8; - uint32_t X9; - uint32_t X10; - uint32_t X11; - uint32_t X12; - uint32_t X13; - uint32_t X14; - uint32_t X15; - uint32_t X16; - uint32_t X17; - uint32_t X18; - uint32_t X19; - uint32_t X20; - uint32_t X21; - uint32_t X22; - uint32_t X23; - uint32_t X24; - uint32_t X25; - uint32_t X26; - uint32_t X27; - uint32_t X28; - uint32_t X29; - uint32_t X30; - uint32_t X31; - uint32_t PC; - uint32_t NEXT_PC; - uint32_t trap_state, pending_trap, machine_state; - uint64_t icount; - } reg; -}; - -} -} -#endif /* _RV32IMAC_H_ */ diff --git a/riscv.sc/incl/iss/arch/rv64ia.h b/riscv.sc/incl/iss/arch/rv64ia.h deleted file mode 100644 index c45cfe2..0000000 --- a/riscv.sc/incl/iss/arch/rv64ia.h +++ /dev/null @@ -1,200 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017, MINRES Technologies GmbH -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Created on: Thu Sep 21 17:01:54 CEST 2017 -// * rv64ia.h Author: -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef _RV64IA_H_ -#define _RV64IA_H_ - -#include -#include -#include - -namespace iss { -namespace arch { - -struct rv64ia; - -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 reg_e { - X0, - X1, - X2, - X3, - X4, - X5, - X6, - X7, - X8, - X9, - X10, - X11, - X12, - X13, - X14, - X15, - X16, - X17, - X18, - X19, - X20, - X21, - X22, - X23, - X24, - X25, - X26, - X27, - X28, - X29, - X30, - X31, - PC, - NUM_REGS, - NEXT_PC=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - ICOUNT - }; - - typedef uint64_t reg_t; - - typedef uint64_t addr_t; - - typedef uint64_t code_word_t; //TODO: check removal - - 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}; - 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}; - return RV64IA_reg_byte_offset[r]; - } - - enum sreg_flag_e {FLAGS}; - - enum mem_type_e {MEM,CSR,FENCE,RES}; - -}; - -struct rv64ia: public arch_if { - - using virt_addr_t = typename traits::virt_addr_t; - using phys_addr_t = typename traits::phys_addr_t; - using reg_t = typename traits::reg_t; - using addr_t = typename traits::addr_t; - - rv64ia(); - ~rv64ia(); - - virtual void reset(uint64_t address=0) 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 {} - /// deprecated - 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 notify_phase(exec_phase phase){ - if(phase==ISTART){ - ++reg.icount; - reg.PC=reg.NEXT_PC; - reg.trap_state=reg.pending_trap; - } - } - - uint64_t get_icount() { return reg.icount;} - - virtual phys_addr_t v2p(const iss::addr_t& pc); - - virtual iss::sync_type needed_sync() const { return iss::PRE_SYNC; } - -protected: - struct RV64IA_regs { - uint64_t X0; - uint64_t X1; - uint64_t X2; - uint64_t X3; - uint64_t X4; - uint64_t X5; - uint64_t X6; - uint64_t X7; - uint64_t X8; - uint64_t X9; - uint64_t X10; - uint64_t X11; - uint64_t X12; - uint64_t X13; - uint64_t X14; - uint64_t X15; - uint64_t X16; - uint64_t X17; - uint64_t X18; - uint64_t X19; - uint64_t X20; - uint64_t X21; - uint64_t X22; - uint64_t X23; - uint64_t X24; - uint64_t X25; - uint64_t X26; - uint64_t X27; - uint64_t X28; - uint64_t X29; - uint64_t X30; - uint64_t X31; - uint64_t PC; - uint64_t NEXT_PC; - uint32_t trap_state, pending_trap, machine_state; - uint64_t icount; - } reg; -}; - -} -} -#endif /* _RV64IA_H_ */ diff --git a/riscv.sc/src/internal/vm_riscv.in.cpp b/riscv.sc/src/internal/vm_riscv.in.cpp deleted file mode 100644 index b5c7b7c..0000000 --- a/riscv.sc/src/internal/vm_riscv.in.cpp +++ /dev/null @@ -1,695 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017, MINRES Technologies GmbH -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Contributors: -// eyck@minres.com - initial API and implementation -// -// -//////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "iss/vm_base.h" -#include "iss/arch/CORE_DEF_NAME.h" -#include "iss/debugger/server.h" - -#include -#include "iss/arch/riscv_hart_msu_vp.h" - -namespace iss { -namespace CORE_DEF_NAME { -using namespace iss::arch; -using namespace llvm; -using namespace iss::debugger; - -template -struct vm_impl; - -template -struct target_adapter: public target_adapter_base { - - 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; - - /* Set control thread */ - status set_ctrl_thread(rp_thread_ref& thread) override; - - /* Get thread status */ - status is_thread_alive(rp_thread_ref& thread, bool& alive) override; - - /*============= Register Access ================================*/ - - /* Read all registers. 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_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; - - /* 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; - - /* 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; - - /*=================== 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; - - /* 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 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 current_thread_query(rp_thread_ref& thread) 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 raw_query(std::string in_buf, 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 packetsize_query(std::string& out_buf) override; - - status add_break(int type, uint64_t addr, unsigned int length) override; - - status remove_break(int type, uint64_t addr, unsigned int length) override; - - 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; - } - - vm_impl* vm; - rp_thread_ref thread_idx; -}; - -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 ; - - vm_impl(); - - vm_impl(ARCH& core, bool dump=false); - - 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); - return vm::vm_base::tgt_adapter; - } - - -protected: - - template inline - llvm::ConstantInt* size(T type){ - return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); - } - - inline llvm::Value * gen_choose(llvm::Value * cond, llvm::Value * trueVal, llvm::Value * falseVal, unsigned size) const { - return 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; - - void gen_leave_behavior(llvm::BasicBlock* leave_blk) override; - - void gen_raise_trap(uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(unsigned lvl); - - void gen_wait(unsigned type); - - void gen_trap_behavior(llvm::BasicBlock*) override; - - void gen_trap_check(llvm::BasicBlock* bb); - - inline - 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) { - case 8: - ptrType=llvm::Type::getInt64PtrTy(this->mod->getContext()); - break; - case 4: - ptrType=llvm::Type::getInt32PtrTy(this->mod->getContext()); - break; - case 2: - ptrType=llvm::Type::getInt16PtrTy(this->mod->getContext()); - break; - case 1: - 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); - } - - 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)); - 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<; - 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}; - - 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; - } else { - auto bitmask = 1UL<>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< 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->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 - 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 -vm_impl::vm_impl(){ - this(new ARCH()); -} - -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); - } - 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){ - // 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 - auto res = this->core.read(paddr, 2, data); - if(res!=iss::Ok) - throw trap_access(1, pc.val); - if((insn & 0x3) == 0x3){ // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc+2), 2, data+2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if(res!=iss::Ok) - throw trap_access(1, pc.val); - } - } catch(trap_access& ta){ - throw trap_access(ta.id, pc.val); - } - if(insn==0x0000006f) - 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; - } - return (this->*f)(pc, insn, this_block); -} - -template -void vm_impl::gen_leave_behavior(llvm::BasicBlock* leave_blk){ - this->builder->SetInsertPoint(leave_blk); - this->builder->CreateRet(this->builder->CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); -} - -template -void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause){ - auto* TRAP_val = this->gen_const(32, 0x80<<24| (cause<<16) | trap_id ); - this->builder->CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); -} - -template -void vm_impl::gen_leave_trap(unsigned lvl){ - std::vector args { - this->core_ptr, - llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)), - }; - this->builder->CreateCall(this->mod->getFunction("leave_trap"), args); - auto* PC_val = this->gen_read_mem(traits::CSR, (lvl<<8)+0x41, traits::XLEN/8); - this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); -} - -template -void vm_impl::gen_wait(unsigned type){ - std::vector args { - this->core_ptr, - llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)), - }; - this->builder->CreateCall(this->mod->getFunction("wait"), args); -} - -template -void vm_impl::gen_trap_behavior(llvm::BasicBlock* trap_blk){ - this->builder->SetInsertPoint(trap_blk); - auto* trap_state_val = this->builder->CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); - std::vector args { - this->core_ptr, - this->adj_to64(trap_state_val), - this->adj_to64(this->builder->CreateLoad(get_reg_ptr(traits::PC), false)) - }; - this->builder->CreateCall(this->mod->getFunction("enter_trap"), args); - auto* trap_addr_val = this->builder->CreateLoad(get_reg_ptr(traits::NEXT_PC), false); - this->builder->CreateRet(trap_addr_val); -} - -template inline -void vm_impl::gen_trap_check(llvm::BasicBlock* bb){ - auto* v = this->builder->CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); - this->gen_cond_branch( - this->builder->CreateICmp( - ICmpInst::ICMP_EQ, - v, - llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, - this->trap_blk, 1); -} - -} // namespace CORE_DEF_NAME - -#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; - 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::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(logging::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 - 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::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(logging::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(logging::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; - vm->get_arch()->set_reg(reg_no, data); - return resume_from_current(step, sig); - } -} // namespace CORE_DEF_NAME -} // namespace iss diff --git a/riscv.sc/src/internal/vm_rv32imac.cpp b/riscv.sc/src/internal/vm_rv32imac.cpp deleted file mode 100644 index 472a2ff..0000000 --- a/riscv.sc/src/internal/vm_rv32imac.cpp +++ /dev/null @@ -1,4882 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017, MINRES Technologies GmbH -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Contributors: -// eyck@minres.com - initial API and implementation -// -// -//////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "iss/vm_base.h" -#include "iss/arch/rv32imac.h" -#include "iss/debugger/server.h" - -#include -#include "iss/arch/riscv_hart_msu_vp.h" - -namespace iss { -namespace rv32imac { -using namespace iss::arch; -using namespace llvm; -using namespace iss::debugger; - -template -struct vm_impl; - -template -struct target_adapter: public target_adapter_base { - - 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; - - /* Set control thread */ - status set_ctrl_thread(rp_thread_ref& thread) override; - - /* Get thread status */ - status is_thread_alive(rp_thread_ref& thread, bool& alive) override; - - /*============= Register Access ================================*/ - - /* Read all registers. 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_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; - - /* 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; - - /* 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; - - /*=================== 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; - - /* 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 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 current_thread_query(rp_thread_ref& thread) 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 raw_query(std::string in_buf, 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 packetsize_query(std::string& out_buf) override; - - status add_break(int type, uint64_t addr, unsigned int length) override; - - status remove_break(int type, uint64_t addr, unsigned int length) override; - - 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; - } - - vm_impl* vm; - rp_thread_ref thread_idx; -}; - -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 ; - - vm_impl(); - - vm_impl(ARCH& core, bool dump=false); - - 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); - return vm::vm_base::tgt_adapter; - } - - -protected: - - template inline - llvm::ConstantInt* size(T type){ - return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); - } - - inline llvm::Value * gen_choose(llvm::Value * cond, llvm::Value * trueVal, llvm::Value * falseVal, unsigned size) const { - return 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; - - void gen_leave_behavior(llvm::BasicBlock* leave_blk) override; - - void gen_raise_trap(uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(unsigned lvl); - - void gen_wait(unsigned type); - - void gen_trap_behavior(llvm::BasicBlock*) override; - - void gen_trap_check(llvm::BasicBlock* bb); - - inline - 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) { - case 8: - ptrType=llvm::Type::getInt64PtrTy(this->mod->getContext()); - break; - case 4: - ptrType=llvm::Type::getInt32PtrTy(this->mod->getContext()); - break; - case 2: - ptrType=llvm::Type::getInt16PtrTy(this->mod->getContext()); - break; - case 1: - 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); - } - - 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)); - 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<; - 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}; - - 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; - } else { - auto bitmask = 1UL<>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< __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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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)); - 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){ - 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){ - /* 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()) - }; - 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)); - 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))); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* generate console output when executing the command */ - 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()) - }; - 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)), - 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_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 */ - 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){ - 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){ - /* generate console output when executing the command */ - 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()) - }; - 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))); - 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){ - bb->setName("ECALL"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - bb->setName("EBREAK"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - bb->setName("URET"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - bb->setName("SRET"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - bb->setName("MRET"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - bb->setName("WFI"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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 */ - 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){ - 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){ - /* generate console output when executing the command */ - 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()) - }; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - // 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->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)); - 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)); - this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); - } - this->builder->CreateBr(bbnext); - bb=bbnext; - this->builder->SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "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){ - 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){ - /* 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()) - }; - 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); - // 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->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)); - 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)); - this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); - } - this->builder->CreateBr(bbnext); - bb=bbnext; - this->builder->SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "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){ - 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){ - /* 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()) - }; - 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); - // 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->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)); - 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); - this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); - } - this->builder->CreateBr(bbnext); - bb=bbnext; - this->builder->SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "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){ - 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){ - /* 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()) - }; - 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); - // 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->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)); - 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); - this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); - } - this->builder->CreateBr(bbnext); - bb=bbnext; - this->builder->SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "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){ - 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){ - /* 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()) - }; - 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); - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - // this->builder->SetInsertPoint(bb); - this->gen_cond_branch(this->builder->CreateICmp( - ICmpInst::ICMP_NE, - res1_val, - this->gen_const(32U, 0)), - bb_then, - bbnext); - this->builder->SetInsertPoint(bb_then); - { - Value* 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; - 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); - 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 */ - 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){ - 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){ - /* 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; - 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()) - }; - 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); - 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))); - 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 */ - 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){ - 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){ - /* 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; - 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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; - 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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; - 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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; - 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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; - 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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; - 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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; - 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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; - 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - uint8_t rd_idx_val = (fld_rd_val + 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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))); - 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 */ - 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){ - bb->setName("C.NOP"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - boost::format ins_fmter("C.NOP "); - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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)); - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - pc=pc+2; - - if(fld_rd_val == 0){ - this->gen_raise_trap(0, 2); - } - if(fld_rd_val == 2){ - this->gen_raise_trap(0, 2); - } - if(fld_nzimm_val == 0){ - this->gen_raise_trap(0, 2); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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); - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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); - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - pc=pc+2; - - if(fld_rs1_val == 0){ - this->gen_raise_trap(0, 2); - } - 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)); - 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 */ - 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){ - 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){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - bb->setName("C.EBREAK"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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)); - this->builder->CreateStore(X_rd_val, get_reg_ptr(rd_val), false); - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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))); - 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 */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - -/* 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); - this->builder->CreateStore( - this->builder->CreateLoad(get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); - this->builder->CreateStore( - this->builder->CreateAdd( - this->builder->CreateLoad(get_reg_ptr(traits::ICOUNT), true), - this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); - 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 -vm_impl::vm_impl(){ - this(new ARCH()); -} - -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); - } - 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){ - // 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 - auto res = this->core.read(paddr, 2, data); - if(res!=iss::Ok) - throw trap_access(1, pc.val); - if((insn & 0x3) == 0x3){ // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc+2), 2, data+2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if(res!=iss::Ok) - throw trap_access(1, pc.val); - } - } catch(trap_access& ta){ - throw trap_access(ta.id, pc.val); - } - if(insn==0x0000006f) - 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; - } - return (this->*f)(pc, insn, this_block); -} - -template -void vm_impl::gen_leave_behavior(llvm::BasicBlock* leave_blk){ - this->builder->SetInsertPoint(leave_blk); - this->builder->CreateRet(this->builder->CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); -} - -template -void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause){ - auto* TRAP_val = this->gen_const(32, 0x80<<24| (cause<<16) | trap_id ); - this->builder->CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); -} - -template -void vm_impl::gen_leave_trap(unsigned lvl){ - std::vector args { - this->core_ptr, - llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)), - }; - this->builder->CreateCall(this->mod->getFunction("leave_trap"), args); - auto* PC_val = this->gen_read_mem(traits::CSR, (lvl<<8)+0x41, traits::XLEN/8); - this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); -} - -template -void vm_impl::gen_wait(unsigned type){ - std::vector args { - this->core_ptr, - llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)), - }; - this->builder->CreateCall(this->mod->getFunction("wait"), args); -} - -template -void vm_impl::gen_trap_behavior(llvm::BasicBlock* trap_blk){ - this->builder->SetInsertPoint(trap_blk); - auto* trap_state_val = this->builder->CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); - std::vector args { - this->core_ptr, - this->adj_to64(trap_state_val), - this->adj_to64(this->builder->CreateLoad(get_reg_ptr(traits::PC), false)) - }; - this->builder->CreateCall(this->mod->getFunction("enter_trap"), args); - auto* trap_addr_val = this->builder->CreateLoad(get_reg_ptr(traits::NEXT_PC), false); - this->builder->CreateRet(trap_addr_val); -} - -template inline -void vm_impl::gen_trap_check(llvm::BasicBlock* bb){ - auto* v = this->builder->CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); - this->gen_cond_branch( - this->builder->CreateICmp( - ICmpInst::ICMP_EQ, - v, - llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, - this->trap_blk, 1); -} - -} // namespace 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);\ -} - -CREATE_FUNCS(arch::rv32imac) - -namespace rv32imac { - - 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::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(logging::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 - 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::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(logging::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(logging::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; - vm->get_arch()->set_reg(reg_no, data); - return resume_from_current(step, sig); - } -} // namespace rv32imac -} // namespace iss diff --git a/riscv.sc/src/internal/vm_rv64ia.cpp b/riscv.sc/src/internal/vm_rv64ia.cpp deleted file mode 100644 index 47b13b8..0000000 --- a/riscv.sc/src/internal/vm_rv64ia.cpp +++ /dev/null @@ -1,3884 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017, MINRES Technologies GmbH -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Contributors: -// eyck@minres.com - initial API and implementation -// -// -//////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "iss/vm_base.h" -#include "iss/arch/rv64ia.h" -#include "iss/debugger/server.h" - -#include -#include "iss/arch/riscv_hart_msu_vp.h" - -namespace iss { -namespace rv64ia { -using namespace iss::arch; -using namespace llvm; -using namespace iss::debugger; - -template -struct vm_impl; - -template -struct target_adapter: public target_adapter_base { - - 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; - - /* Set control thread */ - status set_ctrl_thread(rp_thread_ref& thread) override; - - /* Get thread status */ - status is_thread_alive(rp_thread_ref& thread, bool& alive) override; - - /*============= Register Access ================================*/ - - /* Read all registers. 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_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; - - /* 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; - - /* 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; - - /*=================== 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; - - /* 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 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 current_thread_query(rp_thread_ref& thread) 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 raw_query(std::string in_buf, 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 packetsize_query(std::string& out_buf) override; - - status add_break(int type, uint64_t addr, unsigned int length) override; - - status remove_break(int type, uint64_t addr, unsigned int length) override; - - 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; - } - - vm_impl* vm; - rp_thread_ref thread_idx; -}; - -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 ; - - vm_impl(); - - vm_impl(ARCH& core, bool dump=false); - - 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); - return vm::vm_base::tgt_adapter; - } - - -protected: - - template inline - llvm::ConstantInt* size(T type){ - return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); - } - - inline llvm::Value * gen_choose(llvm::Value * cond, llvm::Value * trueVal, llvm::Value * falseVal, unsigned size) const { - return 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; - - void gen_leave_behavior(llvm::BasicBlock* leave_blk) override; - - void gen_raise_trap(uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(unsigned lvl); - - void gen_wait(unsigned type); - - void gen_trap_behavior(llvm::BasicBlock*) override; - - void gen_trap_check(llvm::BasicBlock* bb); - - inline - 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) { - case 8: - ptrType=llvm::Type::getInt64PtrTy(this->mod->getContext()); - break; - case 4: - ptrType=llvm::Type::getInt32PtrTy(this->mod->getContext()); - break; - case 2: - ptrType=llvm::Type::getInt16PtrTy(this->mod->getContext()); - break; - case 1: - 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); - } - - 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)); - 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<; - 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}; - - 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; - } else { - auto bitmask = 1UL<>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< __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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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) - ), - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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 */ - 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){ - 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){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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->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->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 */ - 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){ - 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){ - /* 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()) - }; - 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->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 */ - 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){ - 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){ - /* 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()) - }; - 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->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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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)); - 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){ - 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){ - /* 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()) - }; - 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)); - 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))); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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)); - 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 */ - 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){ - 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){ - /* generate console output when executing the command */ - 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()) - }; - 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)), - 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_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 */ - 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){ - 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){ - /* generate console output when executing the command */ - 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()) - }; - 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))); - 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){ - bb->setName("ECALL"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - bb->setName("EBREAK"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - bb->setName("URET"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - bb->setName("SRET"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - bb->setName("MRET"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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){ - bb->setName("WFI"); - - this->gen_sync(iss::PRE_SYNC); - - ; - if(this->disass_enabled){ - /* generate console output when executing the command */ - 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()) - }; - this->builder->CreateCall(this->mod->getFunction("print_disass"), args); - } - 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 */ - 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){ - 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){ - /* generate console output when executing the command */ - 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()) - }; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - 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))); - } - 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 */ - 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){ - 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){ - /* 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()) - }; - 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); - // this->builder->SetInsertPoint(bb); - this->gen_cond_branch(this->builder->CreateICmp( - ICmpInst::ICMP_NE, - res_val, - this->gen_const(64U, 0)), - bb_then, - bb_else); - this->builder->SetInsertPoint(bb_then); - { - Value* 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); - this->builder->CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); - } - } - this->builder->CreateBr(bbnext); - bb=bbnext; - this->builder->SetInsertPoint(bb); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(iss::POST_SYNC); /* call post-sync if needed */ - bb = llvm::BasicBlock::Create(this->mod->getContext(), "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){ - 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){ - /* 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()) - }; - 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); - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - 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 */ - 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){ - 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){ - /* 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()) - }; - 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; - 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))); - 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 */ - this->gen_trap_check(bb); - return std::make_tuple(vm::CONT, bb); - } - -/* 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); - this->builder->CreateStore( - this->builder->CreateLoad(get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); - this->builder->CreateStore( - this->builder->CreateAdd( - this->builder->CreateLoad(get_reg_ptr(traits::ICOUNT), true), - this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); - 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 -vm_impl::vm_impl(){ - this(new ARCH()); -} - -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); - } - 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){ - // 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 - auto res = this->core.read(paddr, 2, data); - if(res!=iss::Ok) - throw trap_access(1, pc.val); - if((insn & 0x3) == 0x3){ // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc+2), 2, data+2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if(res!=iss::Ok) - throw trap_access(1, pc.val); - } - } catch(trap_access& ta){ - throw trap_access(ta.id, pc.val); - } - if(insn==0x0000006f) - 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; - } - return (this->*f)(pc, insn, this_block); -} - -template -void vm_impl::gen_leave_behavior(llvm::BasicBlock* leave_blk){ - this->builder->SetInsertPoint(leave_blk); - this->builder->CreateRet(this->builder->CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); -} - -template -void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause){ - auto* TRAP_val = this->gen_const(32, 0x80<<24| (cause<<16) | trap_id ); - this->builder->CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); -} - -template -void vm_impl::gen_leave_trap(unsigned lvl){ - std::vector args { - this->core_ptr, - llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)), - }; - this->builder->CreateCall(this->mod->getFunction("leave_trap"), args); - auto* PC_val = this->gen_read_mem(traits::CSR, (lvl<<8)+0x41, traits::XLEN/8); - this->builder->CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); -} - -template -void vm_impl::gen_wait(unsigned type){ - std::vector args { - this->core_ptr, - llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)), - }; - this->builder->CreateCall(this->mod->getFunction("wait"), args); -} - -template -void vm_impl::gen_trap_behavior(llvm::BasicBlock* trap_blk){ - this->builder->SetInsertPoint(trap_blk); - auto* trap_state_val = this->builder->CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); - std::vector args { - this->core_ptr, - this->adj_to64(trap_state_val), - this->adj_to64(this->builder->CreateLoad(get_reg_ptr(traits::PC), false)) - }; - this->builder->CreateCall(this->mod->getFunction("enter_trap"), args); - auto* trap_addr_val = this->builder->CreateLoad(get_reg_ptr(traits::NEXT_PC), false); - this->builder->CreateRet(trap_addr_val); -} - -template inline -void vm_impl::gen_trap_check(llvm::BasicBlock* bb){ - auto* v = this->builder->CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); - this->gen_cond_branch( - this->builder->CreateICmp( - ICmpInst::ICMP_EQ, - v, - llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, - this->trap_blk, 1); -} - -} // namespace 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);\ -} - -CREATE_FUNCS(arch::rv64ia) - -namespace rv64ia { - - 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::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(logging::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 - 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::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(logging::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(logging::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; - vm->get_arch()->set_reg(reg_no, data); - return resume_from_current(step, sig); - } -} // namespace rv64ia -} // namespace iss diff --git a/riscv.sc/src/iss/rv32imac.cpp b/riscv.sc/src/iss/rv32imac.cpp deleted file mode 100644 index 8b2e118..0000000 --- a/riscv.sc/src/iss/rv32imac.cpp +++ /dev/null @@ -1,76 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017, MINRES Technologies GmbH -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Created on: Tue Aug 29 16:45:20 CEST 2017 -// * rv32imac.cpp Author: -// -//////////////////////////////////////////////////////////////////////////////// - -#include "util/ities.h" -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif -#include -#ifdef __cplusplus -} -#endif -#include -#include -#include - -using namespace iss::arch; - -rv32imac::rv32imac() { - reg.icount=0; -} - -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; -} - -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 -} diff --git a/riscv.sc/src/iss/rv64ia.cpp b/riscv.sc/src/iss/rv64ia.cpp deleted file mode 100644 index 79f11ee..0000000 --- a/riscv.sc/src/iss/rv64ia.cpp +++ /dev/null @@ -1,76 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017, MINRES Technologies GmbH -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -// Created on: Tue Sep 05 18:57:24 CEST 2017 -// * rv64ia.cpp Author: -// -//////////////////////////////////////////////////////////////////////////////// - -#include "util/ities.h" -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif -#include -#ifdef __cplusplus -} -#endif -#include -#include -#include - -using namespace iss::arch; - -rv64ia::rv64ia() { - reg.icount=0; -} - -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; -} - -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 -} diff --git a/riscv/incl/cli_options.h b/riscv/incl/cli_options.h index 9e02585..76da009 100644 --- a/riscv/incl/cli_options.h +++ b/riscv/incl/cli_options.h @@ -39,98 +39,10 @@ #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 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); -} - -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[]){ namespace po = boost::program_options; po::options_description desc("Options"); diff --git a/riscv/incl/iss/arch/riscv_hart_msu_vp.h b/riscv/incl/iss/arch/riscv_hart_msu_vp.h index b2c5d2f..1e5715d 100644 --- a/riscv/incl/iss/arch/riscv_hart_msu_vp.h +++ b/riscv/incl/iss/arch/riscv_hart_msu_vp.h @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include @@ -628,9 +628,9 @@ 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(logging::DEBUG)<<"debug read of "<::write(const iss::addr_t& addr, unsigned len const char* prefix = addr.type & iss::DEBUG?"debug ":""; switch(length){ case 8: - LOG(logging::DEBUG)<::write_mem(phys_addr_t addr, unsigned length switch(hostvar>>48){ case 0: if(hostvar!=0x1) - LOG(logging::FATAL)<<"tohost value is 0x"<(hostvar & 0xff); if(c=='\n' || c==0){ - LOG(logging::INFO)<<"tohost send '"<::enter_trap(uint64_t flags, uint64_t addr) { this->reg.trap_state=0; char buffer[32]; sprintf(buffer, "0x%016lx", addr); - CLOG(logging::INFO, "disass")<<(trap_id?"Interrupt ":"Trap ")<reg.NEXT_PC; } @@ -1230,7 +1230,7 @@ uint64_t riscv_hart_msu_vp::leave_trap(uint64_t flags) { status|= pie<reg.machine_state=ppl; - CLOG(logging::INFO, "disass")<<"Executing xRET , changing privilege level from "<reg.NEXT_PC; } diff --git a/riscv/src/internal/vm_riscv.in.cpp b/riscv/src/internal/vm_riscv.in.cpp index b5c7b7c..6183a2d 100644 --- a/riscv/src/internal/vm_riscv.in.cpp +++ b/riscv/src/internal/vm_riscv.in.cpp @@ -521,7 +521,7 @@ namespace CORE_DEF_NAME { template status target_adapter::read_registers(std::vector& data, std::vector& avail) { - LOG(logging::TRACE)<<"reading target registers"; + LOG(TRACE)<<"reading target registers"; //return idx<0?:; data.clear(); avail.clear(); @@ -663,8 +663,8 @@ namespace CORE_DEF_NAME { 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(logging::TRACE)<<"Adding breakpoint with handle "< status target_adapter::read_registers(std::vector& data, std::vector& avail) { - LOG(logging::TRACE)<<"reading target registers"; + LOG(TRACE)<<"reading target registers"; //return idx<0?:; data.clear(); avail.clear(); @@ -4850,8 +4850,8 @@ namespace rv32imac { 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(logging::TRACE)<<"Adding breakpoint with handle "< status target_adapter::read_registers(std::vector& data, std::vector& avail) { - LOG(logging::TRACE)<<"reading target registers"; + LOG(TRACE)<<"reading target registers"; //return idx<0?:; data.clear(); avail.clear(); @@ -3852,8 +3852,8 @@ namespace rv64ia { 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(logging::TRACE)<<"Adding breakpoint with handle "< #include +#include #include #include #include @@ -46,13 +47,22 @@ namespace po= boost::program_options; int main(int argc, char *argv[]) { try{ - /** Define and parse the program options + /* + * Define and parse the program options */ po::variables_map vm; if(parse_cli_options(vm, argc, argv)) return ERROR_IN_COMMAND_LINE; - configure_default_logger(vm); - // configure the connection logger - configure_debugger_logger(); + if(vm.count("verbose")){ + auto l = logging::as_log_level(vm["verbose"].as()); + LOGGER(DEFAULT)::reporting_level() = l; + LOGGER(connection)::reporting_level()=l; + } + if(vm.count("log-file")){ + // configure the connection logger + auto f = fopen(vm["log-file"].as().c_str(), "w"); + LOG_OUTPUT(DEFAULT)::stream() = f; + LOG_OUTPUT(connection)::stream() = f; + } // application code comes here // iss::init_jit(argc, argv); @@ -77,9 +87,15 @@ int main(int argc, char *argv[]) { cpu->get_arch()->load_file(vm["mem"].as() , iss::arch::traits::MEM); } - configure_disass_logger(vm); if(vm.count("disass")){ cpu->setDisassEnabled(true); + 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")){ auto str = vm["reset"].as(); @@ -90,7 +106,7 @@ int main(int argc, char *argv[]) { } return cpu->start(vm["cycles"].as()); } catch(std::exception& e){ - LOG(logging::ERROR) << "Unhandled Exception reached the top of main: " + 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 4bc2664..46d7950 160000 --- a/sc-components +++ b/sc-components @@ -1 +1 @@ -Subproject commit 4bc26642e349906f6e81619ea8a26bf533c3f46f +Subproject commit 46d79504a8a5a6a9541b19a6774fb8161350a0a4