From a92b84bef4abaa37a50f9ebdbc100384e57d50cb Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 25 Apr 2022 14:18:19 +0200 Subject: [PATCH 001/184] add code word access for ISS plugins --- gen_input/TGC_C.core_desc | 6 +++--- gen_input/templates/CORENAME.cpp.gtl | 2 +- gen_input/templates/CORENAME.h.gtl | 6 ++++-- gen_input/templates/interp/CORENAME.cpp.gtl | 7 ++++--- incl/iss/arch/riscv_hart_m_p.h | 8 +++---- incl/iss/arch/tgc_c.h | 14 +++++++------ src/iss/tgc_c.cpp | 4 ++-- src/plugin/pctrace.cpp | 5 ++++- src/vm/interp/vm_tgc_c.cpp | 23 +++++++++++---------- 9 files changed, 42 insertions(+), 33 deletions(-) diff --git a/gen_input/TGC_C.core_desc b/gen_input/TGC_C.core_desc index d3a529e..72f549d 100644 --- a/gen_input/TGC_C.core_desc +++ b/gen_input/TGC_C.core_desc @@ -1,6 +1,6 @@ -import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" -import "CoreDSL-Instruction-Set-Description/RVM.core_desc" -import "CoreDSL-Instruction-Set-Description/RVC.core_desc" +import "RV32I.core_desc" +import "RVM.core_desc" +import "RVC.core_desc" Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { architectural_state { diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl index 6bb5c4e..ead228a 100644 --- a/gen_input/templates/CORENAME.cpp.gtl +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -33,7 +33,7 @@ def getRegisterSizes(){ def regs = registers.collect{it.size} regs[-1]=64 // correct for NEXT_PC - regs+=[32, 32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET + regs+=[32, 32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION return regs } %> diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index dbe4c82..c114cec 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -37,7 +37,7 @@ def nativeTypeSize(int size){ } def getRegisterSizes(){ def regs = registers.collect{nativeTypeSize(it.size)} - regs+=[32,32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET + regs+=[32,32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION return regs } def getRegisterOffsets(){ @@ -96,7 +96,8 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { PENDING_TRAP, ICOUNT, CYCLE, - INSTRET + INSTRET, + INSTRUCTION }; using reg_t = uint${addrDataWidth}_t; @@ -170,6 +171,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; uint64_t instret = 0; + uint32_t instruction = 0; uint32_t last_branch; } reg; #pragma pack(pop) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 98817ce..9883e16 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -277,9 +277,6 @@ typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ - // we fetch at max 4 byte, alignment is 2 - code_word_t instr = 0; - auto *const data = (uint8_t *)&instr; auto pc=start; auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -287,6 +284,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); auto* icount = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]); auto* instret = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]); + auto *const instruction = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRUCTION]); + // we fetch at max 4 byte, alignment is 2 + auto *const data = reinterpret_cast(instruction); + auto& instr = *instruction; while(!this->core.should_stop() && !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index bff635d..7a798bf 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -235,9 +235,11 @@ protected: */ const std::string core_type_name() const override { return traits::core_type; } - uint64_t get_pc() override { return arch.get_pc(); }; + uint64_t get_pc() override { return arch.reg.PC; }; - uint64_t get_next_pc() override { return arch.get_next_pc(); }; + uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; + + uint64_t get_instr_word() override { return arch.reg.instruction; } uint64_t get_instr_count() { return arch.reg.icount; } @@ -249,8 +251,6 @@ protected: }; friend struct riscv_instrumentation_if; - addr_t get_pc() { return this->reg.PC; } - addr_t get_next_pc() { return this->reg.NEXT_PC; } 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); diff --git a/incl/iss/arch/tgc_c.h b/incl/iss/arch/tgc_c.h index 619034d..9640ae9 100644 --- a/incl/iss/arch/tgc_c.h +++ b/incl/iss/arch/tgc_c.h @@ -53,7 +53,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; - enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, RFS=32, INSTR_ALIGNMENT=2, XLEN=32, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; + enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, RFS=32, XLEN=32, CSR_SIZE=4096, INSTR_ALIGNMENT=2, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; constexpr static unsigned FP_REGS_SIZE = 0; @@ -63,7 +63,8 @@ template <> struct traits { PENDING_TRAP, ICOUNT, CYCLE, - INSTRET + INSTRET, + INSTRUCTION }; using reg_t = uint32_t; @@ -76,11 +77,11 @@ template <> struct traits { using phys_addr_t = iss::typed_addr_t; - static constexpr std::array reg_bit_widths{ - {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64}}; + static constexpr std::array reg_bit_widths{ + {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64,32}}; - static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165}}; + static constexpr std::array reg_byte_offsets{ + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165,173}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); @@ -259,6 +260,7 @@ struct tgc_c: public arch_if { uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; uint64_t instret = 0; + uint32_t instruction = 0; uint32_t last_branch; } reg; #pragma pack(pop) diff --git a/src/iss/tgc_c.cpp b/src/iss/tgc_c.cpp index b5e8fed..3c6fcd0 100644 --- a/src/iss/tgc_c.cpp +++ b/src/iss/tgc_c.cpp @@ -41,8 +41,8 @@ using namespace iss::arch; constexpr std::array iss::arch::traits::reg_names; constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; tgc_c::tgc_c() { reg.icount = 0; diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp index e178072..4c6ea1a 100644 --- a/src/plugin/pctrace.cpp +++ b/src/plugin/pctrace.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include "rapidjson/writer.h" @@ -123,7 +124,9 @@ void iss::plugin::cov::callback(instr_info_t iinfo, const exec_info& einfo) { //source code for the full output auto delay = 0; - auto entry = delays[iinfo.instr_id]; + size_t id = iinfo.instr_id; + auto entry = delays[id]; + auto call = (id==2 || id==3) && bit_sub<7,5>(instr_if->get_instr_word())!=0; bool taken = einfo.branch_taken; if (einfo.branch_taken) delay = entry.taken; diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index ea76eaf..435389d 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -358,9 +358,6 @@ typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ - // we fetch at max 4 byte, alignment is 2 - code_word_t instr = 0; - auto *const data = (uint8_t *)&instr; auto pc=start; auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -368,6 +365,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); auto* icount = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]); auto* instret = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]); + auto *const instruction = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRUCTION]); + // we fetch at max 4 byte, alignment is 2 + auto *const data = reinterpret_cast(instruction); + auto& instr = *instruction; while(!this->core.should_stop() && !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ @@ -2001,7 +2002,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rs1_idx = rs1 + 8; + uint32_t rs1_idx = rs1 + 8; *(X+rs1_idx) = *(X+rs1_idx) >> shamt; } } catch(...){} @@ -2024,11 +2025,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { if(shamt) { - uint8_t rs1_idx = rs1 + 8; + uint32_t rs1_idx = rs1 + 8; *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; } else if(traits::XLEN == 128) { - uint8_t rs1_idx = rs1 + 8; + uint32_t rs1_idx = rs1 + 8; *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; } } catch(...){} @@ -2051,7 +2052,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rs1_idx = rs1 + 8; + uint32_t rs1_idx = rs1 + 8; *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm); } } catch(...){} @@ -2074,7 +2075,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rd_idx = rd + 8; + uint32_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) - *(X+rs2 + 8); } } catch(...){} @@ -2097,7 +2098,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rd_idx = rd + 8; + uint32_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) ^ *(X+rs2 + 8); } } catch(...){} @@ -2120,7 +2121,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rd_idx = rd + 8; + uint32_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) | *(X+rs2 + 8); } } catch(...){} @@ -2143,7 +2144,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rd_idx = rd + 8; + uint32_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) & *(X+rs2 + 8); } } catch(...){} From 5f6d462973f72504001bfd06c9874381a12214c5 Mon Sep 17 00:00:00 2001 From: Stanislaw Kaushanski Date: Tue, 26 Apr 2022 13:58:20 +0200 Subject: [PATCH 002/184] check that no interrupts are pending before entering the wfi wait --- src/sysc/core_complex.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 3d29ee8..f7b95c7 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -175,9 +175,9 @@ public: void wait_until(uint64_t flags) override { SCCDEBUG(owner->name()) << "Sleeping until interrupt"; - do { + while(this->reg.pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) { sc_core::wait(wfi_evt); - } while (this->reg.pending_trap == 0); + } PLAT::wait_until(flags); } From 9d9008a3a2658768a36905aa879652d695633c57 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 26 Apr 2022 15:11:57 +0200 Subject: [PATCH 003/184] fix pointer mess --- gen_input/templates/CORENAME.cpp.gtl | 10 ++-- gen_input/templates/CORENAME.h.gtl | 25 ++++----- gen_input/templates/interp/CORENAME.cpp.gtl | 43 ++++++++------- incl/iss/arch/riscv_hart_m_p.h | 56 ++++++++++---------- incl/iss/arch/riscv_hart_msu_vp.h | 46 ++++++++-------- incl/iss/arch/riscv_hart_mu_p.h | 58 ++++++++++----------- incl/iss/arch/tgc_c.h | 31 +++++------ src/iss/tgc_c.cpp | 12 ++--- src/plugin/pctrace.cpp | 3 +- src/sysc/core_complex.cpp | 8 +-- src/vm/interp/vm_tgc_c.cpp | 43 ++++++++------- 11 files changed, 160 insertions(+), 175 deletions(-) diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl index ead228a..eae0aa7 100644 --- a/gen_input/templates/CORENAME.cpp.gtl +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -33,7 +33,7 @@ def getRegisterSizes(){ def regs = registers.collect{it.size} regs[-1]=64 // correct for NEXT_PC - regs+=[32, 32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION + //regs+=[32, 32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION return regs } %> @@ -51,9 +51,7 @@ constexpr std::array iss::arch::traits iss::arch::traits::reg_bit_widths; constexpr std::array iss::arch::traits::reg_byte_offsets; -${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { - reg.icount = 0; -} +${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() = default; ${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default; @@ -64,8 +62,8 @@ void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { reg.PC=address; reg.NEXT_PC=reg.PC; reg.PRIV=0x3; - reg.trap_state=0; - reg.icount=0; + trap_state=0; + icount=0; } uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index c114cec..4497ba3 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -37,7 +37,7 @@ def nativeTypeSize(int size){ } def getRegisterSizes(){ def regs = registers.collect{nativeTypeSize(it.size)} - regs+=[32,32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION + // regs+=[32,32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION return regs } def getRegisterOffsets(){ @@ -91,13 +91,7 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { constexpr static unsigned FP_REGS_SIZE = ${constants.find {it.name=='FLEN'}?.value?:0}; enum reg_e { - ${registers.collect{it.name}.join(', ')}, NUM_REGS, - TRAP_STATE=NUM_REGS, - PENDING_TRAP, - ICOUNT, - CYCLE, - INSTRET, - INSTRUCTION + ${registers.collect{it.name}.join(', ')}, NUM_REGS }; using reg_t = uint${addrDataWidth}_t; @@ -142,7 +136,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { uint8_t* get_regs_base_ptr() override; - inline uint64_t get_icount() { return reg.icount; } + inline uint64_t get_icount() { return icount; } inline bool should_stop() { return interrupt_sim; } @@ -160,7 +154,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } - inline uint32_t get_last_branch() { return reg.last_branch; } + inline uint32_t get_last_branch() { return last_branch; } #pragma pack(push, 1) @@ -168,12 +162,13 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { registers.each { reg -> if(reg.size>0) {%> uint${byteSize(reg.size)}_t ${reg.name} = 0;<% }}%> - uint32_t trap_state = 0, pending_trap = 0; - uint64_t icount = 0; - uint64_t instret = 0; - uint32_t instruction = 0; - uint32_t last_branch; } reg; + uint32_t trap_state = 0, pending_trap = 0; + uint64_t icount = 0; + uint64_t cycle = 0; + uint64_t instret = 0; + uint32_t instruction = 0; + uint32_t last_branch = 0; #pragma pack(pop) std::array addr_mode; diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 9883e16..76449f6 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -121,7 +121,7 @@ protected: inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; - this->template get_reg(traits::TRAP_STATE) = trap_val; + this->core.trap_state = trap_val; this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); } @@ -141,39 +141,39 @@ protected: T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; return ret; } inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){ auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; return ret; } inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){ auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; return ret; } inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){ auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; return ret; } inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){ super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; } inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){ super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; } inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){ super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; } inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){ super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; } template::type> inline S sext(U from) { @@ -278,16 +278,15 @@ typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ auto pc=start; - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - auto* icount = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]); - auto* instret = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]); - auto *const instruction = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRUCTION]); + auto& trap_state = this->core.trap_state; + auto& icount = this->core.icount; + auto& cycle = this->core.cycle; + auto& instret = this->core.instret; + auto& instr = this->core.instruction; // we fetch at max 4 byte, alignment is 2 - auto *const data = reinterpret_cast(instruction); - auto& instr = *instruction; + auto *const data = reinterpret_cast(&instr); while(!this->core.should_stop() && !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ @@ -329,16 +328,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); + if(trap_state!=0){ + super::core.enter_trap(trap_state, pc.val, instr); } else { - (*icount)++; - (*instret)++; + icount++; + instret++; } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; + cycle++; pc.val=*NEXT_PC; this->core.reg.PC = this->core.reg.NEXT_PC; - this->core.reg.trap_state = this->core.reg.pending_trap; + this->core.trap_state = this->core.pending_trap; } } return pc; diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index 7a798bf..52bf1ad 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -203,7 +203,7 @@ public: void disass_output(uint64_t pc, const std::string instr) override { CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", - pc, instr, (reg_t)state.mstatus, this->reg.icount + cycle_offset); + pc, instr, (reg_t)state.mstatus, this->icount + cycle_offset); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } @@ -239,11 +239,11 @@ protected: uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; - uint64_t get_instr_word() override { return arch.reg.instruction; } + uint64_t get_instr_word() override { return arch.instruction; } - uint64_t get_instr_count() { return arch.reg.icount; } + uint64_t get_instr_count() { return arch.icount; } - uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } + uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; @@ -568,13 +568,13 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31); // issue trap 0 + this->trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { auto alignment = access == iss::access_type::FETCH? (traits::MISA_VAL&0x100? 2 : 4) : length; if(alignment>1 && (addr&(alignment-1))){ - this->reg.trap_state = 1<<31 | 4<<16; + this->trap_state = 1<<31 | 4<<16; fault_data=addr; return iss::Err; } @@ -593,12 +593,12 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce res = read_mem( phys_addr, length, data); } if (unlikely(res != iss::Ok)){ - this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault + this->trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; } return res; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -624,7 +624,7 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce } return iss::Ok; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -662,12 +662,12 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31); // issue trap 0 + this->trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ - this->reg.trap_state = 1<<31 | 6<<16; + this->trap_state = 1<<31 | 6<<16; fault_data=addr; return iss::Err; } @@ -686,12 +686,12 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc res = write_mem( phys_addr, length, data); } if (unlikely(res != iss::Ok)) { - this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) + this->trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } return res; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -751,7 +751,7 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc } return iss::Ok; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -797,7 +797,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { - auto cycle_val = this->reg.icount + cycle_offset; + auto cycle_val = this->icount + cycle_offset; if (addr == mcycle) { val = static_cast(cycle_val); } else if (addr == mcycleh) { @@ -819,16 +819,16 @@ template iss::status riscv_hart_m_p mcycle_csr = (static_cast(val)<<32) + (mcycle_csr & 0xffffffff); } } - cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around + cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around return iss::Ok; } template iss::status riscv_hart_m_p::read_instret(unsigned addr, reg_t &val) { if ((addr&0xff) == (minstret&0xff)) { - val = static_cast(this->reg.instret); + val = static_cast(this->instret); } else if ((addr&0xff) == (minstreth&0xff)) { if (sizeof(typename traits::reg_t) != 4) return iss::Err; - val = static_cast(this->reg.instret >> 32); + val = static_cast(this->instret >> 32); } return iss::Ok; } @@ -837,20 +837,20 @@ template iss::status riscv_hart_m_p if (sizeof(typename traits::reg_t) != 4) { if ((addr&0xff) == (minstreth&0xff)) return iss::Err; - this->reg.instret = static_cast(val); + this->instret = static_cast(val); } else { if ((addr&0xff) == (minstret&0xff)) { - this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; + this->instret = (this->instret & 0xffffffff00000000) + val; } else { - this->reg.instret = (static_cast(val)<<32) + (this->reg.instret & 0xffffffff); + this->instret = (static_cast(val)<<32) + (this->instret & 0xffffffff); } } - this->reg.instret--; + this->instret--; return iss::Ok; } template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t &val) { - uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; + uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052; if (addr == time) { val = static_cast(time_val); } else if (addr == timeh) { @@ -969,7 +969,7 @@ iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned len 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; + if (this->icount > 30000) data[3] |= 0x80; } break; default: { for(auto offs=0U; offs::write_mem(phys_addr_t paddr, unsigned le LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } - this->reg.trap_state=std::numeric_limits::max(); + this->trap_state=std::numeric_limits::max(); this->interrupt_sim=hostvar; break; //throw(iss::simulation_stopped(hostvar)); @@ -1117,7 +1117,7 @@ template void riscv_hart_m_p::check enabled_interrupts >>= 1; res++; } - this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id + this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id } } @@ -1165,7 +1165,7 @@ template uint64_t riscv_hart_m_p::e fault_data = 0; } else { csr[mepc] = this->reg.NEXT_PC & get_pc_mask(); // store next address if interrupt - this->reg.pending_trap = 0; + this->pending_trap = 0; } csr[mcause] = (trap_id << (traits::XLEN-1)) + cause; // update mstatus @@ -1187,7 +1187,7 @@ template uint64_t riscv_hart_m_p::e if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; // reset trap state this->reg.PRIV = new_priv; - this->reg.trap_state = 0; + this->trap_state = 0; std::array buffer; #if defined(_MSC_VER) sprintf(buffer.data(), "0x%016llx", addr); diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/incl/iss/arch/riscv_hart_msu_vp.h index 607c952..e7c86e0 100644 --- a/incl/iss/arch/riscv_hart_msu_vp.h +++ b/incl/iss/arch/riscv_hart_msu_vp.h @@ -307,7 +307,7 @@ public: void disass_output(uint64_t pc, const std::string instr) override { CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.ccount + cycle_offset); + pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->icount + cycle_offset); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } @@ -610,7 +610,7 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31); // issue trap 0 + this->trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { @@ -629,12 +629,12 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data): read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); if (unlikely(res != iss::Ok)){ - this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault + this->trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; } return res; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -650,7 +650,7 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ case 3: { // SFENCE:VMA upper auto tvm = state.mstatus.TVM; if (this->reg.PRIV == PRIV_S & tvm != 0) { - this->reg.trap_state = (1 << 31) | (2 << 16); + this->trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; } @@ -671,7 +671,7 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ } return iss::Ok; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -709,7 +709,7 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31); // issue trap 0 + this->trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { @@ -728,12 +728,12 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access write_mem(phys_addr_t{access, space, addr}, length, data): write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); if (unlikely(res != iss::Ok)) { - this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) + this->trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } return res; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -782,7 +782,7 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access ptw.clear(); auto tvm = state.mstatus.TVM; if (this->reg.PRIV == PRIV_S & tvm != 0) { - this->reg.trap_state = (1 << 31) | (2 << 16); + this->trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; } @@ -798,7 +798,7 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access } return iss::Ok; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -844,7 +844,7 @@ template iss::status riscv_hart_msu_vp::write_reg(unsigned } template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { - auto cycle_val = this->reg.icount + cycle_offset; + auto cycle_val = this->icount + cycle_offset; if (addr == mcycle) { val = static_cast(cycle_val); } else if (addr == mcycleh) { @@ -866,7 +866,7 @@ template iss::status riscv_hart_m_p::write_cycle(unsigned mcycle_csr = (static_cast(val)<<32) + (mcycle_csr & 0xffffffff); } } - cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around + cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around return iss::Ok; } @@ -897,7 +897,7 @@ template iss::status riscv_hart_m_p::write_instret(unsigne } template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t &val) { - uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; + uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052; if (addr == time) { val = static_cast(time_val); } else if (addr == timeh) { @@ -966,7 +966,7 @@ template iss::status riscv_hart_msu_vp::write_epc(unsigned template iss::status riscv_hart_msu_vp::read_satp(unsigned addr, reg_t &val) { reg_t tvm = state.mstatus.TVM; if (this->reg.PRIV == PRIV_S & tvm != 0) { - this->reg.trap_state = (1 << 31) | (2 << 16); + this->trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; } @@ -977,7 +977,7 @@ template iss::status riscv_hart_msu_vp::read_satp(unsigned template iss::status riscv_hart_msu_vp::write_satp(unsigned addr, reg_t val) { reg_t tvm = state.mstatus.TVM; if (this->reg.PRIV == PRIV_S & tvm != 0) { - this->reg.trap_state = (1 << 31) | (2 << 16); + this->trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; } @@ -1033,7 +1033,7 @@ iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length 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; + if (this->icount > 30000) data[3] |= 0x80; } break; default: { for(auto offs=0U; offs::write_mem(phys_addr_t paddr, unsigned lengt LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } - this->reg.trap_state=std::numeric_limits::max(); + this->trap_state=std::numeric_limits::max(); this->interrupt_sim=hostvar; break; //throw(iss::simulation_stopped(hostvar)); @@ -1162,7 +1162,7 @@ template void riscv_hart_msu_vp::check_interrupt() { if (enabled_interrupts != 0) { int res = 0; while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++; - this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id + this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id } } @@ -1306,7 +1306,7 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f 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; + this->pending_trap = 0; } size_t adr = ucause | (new_priv << 8); csr[adr] = (trap_id << 31) + cause; @@ -1351,7 +1351,7 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f << lvl[cur_priv] << " to " << lvl[new_priv]; // reset trap state this->reg.PRIV = new_priv; - this->reg.trap_state = 0; + this->trap_state = 0; update_vm_info(); return this->reg.NEXT_PC; } @@ -1363,7 +1363,7 @@ template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t f auto tsr = state.mstatus.TSR; if (cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) { - this->reg.trap_state = (1 << 31) | (2 << 16); + this->trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return this->reg.PC; } @@ -1402,7 +1402,7 @@ template void riscv_hart_msu_vp::wait_until(uint64_t flags auto status = state.mstatus; auto tw = status.TW; if (this->reg.PRIV == PRIV_S && tw != 0) { - this->reg.trap_state = (1 << 31) | (2 << 16); + this->trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; } } diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index bd50342..e85f1da 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -218,7 +218,7 @@ public: void disass_output(uint64_t pc, const std::string instr) override { CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset); + pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->icount + cycle_offset); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } @@ -704,20 +704,20 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1 + this->trap_state = (1 << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1 return iss::Err; } } if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31); // issue trap 0 + this->trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { auto alignment = access == iss::access_type::FETCH? (traits::MISA_VAL&0x100? 2 : 4) : length; if(alignment>1 && (addr&(alignment-1))){ - this->reg.trap_state = 1<<31 | 4<<16; + this->trap_state = 1<<31 | 4<<16; fault_data=addr; return iss::Err; } @@ -736,12 +736,12 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc res = read_mem( phys_addr, length, data); } if (unlikely(res != iss::Ok)){ - this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault + this->trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; } return res; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -767,7 +767,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc } return iss::Ok; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -806,19 +806,19 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 1 + this->trap_state = (1 << 31) | (7 << 16); // issue trap 1 return iss::Err; } } if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->reg.trap_state = (1 << 31); // issue trap 0 + this->trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ - this->reg.trap_state = 1<<31 | 6<<16; + this->trap_state = 1<<31 | 6<<16; fault_data=addr; return iss::Err; } @@ -837,12 +837,12 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac res = write_mem( phys_addr, length, data); } if (unlikely(res != iss::Ok)) { - this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) + this->trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } return res; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -902,7 +902,7 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac } return iss::Ok; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -948,7 +948,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_cycle(unsigned addr, reg_t &val) { - auto cycle_val = this->reg.icount + cycle_offset; + auto cycle_val = this->icount + cycle_offset; if (addr == mcycle) { val = static_cast(cycle_val); } else if (addr == mcycleh) { @@ -970,16 +970,16 @@ template iss::status riscv_hart_mu_p(val)<<32) + (mcycle_csr & 0xffffffff); } } - cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around + cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around return iss::Ok; } template iss::status riscv_hart_mu_p::read_instret(unsigned addr, reg_t &val) { if ((addr&0xff) == (minstret&0xff)) { - val = static_cast(this->reg.instret); + val = static_cast(this->instret); } else if ((addr&0xff) == (minstreth&0xff)) { if (sizeof(typename traits::reg_t) != 4) return iss::Err; - val = static_cast(this->reg.instret >> 32); + val = static_cast(this->instret >> 32); } return iss::Ok; } @@ -988,20 +988,20 @@ template iss::status riscv_hart_mu_p::reg_t) != 4) { if ((addr&0xff) == (minstreth&0xff)) return iss::Err; - this->reg.instret = static_cast(val); + this->instret = static_cast(val); } else { if ((addr&0xff) == (minstret&0xff)) { - this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; + this->instret = (this->instret & 0xffffffff00000000) + val; } else { - this->reg.instret = (static_cast(val)<<32) + (this->reg.instret & 0xffffffff); + this->instret = (static_cast(val)<<32) + (this->instret & 0xffffffff); } } - this->reg.instret--; + this->instret--; return iss::Ok; } template iss::status riscv_hart_mu_p::read_time(unsigned addr, reg_t &val) { - uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; + uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052; if (addr == time) { val = static_cast(time_val); } else if (addr == timeh) { @@ -1137,7 +1137,7 @@ iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned le 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; + if (this->icount > 30000) data[3] |= 0x80; } break; default: { for(auto offs=0U; offs::write_mem(phys_addr_t paddr, unsigned l LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } - this->reg.trap_state=std::numeric_limits::max(); + this->trap_state=std::numeric_limits::max(); this->interrupt_sim=hostvar; break; //throw(iss::simulation_stopped(hostvar)); @@ -1284,14 +1284,14 @@ template void riscv_hart_mu_p::chec enabled_interrupts >>= 1; res++; } - this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id + this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id } } template uint64_t riscv_hart_mu_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val - if(flags==std::numeric_limits::max()) flags=this->reg.trap_state; + if(flags==std::numeric_limits::max()) flags=this->trap_state; auto trap_id = bit_sub<0, 16>(flags); auto cause = bit_sub<16, 15>(flags); if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause @@ -1338,7 +1338,7 @@ template uint64_t riscv_hart_mu_p:: if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) new_priv = PRIV_U; csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt - this->reg.pending_trap = 0; + this->pending_trap = 0; } size_t adr = ucause | (new_priv << 8); csr[adr] = (trap_id << (traits::XLEN-1)) + cause; @@ -1378,7 +1378,7 @@ template uint64_t riscv_hart_mu_p:: << lvl[this->reg.PRIV] << " to " << lvl[new_priv]; // reset trap state this->reg.PRIV = new_priv; - this->reg.trap_state = 0; + this->trap_state = 0; return this->reg.NEXT_PC; } @@ -1387,7 +1387,7 @@ template uint64_t riscv_hart_mu_p:: auto inst_priv = (flags & 0x3)? 3:0; if(inst_priv>cur_priv){ auto trap_val = 0x80ULL << 24 | (2 << 16); // illegal instruction - this->reg.trap_state = trap_val; + this->trap_state = trap_val; this->reg.NEXT_PC = std::numeric_limits::max(); } else { auto status = state.mstatus; diff --git a/incl/iss/arch/tgc_c.h b/incl/iss/arch/tgc_c.h index 9640ae9..7a71f8c 100644 --- a/incl/iss/arch/tgc_c.h +++ b/incl/iss/arch/tgc_c.h @@ -58,13 +58,7 @@ template <> struct traits { constexpr static unsigned FP_REGS_SIZE = 0; enum reg_e { - X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, - TRAP_STATE=NUM_REGS, - PENDING_TRAP, - ICOUNT, - CYCLE, - INSTRET, - INSTRUCTION + 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, NEXT_PC, PRIV, DPC, NUM_REGS }; using reg_t = uint32_t; @@ -77,11 +71,11 @@ template <> struct traits { using phys_addr_t = iss::typed_addr_t; - static constexpr std::array reg_bit_widths{ - {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64,32}}; + static constexpr std::array reg_bit_widths{ + {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32}}; - static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165,173}}; + static constexpr std::array reg_byte_offsets{ + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); @@ -198,7 +192,7 @@ struct tgc_c: public arch_if { uint8_t* get_regs_base_ptr() override; - inline uint64_t get_icount() { return reg.icount; } + inline uint64_t get_icount() { return icount; } inline bool should_stop() { return interrupt_sim; } @@ -216,7 +210,7 @@ struct tgc_c: public arch_if { virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } - inline uint32_t get_last_branch() { return reg.last_branch; } + inline uint32_t get_last_branch() { return last_branch; } #pragma pack(push, 1) @@ -257,12 +251,13 @@ struct tgc_c: public arch_if { uint32_t NEXT_PC = 0; uint8_t PRIV = 0; uint32_t DPC = 0; - uint32_t trap_state = 0, pending_trap = 0; - uint64_t icount = 0; - uint64_t instret = 0; - uint32_t instruction = 0; - uint32_t last_branch; } reg; + uint32_t trap_state = 0, pending_trap = 0; + uint64_t icount = 0; + uint64_t cycle = 0; + uint64_t instret = 0; + uint32_t instruction = 0; + uint32_t last_branch = 0; #pragma pack(pop) std::array addr_mode; diff --git a/src/iss/tgc_c.cpp b/src/iss/tgc_c.cpp index 3c6fcd0..35a27d0 100644 --- a/src/iss/tgc_c.cpp +++ b/src/iss/tgc_c.cpp @@ -41,12 +41,10 @@ using namespace iss::arch; constexpr std::array iss::arch::traits::reg_names; constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; -tgc_c::tgc_c() { - reg.icount = 0; -} +tgc_c::tgc_c() = default; tgc_c::~tgc_c() = default; @@ -57,8 +55,8 @@ void tgc_c::reset(uint64_t address) { reg.PC=address; reg.NEXT_PC=reg.PC; reg.PRIV=0x3; - reg.trap_state=0; - reg.icount=0; + trap_state=0; + icount=0; } uint8_t *tgc_c::get_regs_base_ptr() { diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp index 4c6ea1a..036b4cc 100644 --- a/src/plugin/pctrace.cpp +++ b/src/plugin/pctrace.cpp @@ -126,7 +126,8 @@ void iss::plugin::cov::callback(instr_info_t iinfo, const exec_info& einfo) { auto delay = 0; size_t id = iinfo.instr_id; auto entry = delays[id]; - auto call = (id==2 || id==3) && bit_sub<7,5>(instr_if->get_instr_word())!=0; + auto instr = instr_if->get_instr_word(); + auto call = (id==2 || id==3) && bit_sub<7,5>(instr)!=0; bool taken = einfo.branch_taken; if (einfo.branch_taken) delay = entry.taken; diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index f7b95c7..53ff0cb 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -105,7 +105,7 @@ public: heart_state_t &get_state() { return this->state; } void notify_phase(iss::arch_if::exec_phase p) override { - if (p == iss::arch_if::ISTART) owner->sync(this->reg.icount); + if (p == iss::arch_if::ISTART) owner->sync(this->icount); } sync_type needed_sync() const override { return PRE_SYNC; } @@ -115,7 +115,7 @@ public: std::stringstream s; s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" - << this->reg.icount + this->cycle_offset << "]"; + << this->icount + this->cycle_offset << "]"; SCCDEBUG(owner->name())<<"disass: " << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) << std::setfill(' ') << std::left << instr << s.str(); @@ -175,7 +175,7 @@ public: void wait_until(uint64_t flags) override { SCCDEBUG(owner->name()) << "Sleeping until interrupt"; - while(this->reg.pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) { + while(this->pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) { sc_core::wait(wfi_evt); } PLAT::wait_until(flags); @@ -204,7 +204,7 @@ public: this->csr[arch::mip] &= ~mask; this->check_interrupt(); if(value) - SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap; + SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->pending_trap; } private: diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 435389d..1da214b 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -115,7 +115,7 @@ protected: inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; - this->template get_reg(traits::TRAP_STATE) = trap_val; + this->core.trap_state = trap_val; this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); } @@ -135,39 +135,39 @@ protected: T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; return ret; } inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){ auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; return ret; } inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){ auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; return ret; } inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){ auto ret = super::template read_mem(space, addr); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; return ret; } inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){ super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; } inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){ super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; } inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){ super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; } inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){ super::write_mem(space, addr, data); - if(this->template get_reg(traits::TRAP_STATE)) throw 0; + if(this->core.trap_state) throw 0; } template::type> inline S sext(U from) { @@ -359,16 +359,15 @@ typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ auto pc=start; - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); - auto* icount = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]); - auto* instret = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]); - auto *const instruction = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRUCTION]); + auto& trap_state = this->core.trap_state; + auto& icount = this->core.icount; + auto& cycle = this->core.cycle; + auto& instret = this->core.instret; + auto& instr = this->core.instruction; // we fetch at max 4 byte, alignment is 2 - auto *const data = reinterpret_cast(instruction); - auto& instr = *instruction; + auto *const data = reinterpret_cast(&instr); while(!this->core.should_stop() && !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ @@ -2409,16 +2408,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); // trap check - if(*trap_state!=0){ - super::core.enter_trap(*trap_state, pc.val, instr); + if(trap_state!=0){ + super::core.enter_trap(trap_state, pc.val, instr); } else { - (*icount)++; - (*instret)++; + icount++; + instret++; } - (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; + cycle++; pc.val=*NEXT_PC; this->core.reg.PC = this->core.reg.NEXT_PC; - this->core.reg.trap_state = this->core.reg.pending_trap; + this->core.trap_state = this->core.pending_trap; } } return pc; From 03bec27376adf9de7dff376c6db5f260b5ba765f Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 26 Apr 2022 17:14:33 +0200 Subject: [PATCH 004/184] implement extended instrumentation interface --- incl/iss/arch/riscv_hart_m_p.h | 4 +++- incl/iss/arch/riscv_hart_msu_vp.h | 8 ++++++-- incl/iss/arch/riscv_hart_mu_p.h | 8 ++++++-- incl/iss/arch/tgc_c.h | 2 +- src/vm/interp/vm_tgc_c.cpp | 16 ++++++++-------- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index 52bf1ad..09d9864 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -241,7 +241,9 @@ protected: uint64_t get_instr_word() override { return arch.instruction; } - uint64_t get_instr_count() { return arch.icount; } + uint64_t get_instr_count() override { return arch.icount; } + + uint64_t get_pendig_traps() override { return arch.trap_state; } uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/incl/iss/arch/riscv_hart_msu_vp.h index e7c86e0..ed2e677 100644 --- a/incl/iss/arch/riscv_hart_msu_vp.h +++ b/incl/iss/arch/riscv_hart_msu_vp.h @@ -340,9 +340,13 @@ protected: virtual uint64_t get_next_pc() { return arch.get_next_pc(); }; - uint64_t get_instr_count() { return arch.reg.icount; } + uint64_t get_instr_word() override { return arch.instruction; } - uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } + uint64_t get_instr_count() { return arch.icount; } + + uint64_t get_pendig_traps() override { return arch.trap_state; } + + uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index e85f1da..440664e 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -254,9 +254,13 @@ protected: virtual uint64_t get_next_pc() { return arch.get_next_pc(); }; - uint64_t get_instr_count() { return arch.reg.icount; } + uint64_t get_instr_word() override { return arch.instruction; } - uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } + uint64_t get_instr_count() { return arch.icount; } + + uint64_t get_pendig_traps() override { return arch.trap_state; } + + uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; diff --git a/incl/iss/arch/tgc_c.h b/incl/iss/arch/tgc_c.h index 7a71f8c..5ff88a3 100644 --- a/incl/iss/arch/tgc_c.h +++ b/incl/iss/arch/tgc_c.h @@ -53,7 +53,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; - enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, RFS=32, XLEN=32, CSR_SIZE=4096, INSTR_ALIGNMENT=2, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; + enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, RFS=32, INSTR_ALIGNMENT=2, XLEN=32, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; constexpr static unsigned FP_REGS_SIZE = 0; diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 1da214b..b366450 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -2001,7 +2001,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint32_t rs1_idx = rs1 + 8; + uint8_t rs1_idx = rs1 + 8; *(X+rs1_idx) = *(X+rs1_idx) >> shamt; } } catch(...){} @@ -2024,11 +2024,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { if(shamt) { - uint32_t rs1_idx = rs1 + 8; + uint8_t rs1_idx = rs1 + 8; *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; } else if(traits::XLEN == 128) { - uint32_t rs1_idx = rs1 + 8; + uint8_t rs1_idx = rs1 + 8; *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; } } catch(...){} @@ -2051,7 +2051,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint32_t rs1_idx = rs1 + 8; + uint8_t rs1_idx = rs1 + 8; *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm); } } catch(...){} @@ -2074,7 +2074,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint32_t rd_idx = rd + 8; + uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) - *(X+rs2 + 8); } } catch(...){} @@ -2097,7 +2097,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint32_t rd_idx = rd + 8; + uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) ^ *(X+rs2 + 8); } } catch(...){} @@ -2120,7 +2120,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint32_t rd_idx = rd + 8; + uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) | *(X+rs2 + 8); } } catch(...){} @@ -2143,7 +2143,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint32_t rd_idx = rd + 8; + uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) & *(X+rs2 + 8); } } catch(...){} From e88f309ea2cfe59bffa8414fbfbb6b4478aebb3f Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 7 May 2022 17:22:06 +0200 Subject: [PATCH 005/184] add lz4 compression to pctrace --- CMakeLists.txt | 4 + gen_input/templates/CORENAME.h.gtl | 2 +- incl/iss/arch/tgc_c.h | 2 +- incl/iss/plugin/pctrace.h | 9 +- src/main.cpp | 4 +- src/plugin/pctrace.cpp | 153 ++++++++++++++++++----------- 6 files changed, 108 insertions(+), 66 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28ba1da..e676292 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,10 @@ elseif(TARGET elfio::elfio) else() message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing") endif() +if(TARGET lz4::lz4) + target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_LZ4) + target_link_libraries(${PROJECT_NAME} PUBLIC lz4::lz4) +endif() if(TARGET RapidJSON) target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON) endif() diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 4497ba3..1765fde 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -163,13 +163,13 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { uint${byteSize(reg.size)}_t ${reg.name} = 0;<% }}%> } reg; +#pragma pack(pop) uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; uint64_t cycle = 0; uint64_t instret = 0; uint32_t instruction = 0; uint32_t last_branch = 0; -#pragma pack(pop) std::array addr_mode; uint64_t interrupt_sim=0; diff --git a/incl/iss/arch/tgc_c.h b/incl/iss/arch/tgc_c.h index 5ff88a3..8e2ae8a 100644 --- a/incl/iss/arch/tgc_c.h +++ b/incl/iss/arch/tgc_c.h @@ -252,13 +252,13 @@ struct tgc_c: public arch_if { uint8_t PRIV = 0; uint32_t DPC = 0; } reg; +#pragma pack(pop) uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; uint64_t cycle = 0; uint64_t instret = 0; uint32_t instruction = 0; uint32_t last_branch = 0; -#pragma pack(pop) std::array addr_mode; uint64_t interrupt_sim=0; diff --git a/incl/iss/plugin/pctrace.h b/incl/iss/plugin/pctrace.h index d227666..446094b 100644 --- a/incl/iss/plugin/pctrace.h +++ b/incl/iss/plugin/pctrace.h @@ -44,7 +44,7 @@ namespace iss { namespace plugin { - +class lz4compress_steambuf; class cov : public iss::vm_plugin { struct instr_delay { std::string instr_name; @@ -88,10 +88,13 @@ public: private: iss::instrumentation_if *instr_if {nullptr}; std::ofstream output; +#ifdef WITH_LZ4 + std::unique_ptr strbuf; + std::ostream ostr; +#endif std::string filename; std::vector delays; - bool jumped, first; - + bool jumped{false}, first{true}; }; } } diff --git a/src/main.cpp b/src/main.cpp index bbde374..d8d6bd6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,13 +60,13 @@ int main(int argc, char *argv[]) { desc.add_options() ("help,h", "Print help message") ("verbose,v", po::value()->implicit_value(0), "Sets logging verbosity") - ("logfile,f", po::value(), "Sets default log file.") + ("logfile,l", po::value(), "Sets default log file.") ("disass,d", po::value()->implicit_value(""), "Enables disassembly") ("gdb-port,g", po::value()->default_value(0), "enable gdb server and specify port to use") ("instructions,i", po::value()->default_value(std::numeric_limits::max()), "max. number of instructions to simulate") ("reset,r", po::value(), "reset address") ("dump-ir", "dump the intermediate representation") - ("elf", po::value>(), "ELF file(s) to load") + ("elf,f", po::value>(), "ELF file(s) to load") ("mem,m", po::value(), "the memory input file") ("plugin,p", po::value>(), "plugin to activate") ("backend", po::value()->default_value("interp"), "the memory input file") diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp index 036b4cc..f14e8fd 100644 --- a/src/plugin/pctrace.cpp +++ b/src/plugin/pctrace.cpp @@ -9,27 +9,97 @@ #include #include #include - #include +#include +namespace iss { +namespace plugin { + using namespace rapidjson; using namespace std; -iss::plugin::cov::cov(std::string const &filename) - : instr_if(nullptr) - , filename(filename) -{ - output.open("output.trc"); - jumped = false; - first = true; -} +class lz4compress_steambuf: public std::streambuf { +public: + lz4compress_steambuf(const lz4compress_steambuf&) = delete; + lz4compress_steambuf& operator=(const lz4compress_steambuf&) = delete; + lz4compress_steambuf(std::ostream &sink, size_t buf_size) + : sink(sink) + , src_buf(buf_size) + , dest_buf(LZ4F_compressBound(buf_size, nullptr)) + { + auto errCode = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION); + if (LZ4F_isError(errCode) != 0) + throw std::runtime_error(std::string("Failed to create LZ4 context: ") + LZ4F_getErrorName(errCode)); + size_t ret = LZ4F_compressBegin(ctx, &dest_buf.front(), dest_buf.capacity(), nullptr); + if (LZ4F_isError(ret) != 0) + throw std::runtime_error(std::string("Failed to start LZ4 compression: ") + LZ4F_getErrorName(ret)); + setp(src_buf.data(), src_buf.data() + src_buf.size() - 1); + sink.write(dest_buf.data(), ret); + } -iss::plugin::cov::~cov() { - output.close(); -} + ~lz4compress_steambuf() { + close(); + } -bool iss::plugin::cov::registration(const char *const version, vm_if& vm) { + void close() { + if (closed) + return; + sync(); + auto ret = LZ4F_compressEnd(ctx, dest_buf.data(), dest_buf.capacity(), nullptr); + if (LZ4F_isError(ret) != 0) + throw std::runtime_error(std::string("Failed to finish LZ4 compression: ") + LZ4F_getErrorName(ret)); + sink.write(dest_buf.data(), ret); + LZ4F_freeCompressionContext(ctx); + closed = true; + } + +private: + int_type overflow(int_type ch) override { + assert(pptr() <= epptr()); + *pptr() = static_cast(ch); + pbump(1); + compress_and_write(); + return ch; + } + + int_type sync() override { + compress_and_write(); + return 0; + } + + void compress_and_write() { + if (closed) + throw std::runtime_error("Cannot write to closed stream"); + if(auto orig_size = pptr() - pbase()){ + auto ret = LZ4F_compressUpdate(ctx, dest_buf.data(), dest_buf.capacity(), pbase(), orig_size, nullptr); + if (LZ4F_isError(ret) != 0) + throw std::runtime_error(std::string("LZ4 compression failed: ") + LZ4F_getErrorName(ret)); + if(ret) sink.write(dest_buf.data(), ret); + pbump(-orig_size); + } + } + + std::ostream &sink; + std::vector src_buf; + std::vector dest_buf; + LZ4F_compressionContext_t ctx{ nullptr }; + bool closed{ false }; +}; + +cov::cov(std::string const &filename) +: instr_if(nullptr) +, filename(filename) +, output("output.trc") +#ifdef WITH_LZ4 +, strbuf(new lz4compress_steambuf(output, 4096)) +, ostr(strbuf.get()) +#endif +{ } + +cov::~cov() { } + +bool cov::registration(const char *const version, vm_if& vm) { instr_if = vm.get_arch()->get_instrumentation_if(); if(!instr_if) return false; const string core_name = instr_if->core_type_name(); @@ -63,11 +133,11 @@ bool iss::plugin::cov::registration(const char *const version, vm_if& vm) { } else { LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<get_pc()) << "," << delay; -// first = false; -// } -// if(instr_if->get_next_pc()-instr_if->get_pc() != delays[iinfo.instr_id].size/8){ -// //The goal is to keep the output in start-target pairs, so after a jump the target address needs to get written -// //to the output. If the target happens to also be a start, we keep the pairing by adding a 0-delay entry. -// if (jumped) -// output <<"\n" <get_pc()) << "," << 0; -// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay; -// jumped = true; -// } -// else{ -// if (jumped){ -// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay; -// jumped = false; -// } -// else if(delay!=1){ -// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay; -// output <<"\n" << formatPC(instr_if->get_pc()) << "," << 0; -// } -// -// } - -//source code for the full output +void cov::callback(instr_info_t iinfo, const exec_info& einfo) { auto delay = 0; size_t id = iinfo.instr_id; auto entry = delays[id]; @@ -132,6 +160,13 @@ void iss::plugin::cov::callback(instr_info_t iinfo, const exec_info& einfo) { if (einfo.branch_taken) delay = entry.taken; else - delay = entry.not_taken; + delay = entry.not_taken; +#ifndef WITH_LZ4 output<get_pc() <<"," << delay << "\n"; +#else + auto rdbuf=ostr.rdbuf(); + ostr<get_pc() <<"," << delay << "\n"; +#endif +} +} } From e56bc1278824b44db92d79b0fe09b7b3377d79af Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 7 May 2022 17:25:11 +0200 Subject: [PATCH 006/184] fix non-lz4 build of plugin --- src/plugin/pctrace.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp index f14e8fd..8fa5ef7 100644 --- a/src/plugin/pctrace.cpp +++ b/src/plugin/pctrace.cpp @@ -10,8 +10,9 @@ #include #include #include +#ifdef WITH_LZ4 #include - +#endif namespace iss { namespace plugin { @@ -19,6 +20,7 @@ namespace plugin { using namespace rapidjson; using namespace std; +#ifdef WITH_LZ4 class lz4compress_steambuf: public std::streambuf { public: lz4compress_steambuf(const lz4compress_steambuf&) = delete; @@ -86,6 +88,7 @@ private: LZ4F_compressionContext_t ctx{ nullptr }; bool closed{ false }; }; +#endif cov::cov(std::string const &filename) : instr_if(nullptr) From 6579780dc96f84b506e085ee936aaae6c9a16351 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sun, 8 May 2022 15:24:26 +0200 Subject: [PATCH 007/184] add call column in output --- src/plugin/pctrace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp index 036b4cc..1134f56 100644 --- a/src/plugin/pctrace.cpp +++ b/src/plugin/pctrace.cpp @@ -133,5 +133,5 @@ void iss::plugin::cov::callback(instr_info_t iinfo, const exec_info& einfo) { delay = entry.taken; else delay = entry.not_taken; - output<get_pc() <<"," << delay << "\n"; + output<get_pc() <<"," << delay <<"," << call<< "\n"; } From 9db4e3fd877d06d93e4c1fb7e4d0cc073990a98b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 10 May 2022 16:13:21 +0200 Subject: [PATCH 008/184] fix assertion --- src/plugin/pctrace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp index 3f72708..ef10ded 100644 --- a/src/plugin/pctrace.cpp +++ b/src/plugin/pctrace.cpp @@ -58,7 +58,7 @@ public: private: int_type overflow(int_type ch) override { - assert(pptr() <= epptr()); + assert(pptr() > epptr()); *pptr() = static_cast(ch); pbump(1); compress_and_write(); From e382217e049a0fe3f840997d7534b3ba90714425 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 11 May 2022 18:52:15 +0200 Subject: [PATCH 009/184] update vm_tgc_c due reworked CoreDSL generator --- src/vm/interp/vm_tgc_c.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index b366450..f6605ee 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -1921,7 +1921,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - if((rd % traits::RFS) != 0) *(X+rd) = (uint32_t)(int32_t)sext<6>(imm); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int8_t)sext<6>(imm); } } catch(...){} } From 5da4e6b424c3e6d348fa6bc275235559734ce900 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 13 May 2022 12:37:47 +0200 Subject: [PATCH 010/184] fix alignment check for unaligned debugger accesses --- incl/iss/arch/riscv_hart_m_p.h | 10 +++++----- incl/iss/arch/riscv_hart_msu_vp.h | 8 +++++++- incl/iss/arch/riscv_hart_mu_p.h | 12 ++++++------ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index 09d9864..c0059b2 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -567,22 +567,22 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce try { switch (space) { case traits::MEM: { - if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) { + auto alignment = is_fetch(access)? (traits::MISA_VAL&0x100? 2 : 4) : length; + if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); + if (is_debug(access)) throw trap_access(0, addr); this->trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { - auto alignment = access == iss::access_type::FETCH? (traits::MISA_VAL&0x100? 2 : 4) : length; - if(alignment>1 && (addr&(alignment-1))){ + if(!is_debug(access) && (addr&(alignment-1))){ this->trap_state = 1<<31 | 4<<16; fault_data=addr; return iss::Err; } auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); auto res = iss::Err; - if(access != access_type::FETCH && memfn_range.size()){ + if(!is_fetch(access) && memfn_range.size()){ auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; }); diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/incl/iss/arch/riscv_hart_msu_vp.h index ed2e677..a742d08 100644 --- a/incl/iss/arch/riscv_hart_msu_vp.h +++ b/incl/iss/arch/riscv_hart_msu_vp.h @@ -611,13 +611,19 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ try { switch (space) { case traits::MEM: { - if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) { + auto alignment = is_fetch(access)? (traits::MISA_VAL&0x100? 2 : 4) : length; + if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); this->trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { + if(!is_debug(access) && (addr&(alignment-1))){ + this->trap_state = 1<<31 | 4<<16; + fault_data=addr; + return iss::Err; + } if (unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary vm_info vm = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp); if (vm.levels != 0) { // VM is active diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index 440664e..1cf8484 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -705,22 +705,22 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc switch (space) { case traits::MEM: { if(FEAT & FEAT_PMP){ - if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) { + if(!pmp_check(access, addr, length) && !is_debug(access)) { fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); + if (is_debug(access)) throw trap_access(0, addr); this->trap_state = (1 << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1 return iss::Err; } } - if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) { + auto alignment = is_fetch(access)? (traits::MISA_VAL&0x100? 2 : 4) : length; + if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); + if (is_debug(access)) throw trap_access(0, addr); this->trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { - auto alignment = access == iss::access_type::FETCH? (traits::MISA_VAL&0x100? 2 : 4) : length; - if(alignment>1 && (addr&(alignment-1))){ + if(!is_debug(access) && (addr&(alignment-1))){ this->trap_state = 1<<31 | 4<<16; fault_data=addr; return iss::Err; From 766f3ba9ee7fe8126dde5a27dc16db6d2854c637 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 13 May 2022 12:38:12 +0200 Subject: [PATCH 011/184] fix assertion in compressed pctrace writer --- src/plugin/pctrace.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp index ef10ded..2f4db3e 100644 --- a/src/plugin/pctrace.cpp +++ b/src/plugin/pctrace.cpp @@ -58,10 +58,9 @@ public: private: int_type overflow(int_type ch) override { - assert(pptr() > epptr()); + compress_and_write(); *pptr() = static_cast(ch); pbump(1); - compress_and_write(); return ch; } From 1438f0f373bf156413b1bfb6b03b1f04c2463aa0 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 17 May 2022 15:29:04 +0200 Subject: [PATCH 012/184] add backannotation to pc trace plugin --- incl/iss/plugin/cycle_estimate.h | 2 +- src/plugin/cycle_estimate.cpp | 14 +++++++------- src/plugin/pctrace.cpp | 9 +++++++-- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/incl/iss/plugin/cycle_estimate.h b/incl/iss/plugin/cycle_estimate.h index 0c2cc15..a8345f5 100644 --- a/incl/iss/plugin/cycle_estimate.h +++ b/incl/iss/plugin/cycle_estimate.h @@ -81,7 +81,7 @@ public: void callback(instr_info_t instr_info, exec_info const&) override; private: - iss::instrumentation_if *arch_instr; + iss::instrumentation_if *instr_if; std::vector delays; struct pair_hash { size_t operator()(const std::pair &p) const { diff --git a/src/plugin/cycle_estimate.cpp b/src/plugin/cycle_estimate.cpp index f68d241..553a772 100644 --- a/src/plugin/cycle_estimate.cpp +++ b/src/plugin/cycle_estimate.cpp @@ -48,7 +48,7 @@ using namespace rapidjson; using namespace std; iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name) -: arch_instr(nullptr) +: instr_if(nullptr) , config_file_name(config_file_name) { } @@ -57,9 +57,9 @@ iss::plugin::cycle_estimate::~cycle_estimate() { } bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& vm) { - arch_instr = vm.get_arch()->get_instrumentation_if(); - if(!arch_instr) return false; - const string core_name = arch_instr->core_type_name(); + instr_if = vm.get_arch()->get_instrumentation_if(); + if(!instr_if) return false; + const string core_name = instr_if->core_type_name(); if (config_file_name.length() > 0) { ifstream is(config_file_name); if (is.is_open()) { @@ -108,11 +108,11 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& } void iss::plugin::cycle_estimate::callback(instr_info_t instr_info, exec_info const& exc_info) { - assert(arch_instr && "No instrumentation interface available but callback executed"); + assert(instr_if && "No instrumentation interface available but callback executed"); auto entry = delays[instr_info.instr_id]; bool taken = exc_info.branch_taken; if (exc_info.branch_taken && (entry.taken > 1)) - arch_instr->set_curr_instr_cycles(entry.taken); + instr_if->set_curr_instr_cycles(entry.taken); else if (entry.not_taken > 1) - arch_instr->set_curr_instr_cycles(entry.not_taken); + instr_if->set_curr_instr_cycles(entry.not_taken); } diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp index 2f4db3e..d3d099b 100644 --- a/src/plugin/pctrace.cpp +++ b/src/plugin/pctrace.cpp @@ -159,10 +159,15 @@ void cov::callback(instr_info_t iinfo, const exec_info& einfo) { auto instr = instr_if->get_instr_word(); auto call = (id==2 || id==3) && bit_sub<7,5>(instr)!=0; bool taken = einfo.branch_taken; - if (einfo.branch_taken) + if (einfo.branch_taken) { delay = entry.taken; - else + if(entry.taken > 1) + instr_if->set_curr_instr_cycles(entry.taken); + } else { delay = entry.not_taken; + if (entry.not_taken > 1) + instr_if->set_curr_instr_cycles(entry.not_taken); + } #ifndef WITH_LZ4 output<get_pc() <<"," << delay <<"," << call<< "\n"; #else From df16378605ac71a296cc645ea805fd5e70cddb7a Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 18 May 2022 19:10:34 +0200 Subject: [PATCH 013/184] update template for changed code generator --- gen_input/templates/interp/CORENAME.cpp.gtl | 6 +- src/vm/interp/vm_tgc_c.cpp | 1132 ++++++++++--------- 2 files changed, 615 insertions(+), 523 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 76449f6..f0cb153 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -314,11 +314,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co <%}}%>// calculate next pc value *NEXT_PC = *PC + ${instr.length/8}; // execute instruction - try { <%instr.behavior.eachLine{%>${it} - <%}%>} catch(...){} - } - break;<%}%> + <%}%>TRAP_${instr.name}:break; + }// @suppress("No break at end of case")<%}%> default: { *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); raise(0, 2); diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index f6605ee..0e1ad99 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -396,11 +396,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)imm; - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)imm; + } + } + TRAP_LUI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::AUIPC: { uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,20>(instr) << 12)); @@ -416,11 +418,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + (int32_t)imm; - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *PC + (int32_t)imm; + } + } + TRAP_AUIPC:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::JAL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); @@ -436,19 +440,20 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { if(imm % traits::INSTR_ALIGNMENT) { raise(0, 0); } else { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + 4; - pc_assign(*NEXT_PC) = *PC + (int32_t)sext<21>(imm); + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *PC + 4; + } + *NEXT_PC = *PC + (int32_t)sext<21>(imm); + super::ex_info.branch_taken=true; } } - } catch(...){} - } - break; + TRAP_JAL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::JALR: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -465,20 +470,21 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { int32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 1; if(new_pc % traits::INSTR_ALIGNMENT) { raise(0, 0); } else { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + 4; - pc_assign(*NEXT_PC) = new_pc & ~ 0x1; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *PC + 4; + } + *NEXT_PC = new_pc & ~ 0x1; + super::ex_info.branch_taken=true; } } - } catch(...){} - } - break; + TRAP_JALR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BEQ: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -495,18 +501,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } } } - } catch(...){} - } - break; + TRAP_BEQ:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BNE: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -523,18 +530,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } } } - } catch(...){} - } - break; + TRAP_BNE:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BLT: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -551,18 +559,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } } } - } catch(...){} - } - break; + TRAP_BLT:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BGE: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -579,18 +588,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } } } - } catch(...){} - } - break; + TRAP_BGE:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BLTU: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -607,18 +617,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } } } - } catch(...){} - } - break; + TRAP_BLTU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BGEU: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -635,18 +646,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } } } - } catch(...){} - } - break; + TRAP_BGEU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::LB: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -663,14 +675,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - int8_t res = (int8_t)readSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; + int8_t res = (int8_t)super::template read_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); + if(this->core.trap_state) goto TRAP_LB; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = res; + } } - } catch(...){} - } - break; + TRAP_LB:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::LH: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -687,15 +700,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - int16_t res = (int16_t)readSpace2(traits::MEM, load_address); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; + int16_t res = (int16_t)super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state) goto TRAP_LH; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = res; + } } - } catch(...){} - } - break; + TRAP_LH:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::LW: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -712,15 +726,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - int32_t res = (int32_t)readSpace4(traits::MEM, load_address); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (uint32_t)res; + int32_t res = (int32_t)super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state) goto TRAP_LW; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (uint32_t)res; + } } - } catch(...){} - } - break; + TRAP_LW:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::LBU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -737,14 +752,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - uint8_t res = (uint8_t)readSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; + uint8_t res = (uint8_t)super::template read_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); + if(this->core.trap_state) goto TRAP_LBU; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = res; + } } - } catch(...){} - } - break; + TRAP_LBU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::LHU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -761,15 +777,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - uint16_t res = (uint16_t)readSpace2(traits::MEM, load_address); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; + uint16_t res = (uint16_t)super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state) goto TRAP_LHU; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = res; + } } - } catch(...){} - } - break; + TRAP_LHU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SB: { uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -786,11 +803,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - writeSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm), (int8_t)*(X+rs2 % traits::RFS)); - } catch(...){} - } - break; + { + super::template write_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm), (int8_t)*(X+rs2 % traits::RFS)); + if(this->core.trap_state) goto TRAP_SB; + } + TRAP_SB:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SH: { uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -807,14 +825,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - writeSpace2(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); + super::template write_mem(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); + if(this->core.trap_state) goto TRAP_SH; } - } catch(...){} - } - break; + TRAP_SH:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SW: { uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -831,14 +848,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - writeSpace4(traits::MEM, store_address, *(X+rs2 % traits::RFS)); + super::template write_mem(traits::MEM, store_address, *(X+rs2 % traits::RFS)); + if(this->core.trap_state) goto TRAP_SW; } - } catch(...){} - } - break; + TRAP_SW:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::ADDI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -855,11 +871,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + } + } + TRAP_ADDI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLTI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -876,11 +894,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm)? 1 : 0; - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm)? 1 : 0; + } + } + TRAP_SLTI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLTIU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -897,11 +917,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; + } + } + TRAP_SLTIU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::XORI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -918,11 +940,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm); + } + } + TRAP_XORI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::ORI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -939,11 +963,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm); + } + } + TRAP_ORI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::ANDI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -960,11 +986,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm); + } + } + TRAP_ANDI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLLI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -981,16 +1009,18 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << shamt; - } - } catch(...){} - } - break; + { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << shamt; + } + } + } + TRAP_SLLI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SRLI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1007,16 +1037,18 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> shamt; - } - } catch(...){} - } - break; + { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> shamt; + } + } + } + TRAP_SRLI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SRAI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1033,16 +1065,18 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; - } - } catch(...){} - } - break; + { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; + } + } + } + TRAP_SRAI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::ADD: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1059,11 +1093,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS); + } + } + TRAP_ADD:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SUB: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1080,11 +1116,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS); + } + } + TRAP_SUB:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1101,11 +1139,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } + } + TRAP_SLL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLT: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1122,11 +1162,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0; - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0; + } + } + TRAP_SLT:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLTU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1143,11 +1185,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0; - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0; + } + } + TRAP_SLTU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::XOR: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1164,11 +1208,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS); + } + } + TRAP_XOR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SRL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1185,11 +1231,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } + } + TRAP_SRL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SRA: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1206,11 +1254,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } + } + TRAP_SRA:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::OR: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1227,11 +1277,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS); + } + } + TRAP_OR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::AND: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1248,11 +1300,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS); + } + } + TRAP_AND:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::FENCE: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1270,11 +1324,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - writeSpace1(traits::FENCE, traits::fence, pred << 4 | succ); - } catch(...){} - } - break; + { + super::template write_mem(traits::FENCE, traits::fence, pred << 4 | succ); + if(this->core.trap_state) goto TRAP_FENCE; + } + TRAP_FENCE:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::ECALL: { if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1284,11 +1339,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - raise(0, 11); - } catch(...){} - } - break; + { + raise(0, 11); + } + TRAP_ECALL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::EBREAK: { if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1298,11 +1353,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - raise(0, 3); - } catch(...){} - } - break; + { + raise(0, 3); + } + TRAP_EBREAK:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::URET: { if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1312,11 +1367,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - leave(0); - } catch(...){} - } - break; + { + leave(0); + } + TRAP_URET:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SRET: { if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1326,11 +1381,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - leave(1); - } catch(...){} - } - break; + { + leave(1); + } + TRAP_SRET:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::MRET: { if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1340,11 +1395,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - leave(3); - } catch(...){} - } - break; + { + leave(3); + } + TRAP_MRET:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::WFI: { if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1354,11 +1409,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - wait(1); - } catch(...){} - } - break; + { + wait(1); + } + TRAP_WFI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::DRET: { if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1372,17 +1427,18 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - if(*PRIV < 4) raise(0, 2); + if(*PRIV < 4) { + raise(0, 2); + } else { - pc_assign(*NEXT_PC) = *DPC; + *NEXT_PC = *DPC; + super::ex_info.branch_taken=true; *PRIV &= 0x3; } } - } catch(...){} - } - break; + TRAP_DRET:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRW: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1399,21 +1455,22 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { uint32_t xrs1 = *(X+rs1 % traits::RFS); if((rd % traits::RFS) != 0) { - uint32_t xrd = readSpace4(traits::CSR, csr); - writeSpace4(traits::CSR, csr, xrs1); + uint32_t xrd = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRW; + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.trap_state) goto TRAP_CSRRW; *(X+rd % traits::RFS) = xrd; } else { - writeSpace4(traits::CSR, csr, xrs1); + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.trap_state) goto TRAP_CSRRW; } } - } catch(...){} - } - break; + TRAP_CSRRW:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRS: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1430,16 +1487,20 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - uint32_t xrd = readSpace4(traits::CSR, csr); + uint32_t xrd = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRS; uint32_t xrs1 = *(X+rs1 % traits::RFS); - if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd | xrs1); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd | xrs1); + if(this->core.trap_state) goto TRAP_CSRRS; + } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = xrd; + } } - } catch(...){} - } - break; + TRAP_CSRRS:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRC: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1456,16 +1517,20 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - uint32_t xrd = readSpace4(traits::CSR, csr); + uint32_t xrd = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRC; uint32_t xrs1 = *(X+rs1 % traits::RFS); - if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd & ~ xrs1); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); + if(this->core.trap_state) goto TRAP_CSRRC; + } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = xrd; + } } - } catch(...){} - } - break; + TRAP_CSRRC:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRWI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); @@ -1482,15 +1547,17 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - uint32_t xrd = readSpace4(traits::CSR, csr); - writeSpace4(traits::CSR, csr, (uint32_t)zimm); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; + uint32_t xrd = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRWI; + super::template write_mem(traits::CSR, csr, (uint32_t)zimm); + if(this->core.trap_state) goto TRAP_CSRRWI; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = xrd; + } } - } catch(...){} - } - break; + TRAP_CSRRWI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRSI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); @@ -1507,15 +1574,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - uint32_t xrd = readSpace4(traits::CSR, csr); - if(zimm != 0) writeSpace4(traits::CSR, csr, xrd | (uint32_t)zimm); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; + uint32_t xrd = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRSI; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); + if(this->core.trap_state) goto TRAP_CSRRSI; + } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = xrd; + } } - } catch(...){} - } - break; + TRAP_CSRRSI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRCI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); @@ -1532,15 +1603,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { - uint32_t xrd = readSpace4(traits::CSR, csr); - if(zimm != 0) writeSpace4(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; + uint32_t xrd = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRCI; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); + if(this->core.trap_state) goto TRAP_CSRRCI; + } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = xrd; + } } - } catch(...){} - } - break; + TRAP_CSRRCI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::FENCE_I: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1556,11 +1631,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { - writeSpace2(traits::FENCE, traits::fencei, imm); - } catch(...){} - } - break; + { + super::template write_mem(traits::FENCE, traits::fencei, imm); + if(this->core.trap_state) goto TRAP_FENCE_I; + } + TRAP_FENCE_I:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::MUL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1577,16 +1653,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { if((rd % traits::RFS) != 0) { int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); *(X+rd % traits::RFS) = (uint32_t)res; } } - } catch(...){} - } - break; + TRAP_MUL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::MULH: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1603,16 +1677,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { if((rd % traits::RFS) != 0) { int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); } } - } catch(...){} - } - break; + TRAP_MULH:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::MULHSU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1629,16 +1701,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { if((rd % traits::RFS) != 0) { int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); } } - } catch(...){} - } - break; + TRAP_MULHSU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::MULHU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1655,16 +1725,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { if((rd % traits::RFS) != 0) { uint64_t res = (uint64_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); } } - } catch(...){} - } - break; + TRAP_MULHU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::DIV: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1681,20 +1749,24 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { if((rd % traits::RFS) != 0) { if(*(X+rs2 % traits::RFS) != 0) { uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) *(X+rd % traits::RFS) = MMIN; - else *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) / (int32_t)*(X+rs2 % traits::RFS); + if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) { + *(X+rd % traits::RFS) = MMIN; + } + else { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) / (int32_t)*(X+rs2 % traits::RFS); + } + } + else { + *(X+rd % traits::RFS) = - 1; } - else *(X+rd % traits::RFS) = - 1; } } - } catch(...){} - } - break; + TRAP_DIV:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::DIVU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1711,16 +1783,18 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) / *(X+rs2 % traits::RFS); - else *(X+rd % traits::RFS) = - 1; + if(*(X+rs2 % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) / *(X+rs2 % traits::RFS); + } + else { + *(X+rd % traits::RFS) = - 1; + } } } - } catch(...){} - } - break; + TRAP_DIVU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::REM: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1737,20 +1811,24 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { if((rd % traits::RFS) != 0) { if(*(X+rs2 % traits::RFS) != 0) { uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) *(X+rd % traits::RFS) = 0; - else *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) % (int32_t)*(X+rs2 % traits::RFS); + if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) { + *(X+rd % traits::RFS) = 0; + } + else { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) % (int32_t)*(X+rs2 % traits::RFS); + } + } + else { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); } - else *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); } } - } catch(...){} - } - break; + TRAP_REM:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::REMU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1767,16 +1845,18 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - try { { if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) % *(X+rs2 % traits::RFS); - else *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); + if(*(X+rs2 % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) % *(X+rs2 % traits::RFS); + } + else { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); + } } } - } catch(...){} - } - break; + TRAP_REMU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CADDI4SPN: { uint8_t rd = ((bit_sub<2,3>(instr))); uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); @@ -1792,12 +1872,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - if(imm) *(X+rd + 8) = *(X+2) + imm; - else raise(0, 2); - } catch(...){} - } - break; + { + if(imm) { + *(X+rd + 8) = *(X+2) + imm; + } + else { + raise(0, 2); + } + } + TRAP_CADDI4SPN:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CLW: { uint8_t rd = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); @@ -1814,14 +1898,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { uint32_t load_address = *(X+rs1 + 8) + uimm; - *(X+rd + 8) = (int32_t)readSpace4(traits::MEM, load_address); + *(X+rd + 8) = (int32_t)super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state) goto TRAP_CLW; } - } catch(...){} - } - break; + TRAP_CLW:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSW: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); @@ -1838,14 +1921,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { uint32_t load_address = *(X+rs1 + 8) + uimm; - writeSpace4(traits::MEM, load_address, *(X+rs2 + 8)); + super::template write_mem(traits::MEM, load_address, *(X+rs2 + 8)); + if(this->core.trap_state) goto TRAP_CSW; } - } catch(...){} - } - break; + TRAP_CSW:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CADDI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,5>(instr))); @@ -1861,11 +1943,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) + (int8_t)sext<6>(imm); - } catch(...){} - } - break; + { + *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) + (int8_t)sext<6>(imm); + } + TRAP_CADDI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CNOP: { uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); if(this->disass_enabled){ @@ -1876,12 +1958,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { } - } catch(...){} - } - break; + TRAP_CNOP:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CJAL: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ @@ -1896,14 +1976,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { *(X+1) = *PC + 2; - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); + *NEXT_PC = *PC + (int16_t)sext<12>(imm); + super::ex_info.branch_taken=true; } - } catch(...){} - } - break; + TRAP_CJAL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CLI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -1919,13 +1998,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int8_t)sext<6>(imm); + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int8_t)sext<6>(imm); + } } - } catch(...){} - } - break; + TRAP_CLI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CLUI: { uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -1941,14 +2020,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { - if(imm == 0) raise(0, 2); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)sext<18>(imm); + if(imm == 0) { + raise(0, 2); + } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)sext<18>(imm); + } } - } catch(...){} - } - break; + TRAP_CLUI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CADDI16SP: { uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ @@ -1963,12 +2044,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - if(nzimm) *(X+2) = *(X+2) + (int16_t)sext<10>(nzimm); - else raise(0, 2); - } catch(...){} - } - break; + { + if(nzimm) { + *(X+2) = *(X+2) + (int16_t)sext<10>(nzimm); + } + else { + raise(0, 2); + } + } + TRAP_CADDI16SP:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::__reserved_clui: { uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -1979,11 +2064,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - raise(0, 2); - } catch(...){} - } - break; + { + raise(0, 2); + } + TRAP___reserved_clui:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRLI: { uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -1999,14 +2084,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { uint8_t rs1_idx = rs1 + 8; *(X+rs1_idx) = *(X+rs1_idx) >> shamt; } - } catch(...){} - } - break; + TRAP_CSRLI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRAI: { uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -2022,18 +2105,20 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - if(shamt) { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; - } - else if(traits::XLEN == 128) { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; - } - } catch(...){} - } - break; + { + if(shamt) { + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; + } + else { + if(traits::XLEN == 128) { + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; + } + } + } + TRAP_CSRAI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CANDI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -2049,14 +2134,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { uint8_t rs1_idx = rs1 + 8; *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm); } - } catch(...){} - } - break; + TRAP_CANDI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSUB: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -2072,14 +2155,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) - *(X+rs2 + 8); } - } catch(...){} - } - break; + TRAP_CSUB:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CXOR: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -2095,14 +2176,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) ^ *(X+rs2 + 8); } - } catch(...){} - } - break; + TRAP_CXOR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::COR: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -2118,14 +2197,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) | *(X+rs2 + 8); } - } catch(...){} - } - break; + TRAP_COR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CAND: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); @@ -2141,14 +2218,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) & *(X+rs2 + 8); } - } catch(...){} - } - break; + TRAP_CAND:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CJ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ @@ -2162,11 +2237,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); - } catch(...){} - } - break; + { + *NEXT_PC = *PC + (int16_t)sext<12>(imm); + super::ex_info.branch_taken=true; + } + TRAP_CJ:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CBEQZ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -2182,11 +2258,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - if(*(X+rs1 + 8) == 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); - } catch(...){} - } - break; + { + if(*(X+rs1 + 8) == 0) { + *NEXT_PC = *PC + (int16_t)sext<9>(imm); + super::ex_info.branch_taken=true; + } + } + TRAP_CBEQZ:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CBNEZ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -2202,11 +2281,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - if(*(X+rs1 + 8) != 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); - } catch(...){} - } - break; + { + if(*(X+rs1 + 8) != 0) { + *NEXT_PC = *PC + (int16_t)sext<9>(imm); + super::ex_info.branch_taken=true; + } + } + TRAP_CBNEZ:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSLLI: { uint8_t nzuimm = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,5>(instr))); @@ -2222,11 +2304,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - if(nzuimm) *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) << nzuimm; - } catch(...){} - } - break; + { + if(nzuimm) { + *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) << nzuimm; + } + } + TRAP_CSLLI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CLWSP: { uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -2242,15 +2326,18 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - if(rd) { - uint32_t offs = *(X+2) + uimm; - *(X+rd % traits::RFS) = (int32_t)readSpace4(traits::MEM, offs); - } - else raise(0, 2); - } catch(...){} - } - break; + { + if(rd) { + uint32_t offs = *(X+2) + uimm; + *(X+rd % traits::RFS) = (int32_t)super::template read_mem(traits::MEM, offs); + if(this->core.trap_state) goto TRAP_CLWSP; + } + else { + raise(0, 2); + } + } + TRAP_CLWSP:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CMV: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -2266,11 +2353,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs2 % traits::RFS); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs2 % traits::RFS); + } + } + TRAP_CMV:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CJR: { uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2285,12 +2374,17 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - if(rs1) pc_assign(*NEXT_PC) = *(X+rs1 % traits::RFS) & ~ 0x1; - else raise(0, 2); - } catch(...){} - } - break; + { + if(rs1) { + *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; + super::ex_info.branch_taken=true; + } + else { + raise(0, 2); + } + } + TRAP_CJR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::__reserved_cmv: { if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2300,11 +2394,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - raise(0, 2); - } catch(...){} - } - break; + { + raise(0, 2); + } + TRAP___reserved_cmv:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CADD: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); @@ -2320,11 +2414,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rd % traits::RFS) + *(X+rs2 % traits::RFS); - } catch(...){} - } - break; + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rd % traits::RFS) + *(X+rs2 % traits::RFS); + } + } + TRAP_CADD:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CJALR: { uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2339,15 +2435,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { int32_t new_pc = *(X+rs1 % traits::RFS); *(X+1) = *PC + 2; - pc_assign(*NEXT_PC) = new_pc & ~ 0x1; + *NEXT_PC = new_pc & ~ 0x1; + super::ex_info.branch_taken=true; } - } catch(...){} - } - break; + TRAP_CJALR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CEBREAK: { if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2357,11 +2452,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - raise(0, 3); - } catch(...){} - } - break; + { + raise(0, 3); + } + TRAP_CEBREAK:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSWSP: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); @@ -2377,14 +2472,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { { uint32_t offs = *(X+2) + uimm; - writeSpace4(traits::MEM, offs, (uint32_t)*(X+rs2 % traits::RFS)); + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 % traits::RFS)); + if(this->core.trap_state) goto TRAP_CSWSP; } - } catch(...){} - } - break; + TRAP_CSWSP:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::DII: { if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2394,11 +2488,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - try { - raise(0, 2); - } catch(...){} - } - break; + { + raise(0, 2); + } + TRAP_DII:break; + }// @suppress("No break at end of case") default: { *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); raise(0, 2); From 1720bd4aaacc98f38526841db486e20e4c341f9c Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Fri, 20 May 2022 15:17:58 +0200 Subject: [PATCH 014/184] adds support for compressed instructions --- src/plugin/pctrace.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp index d3d099b..0d93801 100644 --- a/src/plugin/pctrace.cpp +++ b/src/plugin/pctrace.cpp @@ -157,8 +157,9 @@ void cov::callback(instr_info_t iinfo, const exec_info& einfo) { size_t id = iinfo.instr_id; auto entry = delays[id]; auto instr = instr_if->get_instr_word(); - auto call = (id==2 || id==3) && bit_sub<7,5>(instr)!=0; + auto call = id==65 || id ==86 || ((id==2 || id==3) && bit_sub<7,5>(instr)!=0) ;//not taking care of tail calls (jalr with loading x6) bool taken = einfo.branch_taken; + bool compressed = (instr&0x3)!=0x3; if (einfo.branch_taken) { delay = entry.taken; if(entry.taken > 1) @@ -169,10 +170,10 @@ void cov::callback(instr_info_t iinfo, const exec_info& einfo) { instr_if->set_curr_instr_cycles(entry.not_taken); } #ifndef WITH_LZ4 - output<get_pc() <<"," << delay <<"," << call<< "\n"; + output<get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; #else auto rdbuf=ostr.rdbuf(); - ostr<get_pc() <<"," << delay <<"," << call<< "\n"; + ostr<get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; #endif } } From 966d1616c5543ccf57f04a23322808ef65923341 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 21 May 2022 11:55:24 +0200 Subject: [PATCH 015/184] change source code to unified layout --- CMakeLists.txt | 8 ++++---- {incl => src}/iss/arch/.gitignore | 0 {incl => src}/iss/arch/hwl.h | 0 {incl => src}/iss/arch/riscv_hart_common.h | 0 {incl => src}/iss/arch/riscv_hart_m_p.h | 0 {incl => src}/iss/arch/riscv_hart_msu_vp.h | 0 {incl => src}/iss/arch/riscv_hart_mu_p.h | 0 src/iss/{ => arch}/tgc_c.cpp | 2 +- {incl => src}/iss/arch/tgc_c.h | 0 {incl => src}/iss/arch/tgc_mapper.h | 0 {incl => src}/iss/debugger/riscv_target_adapter.h | 0 {incl => src}/iss/factory.h | 0 src/{ => iss}/plugin/cycle_estimate.cpp | 6 +++--- {incl => src}/iss/plugin/cycle_estimate.h | 0 src/{ => iss}/plugin/instruction_count.cpp | 4 ++-- {incl => src}/iss/plugin/instruction_count.h | 0 src/{ => iss}/plugin/pctrace.cpp | 6 +++--- {incl => src}/iss/plugin/pctrace.h | 0 src/main.cpp | 8 ++++---- src/sysc/core_complex.cpp | 2 +- {incl => src}/sysc/core_complex.h | 0 21 files changed, 18 insertions(+), 18 deletions(-) rename {incl => src}/iss/arch/.gitignore (100%) rename {incl => src}/iss/arch/hwl.h (100%) rename {incl => src}/iss/arch/riscv_hart_common.h (100%) rename {incl => src}/iss/arch/riscv_hart_m_p.h (100%) rename {incl => src}/iss/arch/riscv_hart_msu_vp.h (100%) rename {incl => src}/iss/arch/riscv_hart_mu_p.h (100%) rename src/iss/{ => arch}/tgc_c.cpp (99%) rename {incl => src}/iss/arch/tgc_c.h (100%) rename {incl => src}/iss/arch/tgc_mapper.h (100%) rename {incl => src}/iss/debugger/riscv_target_adapter.h (100%) rename {incl => src}/iss/factory.h (100%) rename src/{ => iss}/plugin/cycle_estimate.cpp (97%) rename {incl => src}/iss/plugin/cycle_estimate.h (100%) rename src/{ => iss}/plugin/instruction_count.cpp (97%) rename {incl => src}/iss/plugin/instruction_count.h (100%) rename src/{ => iss}/plugin/pctrace.cpp (98%) rename {incl => src}/iss/plugin/pctrace.h (100%) rename {incl => src}/sysc/core_complex.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e676292..c039682 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,18 +29,18 @@ endif() add_subdirectory(softfloat) # library files -FILE(GLOB TGC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/iss/*.cpp) +FILE(GLOB TGC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/iss/arch/*.cpp) FILE(GLOB TGC_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/interp/vm_*.cpp) set(LIB_SOURCES src/vm/fp_functions.cpp - src/plugin/instruction_count.cpp + src/iss/plugin/instruction_count.cpp ${TGC_SOURCES} ${TGC_VM_SOURCES} ) if(TARGET RapidJSON) - list(APPEND LIB_SOURCES src/plugin/cycle_estimate.cpp src/plugin/pctrace.cpp) + list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp src/iss/plugin/pctrace.cpp) endif() if(WITH_LLVM) @@ -69,7 +69,7 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") target_compile_options(${PROJECT_NAME} PRIVATE /wd4293) endif() -target_include_directories(${PROJECT_NAME} PUBLIC incl) +target_include_directories(${PROJECT_NAME} PUBLIC src) target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp Boost::coroutine) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive) diff --git a/incl/iss/arch/.gitignore b/src/iss/arch/.gitignore similarity index 100% rename from incl/iss/arch/.gitignore rename to src/iss/arch/.gitignore diff --git a/incl/iss/arch/hwl.h b/src/iss/arch/hwl.h similarity index 100% rename from incl/iss/arch/hwl.h rename to src/iss/arch/hwl.h diff --git a/incl/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h similarity index 100% rename from incl/iss/arch/riscv_hart_common.h rename to src/iss/arch/riscv_hart_common.h diff --git a/incl/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h similarity index 100% rename from incl/iss/arch/riscv_hart_m_p.h rename to src/iss/arch/riscv_hart_m_p.h diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h similarity index 100% rename from incl/iss/arch/riscv_hart_msu_vp.h rename to src/iss/arch/riscv_hart_msu_vp.h diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h similarity index 100% rename from incl/iss/arch/riscv_hart_mu_p.h rename to src/iss/arch/riscv_hart_mu_p.h diff --git a/src/iss/tgc_c.cpp b/src/iss/arch/tgc_c.cpp similarity index 99% rename from src/iss/tgc_c.cpp rename to src/iss/arch/tgc_c.cpp index 35a27d0..a014ac7 100644 --- a/src/iss/tgc_c.cpp +++ b/src/iss/arch/tgc_c.cpp @@ -32,7 +32,7 @@ #include "util/ities.h" #include -#include +#include "tgc_c.h" #include #include #include diff --git a/incl/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h similarity index 100% rename from incl/iss/arch/tgc_c.h rename to src/iss/arch/tgc_c.h diff --git a/incl/iss/arch/tgc_mapper.h b/src/iss/arch/tgc_mapper.h similarity index 100% rename from incl/iss/arch/tgc_mapper.h rename to src/iss/arch/tgc_mapper.h diff --git a/incl/iss/debugger/riscv_target_adapter.h b/src/iss/debugger/riscv_target_adapter.h similarity index 100% rename from incl/iss/debugger/riscv_target_adapter.h rename to src/iss/debugger/riscv_target_adapter.h diff --git a/incl/iss/factory.h b/src/iss/factory.h similarity index 100% rename from incl/iss/factory.h rename to src/iss/factory.h diff --git a/src/plugin/cycle_estimate.cpp b/src/iss/plugin/cycle_estimate.cpp similarity index 97% rename from src/plugin/cycle_estimate.cpp rename to src/iss/plugin/cycle_estimate.cpp index 553a772..3174f30 100644 --- a/src/plugin/cycle_estimate.cpp +++ b/src/iss/plugin/cycle_estimate.cpp @@ -32,14 +32,14 @@ * eyck@minres.com - initial API and implementation ******************************************************************************/ -#include "iss/plugin/cycle_estimate.h" +#include "cycle_estimate.h" #include #include #include #include -#include "rapidjson/writer.h" -#include "rapidjson/stringbuffer.h" +#include +#include #include #include #include diff --git a/incl/iss/plugin/cycle_estimate.h b/src/iss/plugin/cycle_estimate.h similarity index 100% rename from incl/iss/plugin/cycle_estimate.h rename to src/iss/plugin/cycle_estimate.h diff --git a/src/plugin/instruction_count.cpp b/src/iss/plugin/instruction_count.cpp similarity index 97% rename from src/plugin/instruction_count.cpp rename to src/iss/plugin/instruction_count.cpp index aba30eb..0b54e21 100644 --- a/src/plugin/instruction_count.cpp +++ b/src/iss/plugin/instruction_count.cpp @@ -32,8 +32,8 @@ * eyck@minres.com - initial API and implementation ******************************************************************************/ -#include "iss/plugin/instruction_count.h" -#include "iss/instrumentation_if.h" +#include "instruction_count.h" +#include #include #include diff --git a/incl/iss/plugin/instruction_count.h b/src/iss/plugin/instruction_count.h similarity index 100% rename from incl/iss/plugin/instruction_count.h rename to src/iss/plugin/instruction_count.h diff --git a/src/plugin/pctrace.cpp b/src/iss/plugin/pctrace.cpp similarity index 98% rename from src/plugin/pctrace.cpp rename to src/iss/plugin/pctrace.cpp index d3d099b..7f25652 100644 --- a/src/plugin/pctrace.cpp +++ b/src/iss/plugin/pctrace.cpp @@ -1,11 +1,11 @@ #include -#include +#include "pctrace.h" #include #include #include #include -#include "rapidjson/writer.h" -#include "rapidjson/stringbuffer.h" +#include +#include #include #include #include diff --git a/incl/iss/plugin/pctrace.h b/src/iss/plugin/pctrace.h similarity index 100% rename from incl/iss/plugin/pctrace.h rename to src/iss/plugin/pctrace.h diff --git a/src/main.cpp b/src/main.cpp index d8d6bd6..0d4fe2f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,14 +35,14 @@ #include #include -#include +#include "iss/arch/tgc_mapper.h" #ifdef WITH_LLVM #include #endif #include -#include -#include -#include +#include "iss/plugin/cycle_estimate.h" +#include "iss/plugin/instruction_count.h" +#include "iss/plugin/pctrace.h" #include #if defined(HAS_LUA) #include diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 53ff0cb..118767e 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include "core_complex.h" #include #include #include diff --git a/incl/sysc/core_complex.h b/src/sysc/core_complex.h similarity index 100% rename from incl/sysc/core_complex.h rename to src/sysc/core_complex.h From 0c542d42aab412f8e4b2bf5f1f2887cf7b8969c2 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 21 May 2022 12:27:13 +0200 Subject: [PATCH 016/184] separate generated sources --- .gitignore | 1 - CMakeLists.txt | 24 +- gen_input/templates/CORENAME.cpp.gtl | 2 +- gen_input/templates/interp/CORENAME.cpp.gtl | 2 +- src-gen/.gitignore | 2 + src/iss/arch/.gitignore | 1 - src/iss/arch/tgc_c.cpp | 2 +- src/vm/interp/.gitignore | 1 - src/vm/interp/vm_tgc_c.cpp | 4 +- src/vm/llvm/{vm_tgf_c.cpp => vm_tgc_c.cpp} | 10 +- src/vm/llvm/vm_tgf_b.cpp | 2582 ------------------- src/vm/tcc/{vm_tgf_c.cpp => vm_tgc_c.cpp} | 8 +- src/vm/tcc/vm_tgf_b.cpp | 2074 --------------- 13 files changed, 30 insertions(+), 4683 deletions(-) create mode 100644 src-gen/.gitignore delete mode 100644 src/iss/arch/.gitignore delete mode 100644 src/vm/interp/.gitignore rename src/vm/llvm/{vm_tgf_c.cpp => vm_tgc_c.cpp} (99%) delete mode 100644 src/vm/llvm/vm_tgf_b.cpp rename src/vm/tcc/{vm_tgf_c.cpp => vm_tgc_c.cpp} (99%) delete mode 100644 src/vm/tcc/vm_tgf_b.cpp diff --git a/.gitignore b/.gitignore index d687e5f..85bcc37 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,5 @@ language.settings.xml /.gdbinit /*.out /dump.json -/src-gen/ /*.yaml /*.json diff --git a/CMakeLists.txt b/CMakeLists.txt index c039682..25d1883 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,32 +29,35 @@ endif() add_subdirectory(softfloat) # library files -FILE(GLOB TGC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/iss/arch/*.cpp) -FILE(GLOB TGC_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/interp/vm_*.cpp) +FILE(GLOB GEN_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp +) set(LIB_SOURCES src/vm/fp_functions.cpp src/iss/plugin/instruction_count.cpp - - ${TGC_SOURCES} - ${TGC_VM_SOURCES} + src/iss/arch/tgc_c.cpp + src/vm/interp/vm_tgc_c.cpp + src/vm/fp_functions.cpp + ${GEN_SOURCES} ) if(TARGET RapidJSON) list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp src/iss/plugin/pctrace.cpp) endif() if(WITH_LLVM) - FILE(GLOB TGC_LLVM_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/llvm/vm_*.cpp + FILE(GLOB LLVM_GEN_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp ) - list(APPEND LIB_SOURCES ${TGC_LLVM_SOURCES}) + list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES}) endif() if(WITH_TCC) - FILE(GLOB TGC_TCC_SOURCES + FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/tcc/vm_*.cpp ) - list(APPEND LIB_SOURCES ${TGC_TCC_SOURCES}) + list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) endif() # Define the library @@ -70,6 +73,7 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") target_compile_options(${PROJECT_NAME} PRIVATE /wd4293) endif() target_include_directories(${PROJECT_NAME} PUBLIC src) +target_include_directories(${PROJECT_NAME} PUBLIC src-gen) target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp Boost::coroutine) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive) diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl index eae0aa7..b99a67e 100644 --- a/gen_input/templates/CORENAME.cpp.gtl +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -37,9 +37,9 @@ def getRegisterSizes(){ return regs } %> +#include "${coreDef.name.toLowerCase()}.h" #include "util/ities.h" #include -#include #include #include #include diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index f0cb153..c643699 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -36,7 +36,7 @@ def nativeTypeSize(int size){ if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; } %> -#include "../fp_functions.h" +#include #include #include #include diff --git a/src-gen/.gitignore b/src-gen/.gitignore new file mode 100644 index 0000000..d3fcb35 --- /dev/null +++ b/src-gen/.gitignore @@ -0,0 +1,2 @@ +/iss +/vm \ No newline at end of file diff --git a/src/iss/arch/.gitignore b/src/iss/arch/.gitignore deleted file mode 100644 index 52334de..0000000 --- a/src/iss/arch/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/tgc_*.h diff --git a/src/iss/arch/tgc_c.cpp b/src/iss/arch/tgc_c.cpp index a014ac7..6357ced 100644 --- a/src/iss/arch/tgc_c.cpp +++ b/src/iss/arch/tgc_c.cpp @@ -30,9 +30,9 @@ * *******************************************************************************/ +#include "tgc_c.h" #include "util/ities.h" #include -#include "tgc_c.h" #include #include #include diff --git a/src/vm/interp/.gitignore b/src/vm/interp/.gitignore deleted file mode 100644 index 89389b0..0000000 --- a/src/vm/interp/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/vm_tgc_*.cpp diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 0e1ad99..b219e2e 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -30,7 +30,7 @@ * *******************************************************************************/ -#include "../fp_functions.h" +#include #include #include #include @@ -2000,7 +2000,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int8_t)sext<6>(imm); + *(X+rd) = (uint32_t)(int8_t)sext<1>(imm); } } TRAP_CLI:break; diff --git a/src/vm/llvm/vm_tgf_c.cpp b/src/vm/llvm/vm_tgc_c.cpp similarity index 99% rename from src/vm/llvm/vm_tgf_c.cpp rename to src/vm/llvm/vm_tgc_c.cpp index aa881d5..e712445 100644 --- a/src/vm/llvm/vm_tgf_c.cpp +++ b/src/vm/llvm/vm_tgc_c.cpp @@ -30,7 +30,7 @@ * *******************************************************************************/ -#include +#include #include #include #include @@ -52,7 +52,7 @@ namespace fp_impl { void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); } -namespace tgf_c { +namespace tgc_c { using namespace ::llvm; using namespace iss::arch; using namespace iss::debugger; @@ -4151,11 +4151,11 @@ template inline void vm_impl::gen_trap_check(BasicBlock *b bb, this->trap_blk, 1); } -} // namespace tgf_c +} // namespace tgc_c template <> -std::unique_ptr create(arch::tgf_c *core, unsigned short port, bool dump) { - auto ret = new tgf_c::vm_impl(*core, dump); +std::unique_ptr create(arch::tgc_c *core, unsigned short port, bool dump) { + auto ret = new tgc_c::vm_impl(*core, dump); if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } diff --git a/src/vm/llvm/vm_tgf_b.cpp b/src/vm/llvm/vm_tgf_b.cpp deleted file mode 100644 index 1fc6548..0000000 --- a/src/vm/llvm/vm_tgf_b.cpp +++ /dev/null @@ -1,2582 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace llvm { -namespace fp_impl { -void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); -} - -namespace tgf_b { -using namespace ::llvm; -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::llvm::vm_base { -public: - using super = typename iss::llvm::vm_base; - using virt_addr_t = typename super::virt_addr_t; - using phys_addr_t = typename super::phys_addr_t; - using code_word_t = typename super::code_word_t; - using addr_t = typename super::addr_t; - - vm_impl(); - - vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); - - void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } - - target_adapter_if *accquire_target_adapter(server_if *srv) override { - debugger_if::dbg_enabled = true; - if (vm_base::tgt_adapter == nullptr) - vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm_base::tgt_adapter; - } - -protected: - using vm_base::get_reg_ptr; - - inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - template inline ConstantInt *size(T type) { - return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); - } - - void setup_module(Module* m) override { - super::setup_module(m); - iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); - } - - inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { - return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); - } - - std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override; - - void gen_leave_behavior(BasicBlock *leave_blk) override; - - void gen_raise_trap(uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(unsigned lvl); - - void gen_wait(unsigned type); - - void gen_trap_behavior(BasicBlock *) override; - - void gen_trap_check(BasicBlock *bb); - - inline Value *gen_reg_load(unsigned i, unsigned level = 0) { - return this->builder.CreateLoad(get_reg_ptr(i), false); - } - - inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { - Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); - this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); - } - - // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; - - using this_class = vm_impl; - using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, - code_word_t instr, - BasicBlock *bb); - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } - -private: - /**************************************************************************** - * start opcode definitions - ****************************************************************************/ - struct InstructionDesriptor { - size_t length; - uint32_t value; - uint32_t mask; - compile_func op; - }; - - const std::array instr_descr = {{ - /* entries are: size, valid value, valid mask, function ptr */ - /* instruction LUI */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT */ - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE */ - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU */ - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU */ - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB */ - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI */ - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI */ - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI */ - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LUI"); - - this->gen_sync(PRE_SYNC, 0); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 0); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 1: AUIPC */ - std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AUIPC"); - - this->gen_sync(PRE_SYNC, 1); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 1); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 2: JAL */ - std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JAL"); - - this->gen_sync(PRE_SYNC, 2); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 2); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 3: JALR */ - std::tuple __jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JALR"); - - this->gen_sync(PRE_SYNC, 3); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* new_pc_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* align_val = this->builder.CreateAnd( - new_pc_val, - this->gen_const(32U, 0x2)); - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - align_val, - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - this->gen_raise_trap(0, 0); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAnd( - new_pc_val, - this->builder.CreateNot(this->gen_const(32U, 0x1))); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - this->gen_sync(POST_SYNC, 3); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 4: BEQ */ - std::tuple __beq(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BEQ"); - - this->gen_sync(PRE_SYNC, 4); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 4); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 5: BNE */ - std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BNE"); - - this->gen_sync(PRE_SYNC, 5); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 5); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 6: BLT */ - std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLT"); - - this->gen_sync(PRE_SYNC, 6); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 6); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 7: BGE */ - std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGE"); - - this->gen_sync(PRE_SYNC, 7); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGE, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 7); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 8: BLTU */ - std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLTU"); - - this->gen_sync(PRE_SYNC, 8); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 8); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 9: BGEU */ - std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGEU"); - - this->gen_sync(PRE_SYNC, 9); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_sync(POST_SYNC, 9); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 10: LB */ - std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LB"); - - this->gen_sync(PRE_SYNC, 10); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 10); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 11: LH */ - std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LH"); - - this->gen_sync(PRE_SYNC, 11); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 11); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 12: LW */ - std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LW"); - - this->gen_sync(PRE_SYNC, 12); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 12); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 13: LBU */ - std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LBU"); - - this->gen_sync(PRE_SYNC, 13); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 13); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 14: LHU */ - std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LHU"); - - this->gen_sync(PRE_SYNC, 14); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 14); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 15: SB */ - std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SB"); - - this->gen_sync(PRE_SYNC, 15); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 15); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 16: SH */ - std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SH"); - - this->gen_sync(PRE_SYNC, 16); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(16))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 16); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 17: SW */ - std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SW"); - - this->gen_sync(PRE_SYNC, 17); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 17); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 18: ADDI */ - std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDI"); - - this->gen_sync(PRE_SYNC, 18); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 18); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 19: SLTI */ - std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTI"); - - this->gen_sync(PRE_SYNC, 19); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 19); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 20: SLTIU */ - std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTIU"); - - this->gen_sync(PRE_SYNC, 20); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - int32_t full_imm_val = imm; - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, full_imm_val)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 20); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 21: XORI */ - std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XORI"); - - this->gen_sync(PRE_SYNC, 21); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 21); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 22: ORI */ - std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ORI"); - - this->gen_sync(PRE_SYNC, 22); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 22); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 23: ANDI */ - std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ANDI"); - - this->gen_sync(PRE_SYNC, 23); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 23); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 24: SLLI */ - std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLI"); - - this->gen_sync(PRE_SYNC, 24); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 24); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 25: SRLI */ - std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLI"); - - this->gen_sync(PRE_SYNC, 25); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 25); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 26: SRAI */ - std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAI"); - - this->gen_sync(PRE_SYNC, 26); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 26); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 27: ADD */ - std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADD"); - - this->gen_sync(PRE_SYNC, 27); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 27); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 28: SUB */ - std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SUB"); - - this->gen_sync(PRE_SYNC, 28); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 28); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 29: SLL */ - std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLL"); - - this->gen_sync(PRE_SYNC, 29); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 29); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 30: SLT */ - std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLT"); - - this->gen_sync(PRE_SYNC, 30); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 30); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 31: SLTU */ - std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTU"); - - this->gen_sync(PRE_SYNC, 31); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, - false)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 31); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 32: XOR */ - std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XOR"); - - this->gen_sync(PRE_SYNC, 32); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 32); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 33: SRL */ - std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRL"); - - this->gen_sync(PRE_SYNC, 33); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 33); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 34: SRA */ - std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRA"); - - this->gen_sync(PRE_SYNC, 34); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 34); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 35: OR */ - std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("OR"); - - this->gen_sync(PRE_SYNC, 35); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 35); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 36: AND */ - std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AND"); - - this->gen_sync(PRE_SYNC, 36); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 36); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 37: FENCE */ - std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE"); - - this->gen_sync(PRE_SYNC, 37); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(32U, pred), - this->gen_const(32U, 4)), - this->gen_const(32U, succ)); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 0), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 37); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 38: FENCE_I */ - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE_I"); - - this->gen_sync(PRE_SYNC, 38); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence_i"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, imm); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 1), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 38); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(FLUSH, nullptr); - } - - /* instruction 39: ECALL */ - std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ECALL"); - - this->gen_sync(PRE_SYNC, 39); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ecall"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 11); - this->gen_sync(POST_SYNC, 39); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 40: EBREAK */ - std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("EBREAK"); - - this->gen_sync(PRE_SYNC, 40); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ebreak"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 40); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 41: URET */ - std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("URET"); - - this->gen_sync(PRE_SYNC, 41); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("uret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(0); - this->gen_sync(POST_SYNC, 41); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 42: SRET */ - std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRET"); - - this->gen_sync(PRE_SYNC, 42); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(1); - this->gen_sync(POST_SYNC, 42); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 43: MRET */ - std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MRET"); - - this->gen_sync(PRE_SYNC, 43); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("mret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(3); - this->gen_sync(POST_SYNC, 43); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 44: WFI */ - std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("WFI"); - - this->gen_sync(PRE_SYNC, 44); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("wfi"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_wait(1); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 44); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 45: SFENCE.VMA */ - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SFENCE.VMA"); - - this->gen_sync(PRE_SYNC, 45); - - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sfence.vma"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, rs1); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 2), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - Value* FENCEtmp1_val = this->gen_const(32U, rs2); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 3), - this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 45); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 46: CSRRW */ - std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRW"); - - this->gen_sync(PRE_SYNC, 46); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* CSRtmp0_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - Value* Xtmp1_val = csr_val_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* CSRtmp2_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 46); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 47: CSRRS */ - std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRS"); - - this->gen_sync(PRE_SYNC, 47); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateOr( - xrd_val, - xrs1_val); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 47); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 48: CSRRC */ - std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRC"); - - this->gen_sync(PRE_SYNC, 48); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - xrd_val, - this->builder.CreateNot(xrs1_val)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 48); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 49: CSRRWI */ - std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRWI"); - - this->gen_sync(PRE_SYNC, 49); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* CSRtmp1_val = this->gen_ext( - this->gen_const(32U, zimm), - 32, - false); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 49); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 50: CSRRSI */ - std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRSI"); - - this->gen_sync(PRE_SYNC, 50); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - if(zimm != 0){ - Value* CSRtmp0_val = this->builder.CreateOr( - res_val, - this->gen_ext( - this->gen_const(32U, zimm), - 32, - false)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - } - if(rd != 0){ - Value* Xtmp1_val = res_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 50); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 51: CSRRCI */ - std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRCI"); - - this->gen_sync(PRE_SYNC, 51); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(zimm != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - res_val, - this->builder.CreateNot(this->gen_ext( - this->gen_const(32U, zimm), - 32, - false))); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 51); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { - this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); - this->builder.CreateStore( - this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits::ICOUNT), true), - this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - this->gen_raise_trap(0, 2); // illegal instruction trap - this->gen_sync(iss::POST_SYNC, instr_descr.size()); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } -}; - -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; -} - -template vm_impl::vm_impl() { this(new ARCH()); } - -template -vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); - } -} - -template -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, this_block); -} - -template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { - this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); -} - -template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { - auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); - this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); -} - -template void vm_impl::gen_leave_trap(unsigned lvl) { - std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) }; - this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); - auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); -} - -template void vm_impl::gen_wait(unsigned type) { - std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) }; - this->builder.CreateCall(this->mod->getFunction("wait"), args); -} - -template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { - this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), - get_reg_ptr(traits::LAST_BRANCH), false); - std::vector args{this->core_ptr, this->adj_to64(trap_state_val), - this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; - this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); - auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateRet(trap_addr_val); -} - -template inline void vm_impl::gen_trap_check(BasicBlock *bb) { - auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_EQ, v, - ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, this->trap_blk, 1); -} - -} // namespace tgf_b - -template <> -std::unique_ptr create(arch::tgf_b *core, unsigned short port, bool dump) { - auto ret = new tgf_b::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} // namespace llvm -} // namespace iss diff --git a/src/vm/tcc/vm_tgf_c.cpp b/src/vm/tcc/vm_tgc_c.cpp similarity index 99% rename from src/vm/tcc/vm_tgf_c.cpp rename to src/vm/tcc/vm_tgc_c.cpp index 79e4449..ceda6ce 100644 --- a/src/vm/tcc/vm_tgf_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -30,7 +30,7 @@ * *******************************************************************************/ -#include +#include #include #include #include @@ -49,7 +49,7 @@ namespace iss { namespace tcc { -namespace tgf_c { +namespace tgc_c { using namespace iss::arch; using namespace iss::debugger; @@ -3251,8 +3251,8 @@ template void vm_impl::gen_trap_behavior(tu_builder& tu) { } // namespace mnrv32 template <> -std::unique_ptr create(arch::tgf_c *core, unsigned short port, bool dump) { - auto ret = new tgf_c::vm_impl(*core, dump); +std::unique_ptr create(arch::tgc_c *core, unsigned short port, bool dump) { + auto ret = new tgc_c::vm_impl(*core, dump); if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } diff --git a/src/vm/tcc/vm_tgf_b.cpp b/src/vm/tcc/vm_tgf_b.cpp deleted file mode 100644 index 93d4177..0000000 --- a/src/vm/tcc/vm_tgf_b.cpp +++ /dev/null @@ -1,2074 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2020 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace tcc { -namespace tgf_b { -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::tcc::vm_base { -public: - using super = typename iss::tcc::vm_base; - using virt_addr_t = typename super::virt_addr_t; - using phys_addr_t = typename super::phys_addr_t; - using code_word_t = typename super::code_word_t; - using addr_t = typename super::addr_t; - using tu_builder = typename super::tu_builder; - - vm_impl(); - - vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); - - void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } - - target_adapter_if *accquire_target_adapter(server_if *srv) override { - debugger_if::dbg_enabled = true; - if (vm_base::tgt_adapter == nullptr) - vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return vm_base::tgt_adapter; - } - -protected: - using vm_base::get_reg_ptr; - - using this_class = vm_impl; - using compile_ret_t = std::tuple; - using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&); - - inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - void setup_module(std::string m) override { - super::setup_module(m); - } - - compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, tu_builder&) override; - - void gen_trap_behavior(tu_builder& tu) override; - - void gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause); - - void gen_leave_trap(tu_builder& tu, unsigned lvl); - - void gen_wait(tu_builder& tu, unsigned type); - - inline void gen_trap_check(tu_builder& tu) { - tu("if(*trap_state!=0) goto trap_entry;"); - } - - inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) { - switch(reg_num){ - case traits::NEXT_PC: - tu("*next_pc = {:#x};", pc.val); - break; - case traits::PC: - tu("*pc = {:#x};", pc.val); - break; - default: - if(!tu.defined_regs[reg_num]){ - tu("reg_t* reg{:02d} = (reg_t*){:#x};", reg_num, reinterpret_cast(get_reg_ptr(reg_num))); - tu.defined_regs[reg_num]=true; - } - tu("*reg{:02d} = {:#x};", reg_num, pc.val); - } - } - - // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } - -private: - /**************************************************************************** - * start opcode definitions - ****************************************************************************/ - struct InstructionDesriptor { - size_t length; - uint32_t value; - uint32_t mask; - compile_func op; - }; - - const std::array instr_descr = {{ - /* entries are: size, valid value, valid mask, function ptr */ - /* instruction LUI, encoding '.........................0110111' */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC, encoding '.........................0010111' */ - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL, encoding '.........................1101111' */ - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR, encoding '.................000.....1100111' */ - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ, encoding '.................000.....1100011' */ - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE, encoding '.................001.....1100011' */ - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT, encoding '.................100.....1100011' */ - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE, encoding '.................101.....1100011' */ - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU, encoding '.................110.....1100011' */ - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU, encoding '.................111.....1100011' */ - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB, encoding '.................000.....0000011' */ - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH, encoding '.................001.....0000011' */ - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW, encoding '.................010.....0000011' */ - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU, encoding '.................100.....0000011' */ - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU, encoding '.................101.....0000011' */ - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB, encoding '.................000.....0100011' */ - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH, encoding '.................001.....0100011' */ - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW, encoding '.................010.....0100011' */ - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI, encoding '.................000.....0010011' */ - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI, encoding '.................010.....0010011' */ - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU, encoding '.................011.....0010011' */ - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI, encoding '.................100.....0010011' */ - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI, encoding '.................110.....0010011' */ - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI, encoding '.................111.....0010011' */ - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI, encoding '0000000..........001.....0010011' */ - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI, encoding '0000000..........101.....0010011' */ - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI, encoding '0100000..........101.....0010011' */ - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD, encoding '0000000..........000.....0110011' */ - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB, encoding '0100000..........000.....0110011' */ - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL, encoding '0000000..........001.....0110011' */ - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT, encoding '0000000..........010.....0110011' */ - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU, encoding '0000000..........011.....0110011' */ - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR, encoding '0000000..........100.....0110011' */ - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL, encoding '0000000..........101.....0110011' */ - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA, encoding '0100000..........101.....0110011' */ - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR, encoding '0000000..........110.....0110011' */ - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND, encoding '0000000..........111.....0110011' */ - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE, encoding '0000.............000.....0001111' */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I, encoding '.................001.....0001111' */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL, encoding '00000000000000000000000001110011' */ - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK, encoding '00000000000100000000000001110011' */ - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET, encoding '00000000001000000000000001110011' */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET, encoding '00010000001000000000000001110011' */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET, encoding '00110000001000000000000001110011' */ - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI, encoding '00010000010100000000000001110011' */ - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA, encoding '0001001..........000000001110011' */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW, encoding '.................001.....1110011' */ - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS, encoding '.................010.....1110011' */ - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC, encoding '.................011.....1110011' */ - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI, encoding '.................101.....1110011' */ - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI, encoding '.................110.....1110011' */ - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI, encoding '.................111.....1110011' */ - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - }}; - - /* instruction definitions */ - /* instruction 0: LUI */ - compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 0); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.constant(imm, 32U), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 0); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 1: AUIPC */ - compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AUIPC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 1); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 1); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 2: JAL */ - compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 2); - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 2); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 3: JALR */ - compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 3); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto new_pc_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - auto align_val = tu.assignment(tu.l_and( - new_pc_val, - tu.constant(0x2, 32U)), 32); - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - align_val, - tu.constant(0, 32U))); - this->gen_raise_trap(tu, 0, 0); - tu(" }} else {{"); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); - } - auto PC_val_v = tu.assignment("PC_val", tu.l_and( - new_pc_val, - tu.l_not(tu.constant(0x1, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - tu.close_scope(); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 3); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 4: BEQ */ - compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BEQ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 4); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 4); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 5: BNE */ - compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BNE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 5); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 5); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 6: BLT */ - compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 6); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 6); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 7: BGE */ - compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 7); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SGE, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 7); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 8: BLTU */ - compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 8); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 8); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 9: BGEU */ - compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("BGEU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 9); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_UGE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 9); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 10: LB */ - compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 10); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 10); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 11: LH */ - compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 11); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 11); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 12: LW */ - compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 12); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 12); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 13: LBU */ - compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LBU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 13); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 13); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 14: LHU */ - compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("LHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 14); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - true), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 14); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 15: SB */ - compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 15); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 8)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 15); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 16: SH */ - compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 16); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 16)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 16); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 17: SW */ - compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 17); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 17); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 18: ADDI */ - compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 18); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 18); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 19: SLTI */ - compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 19); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 19); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 20: SLTIU */ - compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTIU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 20); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - int32_t full_imm_val = imm; - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.constant(full_imm_val, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 20); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 21: XORI */ - compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 21); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 21); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 22: ORI */ - compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 22); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 22); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 23: ANDI */ - compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 23); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 23); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 24: SLLI */ - compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 24); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 24); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 25: SRLI */ - compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 25); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 25); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 26: SRAI */ - compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 26); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 26); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 27: ADD */ - compile_ret_t __add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 27); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 27); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 28: SUB */ - compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 28); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.sub( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 28); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 29: SLL */ - compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 29); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 29); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 30: SLT */ - compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 30); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 30); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 31: SLTU */ - compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 31); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, - true)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 31); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 32: XOR */ - compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 32); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 32); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 33: SRL */ - compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 33); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 33); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 34: SRA */ - compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 34); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 34); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 35: OR */ - compile_ret_t __or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 35); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 35); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 36: AND */ - compile_ret_t __and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 36); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 36); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 37: FENCE */ - compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 37); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(0, 64U), - tu.trunc(tu.l_or( - tu.shl( - tu.constant(pred, 32U), - tu.constant(4, 32U)), - tu.constant(succ, 32U)), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 37); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 38: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_I_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 38); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence_i"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(1, 64U), - tu.trunc(tu.constant(imm, 32U), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 38); - gen_trap_check(tu); - return std::make_tuple(FLUSH); - } - - /* instruction 39: ECALL */ - compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("ECALL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 39); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ecall"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 11); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 39); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 40: EBREAK */ - compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 40); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ebreak"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 40); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 41: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("URET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 41); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "uret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 0); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 41); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 42: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 42); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 1); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 42); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 43: MRET */ - compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("MRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 43); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "mret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 3); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 43); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 44: WFI */ - compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("WFI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 44); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "wfi"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_wait(tu, 1); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 44); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 45: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SFENCE_VMA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 45); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sfence.vma"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(2, 64U), - tu.trunc(tu.constant(rs1, 32U), 32)); - tu.write_mem( - traits::FENCE, - tu.constant(3, 64U), - tu.trunc(tu.constant(rs2, 32U), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 45); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 46: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 46); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto rs_val_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - auto csr_val_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); - tu.store(csr_val_val, rd + traits::X0); - } else { - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 46); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 47: CSRRS */ - compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRS_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 47); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - xrd_val, - xrs1_val), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 47); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 48: CSRRC */ - compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 48); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); - } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - xrd_val, - tu.l_not(xrs1_val)), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 48); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 49: CSRRWI */ - compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRWI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 49); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - if(rd != 0){ - tu.store(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), rd + traits::X0); - } - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.ext( - tu.constant(zimm, 32U), - 32, - true), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 49); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 50: CSRRSI */ - compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRSI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 50); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - res_val, - tu.ext( - tu.constant(zimm, 32U), - 32, - true)), 32)); - } - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 50); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 51: CSRRCI */ - compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRRCI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 51); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); - } - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - res_val, - tu.l_not(tu.ext( - tu.constant(zimm, 32U), - 32, - true))), 32)); - } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 51); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, tu_builder& tu) { - vm_impl::gen_sync(tu, iss::PRE_SYNC, instr_descr.size()); - pc = pc + ((instr & 3) == 3 ? 4 : 2); - gen_raise_trap(tu, 0, 2); // illegal instruction trap - vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size()); - vm_impl::gen_trap_check(tu); - return BRANCH; - } -}; - -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; -} - -template vm_impl::vm_impl() { this(new ARCH()); } - -template -vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); - } -} - -template -std::tuple -vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - // curr pc on stack - ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (f == nullptr) { - f = &this_class::illegal_intruction; - } - return (this->*f)(pc, insn, tu); -} - -template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { - tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id); -} - -template void vm_impl::gen_leave_trap(tu_builder& tu, unsigned lvl) { - tu("leave_trap(core_ptr, {});", lvl); - tu.store(tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN),traits::NEXT_PC); -} - -template void vm_impl::gen_wait(tu_builder& tu, unsigned type) { -} - -template void vm_impl::gen_trap_behavior(tu_builder& tu) { - tu("trap_entry:"); - tu("enter_trap(core_ptr, *trap_state, *pc);"); - tu("return *next_pc;"); -} - -} // namespace mnrv32 - -template <> -std::unique_ptr create(arch::tgf_b *core, unsigned short port, bool dump) { - auto ret = new tgf_b::vm_impl(*core, dump); - if (port != 0) debugger::server::run_server(ret, port); - return std::unique_ptr(ret); -} -} -} // namespace iss From 0703a0a845ddeb6a90abd3e880c77710c436c27d Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 30 May 2022 07:45:32 +0200 Subject: [PATCH 017/184] update tgc-mapper --- src/iss/arch/tgc_mapper.h | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/iss/arch/tgc_mapper.h b/src/iss/arch/tgc_mapper.h index 7173d7b..e79c065 100644 --- a/src/iss/arch/tgc_mapper.h +++ b/src/iss/arch/tgc_mapper.h @@ -4,39 +4,44 @@ #include "riscv_hart_m_p.h" #include "tgc_c.h" using tgc_c_plat_type = iss::arch::riscv_hart_m_p; +#ifdef CORE_TGC_A +#include "riscv_hart_m_p.h" +#include +using tgc_a_plat_type = iss::arch::riscv_hart_m_p; +#endif #ifdef CORE_TGC_B #include "riscv_hart_m_p.h" -#include "tgc_b.h" +#include using tgc_b_plat_type = iss::arch::riscv_hart_m_p; #endif #ifdef CORE_TGC_C_XRB_NN #include "riscv_hart_m_p.h" -#include "tgc_c_xrb_nn.h" +#include using tgc_c_xrb_nn_plat_type = iss::arch::riscv_hart_m_p; #endif #ifdef CORE_TGC_D #include "riscv_hart_mu_p.h" -#include "tgc_d.h" +#include using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; #endif #ifdef CORE_TGC_D_XRB_MAC #include "riscv_hart_mu_p.h" -#include "tgc_d_xrb_mac.h" +#include using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p; #endif #ifdef CORE_TGC_D_XRB_NN #include "riscv_hart_mu_p.h" -#include "tgc_d_xrb_nn.h" +#include using tgc_d_xrb_nn_plat_type = iss::arch::riscv_hart_mu_p; #endif #ifdef CORE_TGC_E #include "riscv_hart_mu_p.h" -#include "tgc_e.h" +#include using tgc_e_plat_type = iss::arch::riscv_hart_mu_p; #endif #ifdef CORE_TGC_X #include "riscv_hart_mu_p.h" -#include "tgc_x.h" +#include using tgc_x_plat_type = iss::arch::riscv_hart_mu_p; #endif From 52ed8b81a6039ee6819cd8b7b5c9a6c773755add Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 30 May 2022 14:08:02 +0200 Subject: [PATCH 018/184] fixed template to work with previous code generator --- gen_input/templates/interp/CORENAME.cpp.gtl | 7 +- src/vm/interp/vm_tgc_c.cpp | 950 ++++++++++---------- 2 files changed, 478 insertions(+), 479 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index c643699..6041e9b 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -314,8 +314,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co <%}}%>// calculate next pc value *NEXT_PC = *PC + ${instr.length/8}; // execute instruction - <%instr.behavior.eachLine{%>${it} - <%}%>TRAP_${instr.name}:break; + try { + <%instr.behavior.eachLine{%>${it} + <%}%> + } catch(...){} + TRAP_${instr.name}:break; }// @suppress("No break at end of case")<%}%> default: { *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index b219e2e..9866654 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -396,11 +396,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)imm; - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)imm; + + } catch(...){} TRAP_LUI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::AUIPC: { @@ -418,11 +417,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *PC + (int32_t)imm; - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + (int32_t)imm; + + } catch(...){} TRAP_AUIPC:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::JAL: { @@ -440,18 +438,18 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { if(imm % traits::INSTR_ALIGNMENT) { raise(0, 0); } else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *PC + 4; - } - *NEXT_PC = *PC + (int32_t)sext<21>(imm); - super::ex_info.branch_taken=true; + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + 4; + pc_assign(*NEXT_PC) = *PC + (int32_t)sext<21>(imm); } } + + } catch(...){} TRAP_JAL:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::JALR: { @@ -470,19 +468,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { int32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 1; if(new_pc % traits::INSTR_ALIGNMENT) { raise(0, 0); } else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *PC + 4; - } - *NEXT_PC = new_pc & ~ 0x1; - super::ex_info.branch_taken=true; + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + 4; + pc_assign(*NEXT_PC) = new_pc & ~ 0x1; } } + + } catch(...){} TRAP_JALR:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BEQ: { @@ -501,17 +499,17 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } + try { + { + if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); } } + + } catch(...){} TRAP_BEQ:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BNE: { @@ -530,17 +528,17 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } + try { + { + if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); } } + + } catch(...){} TRAP_BNE:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BLT: { @@ -559,17 +557,17 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } + try { + { + if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); } } + + } catch(...){} TRAP_BLT:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BGE: { @@ -588,17 +586,17 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } + try { + { + if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); } } + + } catch(...){} TRAP_BGE:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BLTU: { @@ -617,17 +615,17 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } + try { + { + if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); } } + + } catch(...){} TRAP_BLTU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BGEU: { @@ -646,17 +644,17 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } + try { + { + if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); } } + + } catch(...){} TRAP_BGEU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::LB: { @@ -675,13 +673,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - int8_t res = (int8_t)super::template read_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); - if(this->core.trap_state) goto TRAP_LB; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = res; - } + try { + { + int8_t res = (int8_t)readSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; } + + } catch(...){} TRAP_LB:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::LH: { @@ -700,14 +698,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - int16_t res = (int16_t)super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state) goto TRAP_LH; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = res; - } + int16_t res = (int16_t)readSpace2(traits::MEM, load_address); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; } + + } catch(...){} TRAP_LH:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::LW: { @@ -726,14 +724,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - int32_t res = (int32_t)super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state) goto TRAP_LW; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (uint32_t)res; - } + int32_t res = (int32_t)readSpace4(traits::MEM, load_address); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (uint32_t)res; } + + } catch(...){} TRAP_LW:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::LBU: { @@ -752,13 +750,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - uint8_t res = (uint8_t)super::template read_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); - if(this->core.trap_state) goto TRAP_LBU; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = res; - } + try { + { + uint8_t res = (uint8_t)readSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; } + + } catch(...){} TRAP_LBU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::LHU: { @@ -777,14 +775,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - uint16_t res = (uint16_t)super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state) goto TRAP_LHU; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = res; - } + uint16_t res = (uint16_t)readSpace2(traits::MEM, load_address); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; } + + } catch(...){} TRAP_LHU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SB: { @@ -803,10 +801,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - super::template write_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm), (int8_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state) goto TRAP_SB; - } + try { + writeSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm), (int8_t)*(X+rs2 % traits::RFS)); + + } catch(...){} TRAP_SB:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SH: { @@ -825,11 +823,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state) goto TRAP_SH; + writeSpace2(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); } + + } catch(...){} TRAP_SH:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SW: { @@ -848,11 +848,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, *(X+rs2 % traits::RFS)); - if(this->core.trap_state) goto TRAP_SW; + writeSpace4(traits::MEM, store_address, *(X+rs2 % traits::RFS)); } + + } catch(...){} TRAP_SW:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::ADDI: { @@ -871,11 +873,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + + } catch(...){} TRAP_ADDI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SLTI: { @@ -894,11 +895,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm)? 1 : 0; - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm)? 1 : 0; + + } catch(...){} TRAP_SLTI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SLTIU: { @@ -917,11 +917,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; + + } catch(...){} TRAP_SLTIU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::XORI: { @@ -940,11 +939,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm); + + } catch(...){} TRAP_XORI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::ORI: { @@ -963,11 +961,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm); + + } catch(...){} TRAP_ORI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::ANDI: { @@ -986,11 +983,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm); + + } catch(...){} TRAP_ANDI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SLLI: { @@ -1009,16 +1005,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << shamt; - } - } - } + try { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << shamt; + } + + } catch(...){} TRAP_SLLI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SRLI: { @@ -1037,16 +1032,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> shamt; - } - } - } + try { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> shamt; + } + + } catch(...){} TRAP_SRLI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SRAI: { @@ -1065,16 +1059,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; - } - } - } + try { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; + } + + } catch(...){} TRAP_SRAI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::ADD: { @@ -1093,11 +1086,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS); + + } catch(...){} TRAP_ADD:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SUB: { @@ -1116,11 +1108,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS); + + } catch(...){} TRAP_SUB:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SLL: { @@ -1139,11 +1130,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + + } catch(...){} TRAP_SLL:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SLT: { @@ -1162,11 +1152,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0; - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0; + + } catch(...){} TRAP_SLT:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SLTU: { @@ -1185,11 +1174,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0; - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0; + + } catch(...){} TRAP_SLTU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::XOR: { @@ -1208,11 +1196,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS); + + } catch(...){} TRAP_XOR:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SRL: { @@ -1231,11 +1218,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + + } catch(...){} TRAP_SRL:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SRA: { @@ -1254,11 +1240,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + + } catch(...){} TRAP_SRA:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::OR: { @@ -1277,11 +1262,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS); + + } catch(...){} TRAP_OR:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::AND: { @@ -1300,11 +1284,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS); + + } catch(...){} TRAP_AND:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::FENCE: { @@ -1324,10 +1307,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - super::template write_mem(traits::FENCE, traits::fence, pred << 4 | succ); - if(this->core.trap_state) goto TRAP_FENCE; - } + try { + writeSpace1(traits::FENCE, traits::fence, pred << 4 | succ); + + } catch(...){} TRAP_FENCE:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::ECALL: { @@ -1339,9 +1322,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - raise(0, 11); - } + try { + raise(0, 11); + + } catch(...){} TRAP_ECALL:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::EBREAK: { @@ -1353,9 +1337,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - raise(0, 3); - } + try { + raise(0, 3); + + } catch(...){} TRAP_EBREAK:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::URET: { @@ -1367,9 +1352,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - leave(0); - } + try { + leave(0); + + } catch(...){} TRAP_URET:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SRET: { @@ -1381,9 +1367,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - leave(1); - } + try { + leave(1); + + } catch(...){} TRAP_SRET:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::MRET: { @@ -1395,9 +1382,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - leave(3); - } + try { + leave(3); + + } catch(...){} TRAP_MRET:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::WFI: { @@ -1409,9 +1397,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - wait(1); - } + try { + wait(1); + + } catch(...){} TRAP_WFI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::DRET: { @@ -1427,16 +1416,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - if(*PRIV < 4) { - raise(0, 2); - } + try { + { + if(*PRIV < 4) raise(0, 2); else { - *NEXT_PC = *DPC; - super::ex_info.branch_taken=true; + pc_assign(*NEXT_PC) = *DPC; *PRIV &= 0x3; } } + + } catch(...){} TRAP_DRET:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRW: { @@ -1455,20 +1444,20 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { uint32_t xrs1 = *(X+rs1 % traits::RFS); if((rd % traits::RFS) != 0) { - uint32_t xrd = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRW; - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.trap_state) goto TRAP_CSRRW; + uint32_t xrd = readSpace4(traits::CSR, csr); + writeSpace4(traits::CSR, csr, xrs1); *(X+rd % traits::RFS) = xrd; } else { - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.trap_state) goto TRAP_CSRRW; + writeSpace4(traits::CSR, csr, xrs1); } } + + } catch(...){} TRAP_CSRRW:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRS: { @@ -1487,18 +1476,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - uint32_t xrd = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRS; + try { + { + uint32_t xrd = readSpace4(traits::CSR, csr); uint32_t xrs1 = *(X+rs1 % traits::RFS); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd | xrs1); - if(this->core.trap_state) goto TRAP_CSRRS; - } - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = xrd; - } + if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd | xrs1); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; } + + } catch(...){} TRAP_CSRRS:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRC: { @@ -1517,18 +1503,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - uint32_t xrd = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRC; + try { + { + uint32_t xrd = readSpace4(traits::CSR, csr); uint32_t xrs1 = *(X+rs1 % traits::RFS); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); - if(this->core.trap_state) goto TRAP_CSRRC; - } - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = xrd; - } + if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd & ~ xrs1); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; } + + } catch(...){} TRAP_CSRRC:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRWI: { @@ -1547,15 +1530,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - uint32_t xrd = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRWI; - super::template write_mem(traits::CSR, csr, (uint32_t)zimm); - if(this->core.trap_state) goto TRAP_CSRRWI; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = xrd; - } + try { + { + uint32_t xrd = readSpace4(traits::CSR, csr); + writeSpace4(traits::CSR, csr, (uint32_t)zimm); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; } + + } catch(...){} TRAP_CSRRWI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRSI: { @@ -1574,17 +1556,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - uint32_t xrd = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRSI; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); - if(this->core.trap_state) goto TRAP_CSRRSI; - } - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = xrd; - } + try { + { + uint32_t xrd = readSpace4(traits::CSR, csr); + if(zimm != 0) writeSpace4(traits::CSR, csr, xrd | (uint32_t)zimm); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; } + + } catch(...){} TRAP_CSRRSI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRCI: { @@ -1603,17 +1582,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - uint32_t xrd = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRCI; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); - if(this->core.trap_state) goto TRAP_CSRRCI; - } - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = xrd; - } + try { + { + uint32_t xrd = readSpace4(traits::CSR, csr); + if(zimm != 0) writeSpace4(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; } + + } catch(...){} TRAP_CSRRCI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::FENCE_I: { @@ -1631,10 +1607,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { - super::template write_mem(traits::FENCE, traits::fencei, imm); - if(this->core.trap_state) goto TRAP_FENCE_I; - } + try { + writeSpace2(traits::FENCE, traits::fencei, imm); + + } catch(...){} TRAP_FENCE_I:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::MUL: { @@ -1653,12 +1629,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { if((rd % traits::RFS) != 0) { int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); *(X+rd % traits::RFS) = (uint32_t)res; } } + + } catch(...){} TRAP_MUL:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::MULH: { @@ -1677,12 +1656,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { if((rd % traits::RFS) != 0) { int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); } } + + } catch(...){} TRAP_MULH:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::MULHSU: { @@ -1701,12 +1683,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { if((rd % traits::RFS) != 0) { int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); } } + + } catch(...){} TRAP_MULHSU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::MULHU: { @@ -1725,12 +1710,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { if((rd % traits::RFS) != 0) { uint64_t res = (uint64_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); } } + + } catch(...){} TRAP_MULHU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::DIV: { @@ -1749,22 +1737,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { if((rd % traits::RFS) != 0) { if(*(X+rs2 % traits::RFS) != 0) { uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) { - *(X+rd % traits::RFS) = MMIN; - } - else { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) / (int32_t)*(X+rs2 % traits::RFS); - } - } - else { - *(X+rd % traits::RFS) = - 1; + if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) *(X+rd % traits::RFS) = MMIN; + else *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) / (int32_t)*(X+rs2 % traits::RFS); } + else *(X+rd % traits::RFS) = - 1; } } + + } catch(...){} TRAP_DIV:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::DIVU: { @@ -1783,16 +1768,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) / *(X+rs2 % traits::RFS); - } - else { - *(X+rd % traits::RFS) = - 1; - } + if(*(X+rs2 % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) / *(X+rs2 % traits::RFS); + else *(X+rd % traits::RFS) = - 1; } } + + } catch(...){} TRAP_DIVU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::REM: { @@ -1811,22 +1795,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { if((rd % traits::RFS) != 0) { if(*(X+rs2 % traits::RFS) != 0) { uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) { - *(X+rd % traits::RFS) = 0; - } - else { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) % (int32_t)*(X+rs2 % traits::RFS); - } - } - else { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); + if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) *(X+rd % traits::RFS) = 0; + else *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) % (int32_t)*(X+rs2 % traits::RFS); } + else *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); } } + + } catch(...){} TRAP_REM:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::REMU: { @@ -1845,16 +1826,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction - { + try { + { if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) % *(X+rs2 % traits::RFS); - } - else { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); - } + if(*(X+rs2 % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) % *(X+rs2 % traits::RFS); + else *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); } } + + } catch(...){} TRAP_REMU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CADDI4SPN: { @@ -1872,14 +1852,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if(imm) { - *(X+rd + 8) = *(X+2) + imm; - } - else { - raise(0, 2); - } - } + try { + if(imm) *(X+rd + 8) = *(X+2) + imm; + else raise(0, 2); + + } catch(...){} TRAP_CADDI4SPN:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CLW: { @@ -1898,11 +1875,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { uint32_t load_address = *(X+rs1 + 8) + uimm; - *(X+rd + 8) = (int32_t)super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state) goto TRAP_CLW; + *(X+rd + 8) = (int32_t)readSpace4(traits::MEM, load_address); } + + } catch(...){} TRAP_CLW:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSW: { @@ -1921,11 +1900,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { uint32_t load_address = *(X+rs1 + 8) + uimm; - super::template write_mem(traits::MEM, load_address, *(X+rs2 + 8)); - if(this->core.trap_state) goto TRAP_CSW; + writeSpace4(traits::MEM, load_address, *(X+rs2 + 8)); } + + } catch(...){} TRAP_CSW:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CADDI: { @@ -1943,9 +1924,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) + (int8_t)sext<6>(imm); - } + try { + *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) + (int8_t)sext<6>(imm); + + } catch(...){} TRAP_CADDI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CNOP: { @@ -1958,8 +1940,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { } + + } catch(...){} TRAP_CNOP:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CJAL: { @@ -1976,11 +1961,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { *(X+1) = *PC + 2; - *NEXT_PC = *PC + (int16_t)sext<12>(imm); - super::ex_info.branch_taken=true; + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); } + + } catch(...){} TRAP_CJAL:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CLI: { @@ -1998,11 +1985,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd) = (uint32_t)(int8_t)sext<1>(imm); - } + try { + { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int8_t)sext<6>(imm); } + + } catch(...){} TRAP_CLI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CLUI: { @@ -2020,14 +2008,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if(imm == 0) { - raise(0, 2); - } - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)sext<18>(imm); - } + try { + { + if(imm == 0) raise(0, 2); + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)sext<18>(imm); } + + } catch(...){} TRAP_CLUI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CADDI16SP: { @@ -2044,14 +2031,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if(nzimm) { - *(X+2) = *(X+2) + (int16_t)sext<10>(nzimm); - } - else { - raise(0, 2); - } - } + try { + if(nzimm) *(X+2) = *(X+2) + (int16_t)sext<10>(nzimm); + else raise(0, 2); + + } catch(...){} TRAP_CADDI16SP:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::__reserved_clui: { @@ -2064,9 +2048,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - raise(0, 2); - } + try { + raise(0, 2); + + } catch(...){} TRAP___reserved_clui:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRLI: { @@ -2084,10 +2069,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { uint8_t rs1_idx = rs1 + 8; *(X+rs1_idx) = *(X+rs1_idx) >> shamt; } + + } catch(...){} TRAP_CSRLI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRAI: { @@ -2105,18 +2093,17 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if(shamt) { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; - } - else { - if(traits::XLEN == 128) { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; - } - } - } + try { + if(shamt) { + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; + } + else if(traits::XLEN == 128) { + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; + } + + } catch(...){} TRAP_CSRAI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CANDI: { @@ -2134,10 +2121,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { uint8_t rs1_idx = rs1 + 8; *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm); } + + } catch(...){} TRAP_CANDI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSUB: { @@ -2155,10 +2145,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) - *(X+rs2 + 8); } + + } catch(...){} TRAP_CSUB:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CXOR: { @@ -2176,10 +2169,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) ^ *(X+rs2 + 8); } + + } catch(...){} TRAP_CXOR:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::COR: { @@ -2197,10 +2193,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) | *(X+rs2 + 8); } + + } catch(...){} TRAP_COR:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CAND: { @@ -2218,10 +2217,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { uint8_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) & *(X+rs2 + 8); } + + } catch(...){} TRAP_CAND:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CJ: { @@ -2237,10 +2239,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - *NEXT_PC = *PC + (int16_t)sext<12>(imm); - super::ex_info.branch_taken=true; - } + try { + pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); + + } catch(...){} TRAP_CJ:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CBEQZ: { @@ -2258,12 +2260,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if(*(X+rs1 + 8) == 0) { - *NEXT_PC = *PC + (int16_t)sext<9>(imm); - super::ex_info.branch_taken=true; - } - } + try { + if(*(X+rs1 + 8) == 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); + + } catch(...){} TRAP_CBEQZ:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CBNEZ: { @@ -2281,12 +2281,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if(*(X+rs1 + 8) != 0) { - *NEXT_PC = *PC + (int16_t)sext<9>(imm); - super::ex_info.branch_taken=true; - } - } + try { + if(*(X+rs1 + 8) != 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); + + } catch(...){} TRAP_CBNEZ:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSLLI: { @@ -2304,11 +2302,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if(nzuimm) { - *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) << nzuimm; - } - } + try { + if(nzuimm) *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) << nzuimm; + + } catch(...){} TRAP_CSLLI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CLWSP: { @@ -2326,16 +2323,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if(rd) { - uint32_t offs = *(X+2) + uimm; - *(X+rd % traits::RFS) = (int32_t)super::template read_mem(traits::MEM, offs); - if(this->core.trap_state) goto TRAP_CLWSP; - } - else { - raise(0, 2); - } - } + try { + if(rd) { + uint32_t offs = *(X+2) + uimm; + *(X+rd % traits::RFS) = (int32_t)readSpace4(traits::MEM, offs); + } + else raise(0, 2); + + } catch(...){} TRAP_CLWSP:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CMV: { @@ -2353,11 +2348,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs2 % traits::RFS); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs2 % traits::RFS); + + } catch(...){} TRAP_CMV:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CJR: { @@ -2374,15 +2368,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if(rs1) { - *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; - super::ex_info.branch_taken=true; - } - else { - raise(0, 2); - } - } + try { + if(rs1) pc_assign(*NEXT_PC) = *(X+rs1 % traits::RFS) & ~ 0x1; + else raise(0, 2); + + } catch(...){} TRAP_CJR:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::__reserved_cmv: { @@ -2394,9 +2384,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - raise(0, 2); - } + try { + raise(0, 2); + + } catch(...){} TRAP___reserved_cmv:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CADD: { @@ -2414,11 +2405,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rd % traits::RFS) + *(X+rs2 % traits::RFS); - } - } + try { + if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rd % traits::RFS) + *(X+rs2 % traits::RFS); + + } catch(...){} TRAP_CADD:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CJALR: { @@ -2435,12 +2425,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { int32_t new_pc = *(X+rs1 % traits::RFS); *(X+1) = *PC + 2; - *NEXT_PC = new_pc & ~ 0x1; - super::ex_info.branch_taken=true; + pc_assign(*NEXT_PC) = new_pc & ~ 0x1; } + + } catch(...){} TRAP_CJALR:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CEBREAK: { @@ -2452,9 +2444,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - raise(0, 3); - } + try { + raise(0, 3); + + } catch(...){} TRAP_CEBREAK:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSWSP: { @@ -2472,11 +2465,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { + try { + { uint32_t offs = *(X+2) + uimm; - super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state) goto TRAP_CSWSP; + writeSpace4(traits::MEM, offs, (uint32_t)*(X+rs2 % traits::RFS)); } + + } catch(...){} TRAP_CSWSP:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::DII: { @@ -2488,9 +2483,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // used registers// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction - { - raise(0, 2); - } + try { + raise(0, 2); + + } catch(...){} TRAP_DII:break; }// @suppress("No break at end of case") default: { From 5d481eb79db9a82753bc869d790908f010ac8a68 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 30 May 2022 22:04:16 +0200 Subject: [PATCH 019/184] fix generation of non-exception code --- gen_input/templates/interp/CORENAME.cpp.gtl | 34 +++++++++------------ 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 6041e9b..56dc1a1 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -301,25 +301,21 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> case arch::traits::opcode_e::${instr.name}: { - <%instr.fields.eachLine{%>${it} - <%}%>if(this->disass_enabled){ - /* generate console output when executing the command */ - <%instr.disass.eachLine{%>${it} - <%}%> - } - // used registers<%instr.usedVariables.each{ k,v-> - if(v.isArray) {%> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); - <%}}%>// calculate next pc value - *NEXT_PC = *PC + ${instr.length/8}; - // execute instruction - try { - <%instr.behavior.eachLine{%>${it} - <%}%> - } catch(...){} - TRAP_${instr.name}:break; - }// @suppress("No break at end of case")<%}%> + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate console output when executing the command */<%instr.disass.eachLine{%> + ${it}<%}%> + } + // used registers<%instr.usedVariables.each{ k,v-> + if(v.isArray) {%> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); + <%}}%>// calculate next pc value + *NEXT_PC = *PC + ${instr.length/8}; + // execute instruction<%instr.behavior.eachLine{%> + ${it}<%}%> + TRAP_${instr.name}:break; + }// @suppress("No break at end of case")<%}%> default: { *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); raise(0, 2); From 31fb51de955bcb349a4d64a526be00501456765e Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 30 May 2022 22:15:44 +0200 Subject: [PATCH 020/184] update tgc_c generated code --- src/vm/interp/vm_tgc_c.cpp | 3877 ++++++++++++++++++------------------ 1 file changed, 1902 insertions(+), 1975 deletions(-) diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 9866654..c8b2461 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -382,2113 +382,2040 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); switch(inst_id){ case arch::traits::opcode_e::LUI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)imm; - - } catch(...){} - TRAP_LUI:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)imm; + } + } + TRAP_LUI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::AUIPC: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + (int32_t)imm; - - } catch(...){} - TRAP_AUIPC:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *PC + (int32_t)imm; + } + } + TRAP_AUIPC:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::JAL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + 4; - pc_assign(*NEXT_PC) = *PC + (int32_t)sext<21>(imm); - } - } - - } catch(...){} - TRAP_JAL:break; - }// @suppress("No break at end of case") + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *PC + 4; + } + *NEXT_PC = *PC + (int32_t)sext<21>(imm); + super::ex_info.branch_taken=true; + } + } + TRAP_JAL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::JALR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - int32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 1; - if(new_pc % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *PC + 4; - pc_assign(*NEXT_PC) = new_pc & ~ 0x1; - } - } - - } catch(...){} - TRAP_JALR:break; - }// @suppress("No break at end of case") + int32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 1; + if(new_pc % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *PC + 4; + } + *NEXT_PC = new_pc & ~ 0x1; + super::ex_info.branch_taken=true; + } + } + TRAP_JALR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BEQ: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } - - } catch(...){} - TRAP_BEQ:break; - }// @suppress("No break at end of case") + if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + TRAP_BEQ:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BNE: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } - - } catch(...){} - TRAP_BNE:break; - }// @suppress("No break at end of case") + if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + TRAP_BNE:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BLT: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } - - } catch(...){} - TRAP_BLT:break; - }// @suppress("No break at end of case") + if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + TRAP_BLT:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BGE: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } - - } catch(...){} - TRAP_BGE:break; - }// @suppress("No break at end of case") + if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + TRAP_BGE:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BLTU: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } - - } catch(...){} - TRAP_BLTU:break; - }// @suppress("No break at end of case") + if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + TRAP_BLTU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::BGEU: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); - } - } - - } catch(...){} - TRAP_BGEU:break; - }// @suppress("No break at end of case") + if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + TRAP_BGEU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::LB: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - int8_t res = (int8_t)readSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; - } - - } catch(...){} - TRAP_LB:break; - }// @suppress("No break at end of case") + uint8_t read_res = super::template read_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); + if(this->core.trap_state) goto TRAP_LB; + int8_t res = (int8_t)read_res; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = res; + } + } + TRAP_LB:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::LH: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - int16_t res = (int16_t)readSpace2(traits::MEM, load_address); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; - } - - } catch(...){} - TRAP_LH:break; - }// @suppress("No break at end of case") + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint16_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state) goto TRAP_LH; + int16_t res = (int16_t)read_res; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = res; + } + } + TRAP_LH:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::LW: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - int32_t res = (int32_t)readSpace4(traits::MEM, load_address); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (uint32_t)res; - } - - } catch(...){} - TRAP_LW:break; - }// @suppress("No break at end of case") + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint32_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state) goto TRAP_LW; + int32_t res = (int32_t)read_res; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (uint32_t)res; + } + } + TRAP_LW:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::LBU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint8_t res = (uint8_t)readSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; - } - - } catch(...){} - TRAP_LBU:break; - }// @suppress("No break at end of case") + uint8_t read_res = super::template read_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); + if(this->core.trap_state) goto TRAP_LBU; + uint8_t res = (uint8_t)read_res; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = res; + } + } + TRAP_LBU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::LHU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - uint16_t res = (uint16_t)readSpace2(traits::MEM, load_address); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = res; - } - - } catch(...){} - TRAP_LHU:break; - }// @suppress("No break at end of case") + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint16_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state) goto TRAP_LHU; + uint16_t res = (uint16_t)read_res; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = res; + } + } + TRAP_LHU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SB: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - writeSpace1(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm), (int8_t)*(X+rs2 % traits::RFS)); - - } catch(...){} - TRAP_SB:break; - }// @suppress("No break at end of case") + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + super::template write_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm), (int8_t)*(X+rs2 % traits::RFS)); + if(this->core.trap_state) goto TRAP_SB; + } + TRAP_SB:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SH: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - writeSpace2(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); - } - - } catch(...){} - TRAP_SH:break; - }// @suppress("No break at end of case") + uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + super::template write_mem(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); + if(this->core.trap_state) goto TRAP_SH; + } + TRAP_SH:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SW: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - writeSpace4(traits::MEM, store_address, *(X+rs2 % traits::RFS)); - } - - } catch(...){} - TRAP_SW:break; - }// @suppress("No break at end of case") + uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + super::template write_mem(traits::MEM, store_address, *(X+rs2 % traits::RFS)); + if(this->core.trap_state) goto TRAP_SW; + } + TRAP_SW:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::ADDI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - - } catch(...){} - TRAP_ADDI:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + } + } + TRAP_ADDI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLTI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm)? 1 : 0; - - } catch(...){} - TRAP_SLTI:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm)? 1 : 0; + } + } + TRAP_SLTI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLTIU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; - - } catch(...){} - TRAP_SLTIU:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; + } + } + TRAP_SLTIU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::XORI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm); - - } catch(...){} - TRAP_XORI:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm); + } + } + TRAP_XORI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::ORI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm); - - } catch(...){} - TRAP_ORI:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm); + } + } + TRAP_ORI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::ANDI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm); - - } catch(...){} - TRAP_ANDI:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm); + } + } + TRAP_ANDI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLLI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << shamt; - } - - } catch(...){} - TRAP_SLLI:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << shamt; + } + } + } + TRAP_SLLI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SRLI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> shamt; - } - - } catch(...){} - TRAP_SRLI:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> shamt; + } + } + } + TRAP_SRLI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SRAI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; - } - - } catch(...){} - TRAP_SRAI:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(shamt > 31) { + raise(0, 0); + } + else { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; + } + } + } + TRAP_SRAI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::ADD: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS); - - } catch(...){} - TRAP_ADD:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS); + } + } + TRAP_ADD:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SUB: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS); - - } catch(...){} - TRAP_SUB:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS); + } + } + TRAP_SUB:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); - - } catch(...){} - TRAP_SLL:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } + } + TRAP_SLL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLT: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0; - - } catch(...){} - TRAP_SLT:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0; + } + } + TRAP_SLT:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SLTU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0; - - } catch(...){} - TRAP_SLTU:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0; + } + } + TRAP_SLTU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::XOR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS); - - } catch(...){} - TRAP_XOR:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS); + } + } + TRAP_XOR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SRL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); - - } catch(...){} - TRAP_SRL:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } + } + TRAP_SRL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SRA: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); - - } catch(...){} - TRAP_SRA:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } + } + TRAP_SRA:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::OR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS); - - } catch(...){} - TRAP_OR:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS); + } + } + TRAP_OR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::AND: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS); - - } catch(...){} - TRAP_AND:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS); + } + } + TRAP_AND:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::FENCE: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - uint8_t fm = ((bit_sub<28,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), - fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - writeSpace1(traits::FENCE, traits::fence, pred << 4 | succ); - - } catch(...){} - TRAP_FENCE:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + uint8_t fm = ((bit_sub<28,4>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), + fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + super::template write_mem(traits::FENCE, traits::fence, pred << 4 | succ); + if(this->core.trap_state) goto TRAP_FENCE; + } + TRAP_FENCE:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::ECALL: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ecall"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - raise(0, 11); - - } catch(...){} - TRAP_ECALL:break; - }// @suppress("No break at end of case") + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "ecall"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + raise(0, 11); + } + TRAP_ECALL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::EBREAK: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ebreak"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - raise(0, 3); - - } catch(...){} - TRAP_EBREAK:break; - }// @suppress("No break at end of case") + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "ebreak"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + raise(0, 3); + } + TRAP_EBREAK:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::URET: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "uret"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - leave(0); - - } catch(...){} - TRAP_URET:break; - }// @suppress("No break at end of case") + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "uret"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + leave(0); + } + TRAP_URET:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::SRET: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "sret"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - leave(1); - - } catch(...){} - TRAP_SRET:break; - }// @suppress("No break at end of case") + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "sret"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + leave(1); + } + TRAP_SRET:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::MRET: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "mret"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - leave(3); - - } catch(...){} - TRAP_MRET:break; - }// @suppress("No break at end of case") + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "mret"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + leave(3); + } + TRAP_MRET:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::WFI: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "wfi"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - wait(1); - - } catch(...){} - TRAP_WFI:break; - }// @suppress("No break at end of case") + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "wfi"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + wait(1); + } + TRAP_WFI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::DRET: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "dret"); - - } - // used registers - auto* PRIV = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PRIV]); - - auto* DPC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::DPC]); - // calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "dret"); + } + // used registers + auto* PRIV = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PRIV]); + + auto* DPC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::DPC]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if(*PRIV < 4) raise(0, 2); - else { - pc_assign(*NEXT_PC) = *DPC; - *PRIV &= 0x3; - } - } - - } catch(...){} - TRAP_DRET:break; - }// @suppress("No break at end of case") + if(*PRIV < 4) { + raise(0, 2); + } + else { + *NEXT_PC = *DPC; + super::ex_info.branch_taken=true; + *PRIV &= 0x3; + } + } + TRAP_DRET:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRW: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint32_t xrs1 = *(X+rs1 % traits::RFS); - if((rd % traits::RFS) != 0) { - uint32_t xrd = readSpace4(traits::CSR, csr); - writeSpace4(traits::CSR, csr, xrs1); - *(X+rd % traits::RFS) = xrd; - } - else { - writeSpace4(traits::CSR, csr, xrs1); - } - } - - } catch(...){} - TRAP_CSRRW:break; - }// @suppress("No break at end of case") + uint32_t xrs1 = *(X+rs1 % traits::RFS); + if((rd % traits::RFS) != 0) { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRW; + uint32_t xrd = read_res; + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.trap_state) goto TRAP_CSRRW; + *(X+rd % traits::RFS) = xrd; + } + else { + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.trap_state) goto TRAP_CSRRW; + } + } + TRAP_CSRRW:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRS: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint32_t xrd = readSpace4(traits::CSR, csr); - uint32_t xrs1 = *(X+rs1 % traits::RFS); - if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd | xrs1); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; - } - - } catch(...){} - TRAP_CSRRS:break; - }// @suppress("No break at end of case") + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRS; + uint32_t xrd = read_res; + uint32_t xrs1 = *(X+rs1 % traits::RFS); + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd | xrs1); + if(this->core.trap_state) goto TRAP_CSRRS; + } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = xrd; + } + } + TRAP_CSRRS:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRC: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint32_t xrd = readSpace4(traits::CSR, csr); - uint32_t xrs1 = *(X+rs1 % traits::RFS); - if(rs1 != 0) writeSpace4(traits::CSR, csr, xrd & ~ xrs1); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; - } - - } catch(...){} - TRAP_CSRRC:break; - }// @suppress("No break at end of case") + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRC; + uint32_t xrd = read_res; + uint32_t xrs1 = *(X+rs1 % traits::RFS); + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); + if(this->core.trap_state) goto TRAP_CSRRC; + } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = xrd; + } + } + TRAP_CSRRC:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRWI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint32_t xrd = readSpace4(traits::CSR, csr); - writeSpace4(traits::CSR, csr, (uint32_t)zimm); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; - } - - } catch(...){} - TRAP_CSRRWI:break; - }// @suppress("No break at end of case") + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRWI; + uint32_t xrd = read_res; + super::template write_mem(traits::CSR, csr, (uint32_t)zimm); + if(this->core.trap_state) goto TRAP_CSRRWI; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = xrd; + } + } + TRAP_CSRRWI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRSI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint32_t xrd = readSpace4(traits::CSR, csr); - if(zimm != 0) writeSpace4(traits::CSR, csr, xrd | (uint32_t)zimm); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; - } - - } catch(...){} - TRAP_CSRRSI:break; - }// @suppress("No break at end of case") + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRSI; + uint32_t xrd = read_res; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); + if(this->core.trap_state) goto TRAP_CSRRSI; + } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = xrd; + } + } + TRAP_CSRRSI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRCI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - uint32_t xrd = readSpace4(traits::CSR, csr); - if(zimm != 0) writeSpace4(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = xrd; - } - - } catch(...){} - TRAP_CSRRCI:break; - }// @suppress("No break at end of case") + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state) goto TRAP_CSRRCI; + uint32_t xrd = read_res; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); + if(this->core.trap_state) goto TRAP_CSRRCI; + } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = xrd; + } + } + TRAP_CSRRCI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::FENCE_I: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), - fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { - writeSpace2(traits::FENCE, traits::fencei, imm); - - } catch(...){} - TRAP_FENCE_I:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), + fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + super::template write_mem(traits::FENCE, traits::fencei, imm); + if(this->core.trap_state) goto TRAP_FENCE_I; + } + TRAP_FENCE_I:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::MUL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if((rd % traits::RFS) != 0) { - int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); - *(X+rd % traits::RFS) = (uint32_t)res; - } - } - - } catch(...){} - TRAP_MUL:break; - }// @suppress("No break at end of case") + if((rd % traits::RFS) != 0) { + int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); + *(X+rd % traits::RFS) = (uint32_t)res; + } + } + TRAP_MUL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::MULH: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if((rd % traits::RFS) != 0) { - int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); - *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); - } - } - - } catch(...){} - TRAP_MULH:break; - }// @suppress("No break at end of case") + if((rd % traits::RFS) != 0) { + int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); + *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); + } + } + TRAP_MULH:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::MULHSU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if((rd % traits::RFS) != 0) { - int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); - *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); - } - } - - } catch(...){} - TRAP_MULHSU:break; - }// @suppress("No break at end of case") + if((rd % traits::RFS) != 0) { + int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); + *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); + } + } + TRAP_MULHSU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::MULHU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if((rd % traits::RFS) != 0) { - uint64_t res = (uint64_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); - *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); - } - } - - } catch(...){} - TRAP_MULHU:break; - }// @suppress("No break at end of case") + if((rd % traits::RFS) != 0) { + uint64_t res = (uint64_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); + *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); + } + } + TRAP_MULHU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::DIV: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { - uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) *(X+rd % traits::RFS) = MMIN; - else *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) / (int32_t)*(X+rs2 % traits::RFS); - } - else *(X+rd % traits::RFS) = - 1; - } - } - - } catch(...){} - TRAP_DIV:break; - }// @suppress("No break at end of case") + if((rd % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) { + uint32_t MMIN = 1 << (traits::XLEN - 1); + if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) { + *(X+rd % traits::RFS) = MMIN; + } + else { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) / (int32_t)*(X+rs2 % traits::RFS); + } + } + else { + *(X+rd % traits::RFS) = - 1; + } + } + } + TRAP_DIV:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::DIVU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) / *(X+rs2 % traits::RFS); - else *(X+rd % traits::RFS) = - 1; - } - } - - } catch(...){} - TRAP_DIVU:break; - }// @suppress("No break at end of case") + if((rd % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) / *(X+rs2 % traits::RFS); + } + else { + *(X+rd % traits::RFS) = - 1; + } + } + } + TRAP_DIVU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::REM: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { - uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) *(X+rd % traits::RFS) = 0; - else *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) % (int32_t)*(X+rs2 % traits::RFS); - } - else *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); - } - } - - } catch(...){} - TRAP_REM:break; - }// @suppress("No break at end of case") + if((rd % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) { + uint32_t MMIN = 1 << (traits::XLEN - 1); + if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) { + *(X+rd % traits::RFS) = 0; + } + else { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) % (int32_t)*(X+rs2 % traits::RFS); + } + } + else { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); + } + } + } + TRAP_REM:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::REMU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - try { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction { - if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) % *(X+rs2 % traits::RFS); - else *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); - } - } - - } catch(...){} - TRAP_REMU:break; - }// @suppress("No break at end of case") + if((rd % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) % *(X+rs2 % traits::RFS); + } + else { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); + } + } + } + TRAP_REMU:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CADDI4SPN: { - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(imm) *(X+rd + 8) = *(X+2) + imm; - else raise(0, 2); - - } catch(...){} - TRAP_CADDI4SPN:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<2,3>(instr))); + uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(imm) { + *(X+rd + 8) = *(X+2) + imm; + } + else { + raise(0, 2); + } + } + TRAP_CADDI4SPN:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CLW: { - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint8_t rd = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), + fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - uint32_t load_address = *(X+rs1 + 8) + uimm; - *(X+rd + 8) = (int32_t)readSpace4(traits::MEM, load_address); - } - - } catch(...){} - TRAP_CLW:break; - }// @suppress("No break at end of case") + uint32_t load_address = *(X+rs1 + 8) + uimm; + uint32_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state) goto TRAP_CLW; + *(X+rd + 8) = (int32_t)read_res; + } + TRAP_CLW:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSW: { - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), + fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - uint32_t load_address = *(X+rs1 + 8) + uimm; - writeSpace4(traits::MEM, load_address, *(X+rs2 + 8)); - } - - } catch(...){} - TRAP_CSW:break; - }// @suppress("No break at end of case") + uint32_t load_address = *(X+rs1 + 8) + uimm; + super::template write_mem(traits::MEM, load_address, *(X+rs2 + 8)); + if(this->core.trap_state) goto TRAP_CSW; + } + TRAP_CSW:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CADDI: { - uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) + (int8_t)sext<6>(imm); - - } catch(...){} - TRAP_CADDI:break; - }// @suppress("No break at end of case") + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) + (int8_t)sext<6>(imm); + } + TRAP_CADDI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CNOP: { - uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cnop"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "cnop"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - } - - } catch(...){} - TRAP_CNOP:break; - }// @suppress("No break at end of case") + } + TRAP_CNOP:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CJAL: { - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - *(X+1) = *PC + 2; - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); - } - - } catch(...){} - TRAP_CJAL:break; - }// @suppress("No break at end of case") + *(X+1) = *PC + 2; + *NEXT_PC = *PC + (int16_t)sext<12>(imm); + super::ex_info.branch_taken=true; + } + TRAP_CJAL:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CLI: { - uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int8_t)sext<6>(imm); - } - - } catch(...){} - TRAP_CLI:break; - }// @suppress("No break at end of case") + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int8_t)sext<6>(imm); + } + } + TRAP_CLI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CLUI: { - uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - if(imm == 0) raise(0, 2); - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = (int32_t)sext<18>(imm); - } - - } catch(...){} - TRAP_CLUI:break; - }// @suppress("No break at end of case") + if(imm == 0) { + raise(0, 2); + } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)sext<18>(imm); + } + } + TRAP_CLUI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CADDI16SP: { - uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), - fmt::arg("nzimm", nzimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(nzimm) *(X+2) = *(X+2) + (int16_t)sext<10>(nzimm); - else raise(0, 2); - - } catch(...){} - TRAP_CADDI16SP:break; - }// @suppress("No break at end of case") + uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), + fmt::arg("nzimm", nzimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(nzimm) { + *(X+2) = *(X+2) + (int16_t)sext<10>(nzimm); + } + else { + raise(0, 2); + } + } + TRAP_CADDI16SP:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::__reserved_clui: { - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "__reserved_clui"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - raise(0, 2); - - } catch(...){} - TRAP___reserved_clui:break; - }// @suppress("No break at end of case") + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "__reserved_clui"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + raise(0, 2); + } + TRAP___reserved_clui:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRLI: { - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = *(X+rs1_idx) >> shamt; - } - - } catch(...){} - TRAP_CSRLI:break; - }// @suppress("No break at end of case") + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = *(X+rs1_idx) >> shamt; + } + TRAP_CSRLI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRAI: { - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(shamt) { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; - } - else if(traits::XLEN == 128) { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; - } - - } catch(...){} - TRAP_CSRAI:break; - }// @suppress("No break at end of case") + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(shamt) { + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; + } + else { + if(traits::XLEN == 128) { + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; + } + } + } + TRAP_CSRAI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CANDI: { - uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm); - } - - } catch(...){} - TRAP_CANDI:break; - }// @suppress("No break at end of case") + uint8_t rs1_idx = rs1 + 8; + *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm); + } + TRAP_CANDI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSUB: { - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - uint8_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) - *(X+rs2 + 8); - } - - } catch(...){} - TRAP_CSUB:break; - }// @suppress("No break at end of case") + uint8_t rd_idx = rd + 8; + *(X+rd_idx) = *(X+rd_idx) - *(X+rs2 + 8); + } + TRAP_CSUB:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CXOR: { - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - uint8_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) ^ *(X+rs2 + 8); - } - - } catch(...){} - TRAP_CXOR:break; - }// @suppress("No break at end of case") + uint8_t rd_idx = rd + 8; + *(X+rd_idx) = *(X+rd_idx) ^ *(X+rs2 + 8); + } + TRAP_CXOR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::COR: { - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - uint8_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) | *(X+rs2 + 8); - } - - } catch(...){} - TRAP_COR:break; - }// @suppress("No break at end of case") + uint8_t rd_idx = rd + 8; + *(X+rd_idx) = *(X+rd_idx) | *(X+rs2 + 8); + } + TRAP_COR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CAND: { - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - uint8_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) & *(X+rs2 + 8); - } - - } catch(...){} - TRAP_CAND:break; - }// @suppress("No break at end of case") + uint8_t rd_idx = rd + 8; + *(X+rd_idx) = *(X+rd_idx) & *(X+rs2 + 8); + } + TRAP_CAND:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CJ: { - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); - - } catch(...){} - TRAP_CJ:break; - }// @suppress("No break at end of case") + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *NEXT_PC = *PC + (int16_t)sext<12>(imm); + super::ex_info.branch_taken=true; + } + TRAP_CJ:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CBEQZ: { - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(*(X+rs1 + 8) == 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); - - } catch(...){} - TRAP_CBEQZ:break; - }// @suppress("No break at end of case") + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(*(X+rs1 + 8) == 0) { + *NEXT_PC = *PC + (int16_t)sext<9>(imm); + super::ex_info.branch_taken=true; + } + } + TRAP_CBEQZ:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CBNEZ: { - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(*(X+rs1 + 8) != 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); - - } catch(...){} - TRAP_CBNEZ:break; - }// @suppress("No break at end of case") + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(*(X+rs1 + 8) != 0) { + *NEXT_PC = *PC + (int16_t)sext<9>(imm); + super::ex_info.branch_taken=true; + } + } + TRAP_CBNEZ:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CSLLI: { - uint8_t nzuimm = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), - fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(nzuimm) *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) << nzuimm; - - } catch(...){} - TRAP_CSLLI:break; - }// @suppress("No break at end of case") + uint8_t nzuimm = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(nzuimm) { + *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) << nzuimm; + } + } + TRAP_CSLLI:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CLWSP: { - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(rd) { - uint32_t offs = *(X+2) + uimm; - *(X+rd % traits::RFS) = (int32_t)readSpace4(traits::MEM, offs); - } - else raise(0, 2); - - } catch(...){} - TRAP_CLWSP:break; - }// @suppress("No break at end of case") + uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rd) { + uint32_t offs = *(X+2) + uimm; + uint32_t read_res = super::template read_mem(traits::MEM, offs); + if(this->core.trap_state) goto TRAP_CLWSP; + *(X+rd % traits::RFS) = (int32_t)read_res; + } + else { + raise(0, 2); + } + } + TRAP_CLWSP:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CMV: { - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rs2 % traits::RFS); - - } catch(...){} - TRAP_CMV:break; - }// @suppress("No break at end of case") + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs2 % traits::RFS); + } + } + TRAP_CMV:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CJR: { - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if(rs1) pc_assign(*NEXT_PC) = *(X+rs1 % traits::RFS) & ~ 0x1; - else raise(0, 2); - - } catch(...){} - TRAP_CJR:break; - }// @suppress("No break at end of case") + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs1) { + *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; + super::ex_info.branch_taken=true; + } + else { + raise(0, 2); + } + } + TRAP_CJR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::__reserved_cmv: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "__reserved_cmv"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - raise(0, 2); - - } catch(...){} - TRAP___reserved_cmv:break; - }// @suppress("No break at end of case") + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "__reserved_cmv"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + raise(0, 2); + } + TRAP___reserved_cmv:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CADD: { - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - if((rd % traits::RFS) != 0) *(X+rd % traits::RFS) = *(X+rd % traits::RFS) + *(X+rs2 % traits::RFS); - - } catch(...){} - TRAP_CADD:break; - }// @suppress("No break at end of case") + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rd % traits::RFS) + *(X+rs2 % traits::RFS); + } + } + TRAP_CADD:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CJALR: { - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - int32_t new_pc = *(X+rs1 % traits::RFS); - *(X+1) = *PC + 2; - pc_assign(*NEXT_PC) = new_pc & ~ 0x1; - } - - } catch(...){} - TRAP_CJALR:break; - }// @suppress("No break at end of case") + int32_t new_pc = *(X+rs1 % traits::RFS); + *(X+1) = *PC + 2; + *NEXT_PC = new_pc & ~ 0x1; + super::ex_info.branch_taken=true; + } + TRAP_CJALR:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::CEBREAK: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cebreak"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - raise(0, 3); - - } catch(...){} - TRAP_CEBREAK:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSWSP: { - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "cebreak"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction { - uint32_t offs = *(X+2) + uimm; - writeSpace4(traits::MEM, offs, (uint32_t)*(X+rs2 % traits::RFS)); - } - - } catch(...){} - TRAP_CSWSP:break; - }// @suppress("No break at end of case") + raise(0, 3); + } + TRAP_CEBREAK:break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSWSP: { + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + uint32_t offs = *(X+2) + uimm; + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 % traits::RFS)); + if(this->core.trap_state) goto TRAP_CSWSP; + } + TRAP_CSWSP:break; + }// @suppress("No break at end of case") case arch::traits::opcode_e::DII: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "dii"); - - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - try { - raise(0, 2); - - } catch(...){} - TRAP_DII:break; - }// @suppress("No break at end of case") + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "dii"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + raise(0, 2); + } + TRAP_DII:break; + }// @suppress("No break at end of case") default: { *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); raise(0, 2); From e8fd5143bcc23e7375365401dbc8ea1f72e69d73 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 31 May 2022 11:05:26 +0200 Subject: [PATCH 021/184] fix build options for standalone ISS --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 25d1883..4d34d34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,6 +121,7 @@ project(tgc-sim) find_package(Boost COMPONENTS program_options thread REQUIRED) add_executable(${PROJECT_NAME} src/main.cpp) +FILE(GLOB TGC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp) foreach(F IN LISTS TGC_SOURCES) string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) string(TOUPPER ${CORE_NAME_LC} CORE_NAME) From f40ab41899d8519efc1110189940d8a3254a881b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 2 Jun 2022 08:30:02 +0200 Subject: [PATCH 022/184] fix left-over from layout refactoring --- src/iss/plugin/pctrace.cpp | 9 +- src/plugin/pctrace.cpp | 180 ------------------------------------- 2 files changed, 5 insertions(+), 184 deletions(-) delete mode 100644 src/plugin/pctrace.cpp diff --git a/src/iss/plugin/pctrace.cpp b/src/iss/plugin/pctrace.cpp index 7f25652..fdda44d 100644 --- a/src/iss/plugin/pctrace.cpp +++ b/src/iss/plugin/pctrace.cpp @@ -1,5 +1,5 @@ #include -#include "pctrace.h" +#include #include #include #include @@ -157,8 +157,9 @@ void cov::callback(instr_info_t iinfo, const exec_info& einfo) { size_t id = iinfo.instr_id; auto entry = delays[id]; auto instr = instr_if->get_instr_word(); - auto call = (id==2 || id==3) && bit_sub<7,5>(instr)!=0; + auto call = id==65 || id ==86 || ((id==2 || id==3) && bit_sub<7,5>(instr)!=0) ;//not taking care of tail calls (jalr with loading x6) bool taken = einfo.branch_taken; + bool compressed = (instr&0x3)!=0x3; if (einfo.branch_taken) { delay = entry.taken; if(entry.taken > 1) @@ -169,10 +170,10 @@ void cov::callback(instr_info_t iinfo, const exec_info& einfo) { instr_if->set_curr_instr_cycles(entry.not_taken); } #ifndef WITH_LZ4 - output<get_pc() <<"," << delay <<"," << call<< "\n"; + output<get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; #else auto rdbuf=ostr.rdbuf(); - ostr<get_pc() <<"," << delay <<"," << call<< "\n"; + ostr<get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; #endif } } diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp deleted file mode 100644 index 0d93801..0000000 --- a/src/plugin/pctrace.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "rapidjson/writer.h" -#include "rapidjson/stringbuffer.h" -#include -#include -#include -#include -#ifdef WITH_LZ4 -#include -#endif - -namespace iss { -namespace plugin { - -using namespace rapidjson; -using namespace std; - -#ifdef WITH_LZ4 -class lz4compress_steambuf: public std::streambuf { -public: - lz4compress_steambuf(const lz4compress_steambuf&) = delete; - lz4compress_steambuf& operator=(const lz4compress_steambuf&) = delete; - lz4compress_steambuf(std::ostream &sink, size_t buf_size) - : sink(sink) - , src_buf(buf_size) - , dest_buf(LZ4F_compressBound(buf_size, nullptr)) - { - auto errCode = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION); - if (LZ4F_isError(errCode) != 0) - throw std::runtime_error(std::string("Failed to create LZ4 context: ") + LZ4F_getErrorName(errCode)); - size_t ret = LZ4F_compressBegin(ctx, &dest_buf.front(), dest_buf.capacity(), nullptr); - if (LZ4F_isError(ret) != 0) - throw std::runtime_error(std::string("Failed to start LZ4 compression: ") + LZ4F_getErrorName(ret)); - setp(src_buf.data(), src_buf.data() + src_buf.size() - 1); - sink.write(dest_buf.data(), ret); - } - - ~lz4compress_steambuf() { - close(); - } - - void close() { - if (closed) - return; - sync(); - auto ret = LZ4F_compressEnd(ctx, dest_buf.data(), dest_buf.capacity(), nullptr); - if (LZ4F_isError(ret) != 0) - throw std::runtime_error(std::string("Failed to finish LZ4 compression: ") + LZ4F_getErrorName(ret)); - sink.write(dest_buf.data(), ret); - LZ4F_freeCompressionContext(ctx); - closed = true; - } - -private: - int_type overflow(int_type ch) override { - compress_and_write(); - *pptr() = static_cast(ch); - pbump(1); - return ch; - } - - int_type sync() override { - compress_and_write(); - return 0; - } - - void compress_and_write() { - if (closed) - throw std::runtime_error("Cannot write to closed stream"); - if(auto orig_size = pptr() - pbase()){ - auto ret = LZ4F_compressUpdate(ctx, dest_buf.data(), dest_buf.capacity(), pbase(), orig_size, nullptr); - if (LZ4F_isError(ret) != 0) - throw std::runtime_error(std::string("LZ4 compression failed: ") + LZ4F_getErrorName(ret)); - if(ret) sink.write(dest_buf.data(), ret); - pbump(-orig_size); - } - } - - std::ostream &sink; - std::vector src_buf; - std::vector dest_buf; - LZ4F_compressionContext_t ctx{ nullptr }; - bool closed{ false }; -}; -#endif - -cov::cov(std::string const &filename) -: instr_if(nullptr) -, filename(filename) -, output("output.trc") -#ifdef WITH_LZ4 -, strbuf(new lz4compress_steambuf(output, 4096)) -, ostr(strbuf.get()) -#endif -{ } - -cov::~cov() { } - -bool cov::registration(const char *const version, vm_if& vm) { - instr_if = vm.get_arch()->get_instrumentation_if(); - if(!instr_if) return false; - const string core_name = instr_if->core_type_name(); - if (filename.length() > 0) { - ifstream is(filename); - if (is.is_open()) { - try { - IStreamWrapper isw(is); - Document d; - ParseResult ok = d.ParseStream(isw); - if(ok) { - Value& val = d[core_name.c_str()]; - if(val.IsArray()){ - delays.reserve(val.Size()); - for (auto it = val.Begin(); it != val.End(); ++it) { - auto& name = (*it)["name"]; - auto& size = (*it)["size"]; - auto& delay = (*it)["delay"]; - auto& branch = (*it)["branch"]; - if(delay.IsArray()) { - auto dt = delay[0].Get(); - auto dnt = delay[1].Get(); - delays.push_back(instr_desc{size.Get(), dt, dnt, branch.Get()}); - } else if(delay.Is()) { - auto d = delay.Get(); - delays.push_back(instr_desc{size.Get(), d, d, branch.Get()}); - } else - throw runtime_error("JSON parse error"); - - } - } else { - LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<get_instr_word(); - auto call = id==65 || id ==86 || ((id==2 || id==3) && bit_sub<7,5>(instr)!=0) ;//not taking care of tail calls (jalr with loading x6) - bool taken = einfo.branch_taken; - bool compressed = (instr&0x3)!=0x3; - if (einfo.branch_taken) { - delay = entry.taken; - if(entry.taken > 1) - instr_if->set_curr_instr_cycles(entry.taken); - } else { - delay = entry.not_taken; - if (entry.not_taken > 1) - instr_if->set_curr_instr_cycles(entry.not_taken); - } -#ifndef WITH_LZ4 - output<get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; -#else - auto rdbuf=ostr.rdbuf(); - ostr<get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; -#endif -} -} -} From 076b5a39add3ceae2514fdefd853c05df5ad01ab Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 2 Jun 2022 08:30:49 +0200 Subject: [PATCH 023/184] fix class naming --- src/iss/plugin/pctrace.cpp | 8 ++++---- src/iss/plugin/pctrace.h | 14 +++++++------- src/main.cpp | 2 +- src/sysc/core_complex.cpp | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/iss/plugin/pctrace.cpp b/src/iss/plugin/pctrace.cpp index fdda44d..df2225a 100644 --- a/src/iss/plugin/pctrace.cpp +++ b/src/iss/plugin/pctrace.cpp @@ -89,7 +89,7 @@ private: }; #endif -cov::cov(std::string const &filename) +pctrace::pctrace(std::string const &filename) : instr_if(nullptr) , filename(filename) , output("output.trc") @@ -99,9 +99,9 @@ cov::cov(std::string const &filename) #endif { } -cov::~cov() { } +pctrace::~pctrace() { } -bool cov::registration(const char *const version, vm_if& vm) { +bool pctrace::registration(const char *const version, vm_if& vm) { instr_if = vm.get_arch()->get_instrumentation_if(); if(!instr_if) return false; const string core_name = instr_if->core_type_name(); @@ -152,7 +152,7 @@ bool cov::registration(const char *const version, vm_if& vm) { return true; } -void cov::callback(instr_info_t iinfo, const exec_info& einfo) { +void pctrace::callback(instr_info_t iinfo, const exec_info& einfo) { auto delay = 0; size_t id = iinfo.instr_id; auto entry = delays[id]; diff --git a/src/iss/plugin/pctrace.h b/src/iss/plugin/pctrace.h index 446094b..ff3153c 100644 --- a/src/iss/plugin/pctrace.h +++ b/src/iss/plugin/pctrace.h @@ -45,7 +45,7 @@ namespace iss { namespace plugin { class lz4compress_steambuf; -class cov : public iss::vm_plugin { +class pctrace : public iss::vm_plugin { struct instr_delay { std::string instr_name; size_t size; @@ -67,17 +67,17 @@ class cov : public iss::vm_plugin { public: - cov(const cov &) = delete; + pctrace(const pctrace &) = delete; - cov(const cov &&) = delete; + pctrace(const pctrace &&) = delete; - cov(std::string const &); + pctrace(std::string const &); - virtual ~cov(); + virtual ~pctrace(); - cov &operator=(const cov &) = delete; + pctrace &operator=(const pctrace &) = delete; - cov &operator=(const cov &&) = delete; + pctrace &operator=(const pctrace &&) = delete; bool registration(const char *const version, vm_if &arch) override; diff --git a/src/main.cpp b/src/main.cpp index 0d4fe2f..c2b5254 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -177,7 +177,7 @@ int main(int argc, char *argv[]) { vm->register_plugin(*ce_plugin); plugin_list.push_back(ce_plugin); } else if (plugin_name == "pctrace") { - auto *plugin = new iss::plugin::cov(filename); + auto *plugin = new iss::plugin::pctrace(filename); vm->register_plugin(*plugin); plugin_list.push_back(plugin); } else { diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 118767e..ffd4737 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -405,7 +405,7 @@ void core_complex::before_end_of_elaboration() { cpu->vm->register_plugin(*plugin); plugin_list.push_back(plugin); } else if (plugin_name == "pctrace") { - auto *plugin = new iss::plugin::cov(filename); + auto *plugin = new iss::plugin::pctrace(filename); cpu->vm->register_plugin(*plugin); plugin_list.push_back(plugin); } else { From cb5375258a315b77f51bf8454ee7d8c9351fe636 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 10 Jun 2022 07:19:46 +0200 Subject: [PATCH 024/184] removes compilatioon of unneeded files --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d34d34..f84ed5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,6 @@ FILE(GLOB GEN_SOURCES ) set(LIB_SOURCES - src/vm/fp_functions.cpp src/iss/plugin/instruction_count.cpp src/iss/arch/tgc_c.cpp src/vm/interp/vm_tgc_c.cpp From f096b15dbdf7413984430c70da305c9752d86db7 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 19 Jun 2022 12:45:34 +0200 Subject: [PATCH 025/184] factors decoder into separate component --- CMakeLists.txt | 3 +- gen_input/templates/CORENAME.h.gtl | 3 + gen_input/templates/CORENAME_decoder.cpp.gtl | 86 ++++ gen_input/templates/CORENAME_instr.yaml.gtl | 3 +- gen_input/templates/interp/CORENAME.cpp.gtl | 92 +--- src/iss/arch/tgc_c.h | 3 + src/iss/arch/tgc_c_decoder.cpp | 175 +++++++ src/vm/interp/vm_tgc_c.cpp | 509 +++++++------------ 8 files changed, 455 insertions(+), 419 deletions(-) create mode 100644 gen_input/templates/CORENAME_decoder.cpp.gtl create mode 100644 src/iss/arch/tgc_c_decoder.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f84ed5f..5ae4f32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,8 @@ FILE(GLOB GEN_SOURCES set(LIB_SOURCES src/iss/plugin/instruction_count.cpp - src/iss/arch/tgc_c.cpp + src/iss/arch/tgc_c.cpp + src/iss/arch/tgc_c_decoder.cpp src/vm/interp/vm_tgc_c.cpp src/vm/fp_functions.cpp ${GEN_SOURCES} diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 1765fde..bd42664 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -69,6 +69,7 @@ def getCString(def val){ #include #include #include +#include #include namespace iss { @@ -120,6 +121,8 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { ${instr.instruction.name} = ${index},<%}%> MAX_OPCODE }; + + static std::unique_ptr> get_decoder(); }; struct ${coreDef.name.toLowerCase()}: public arch_if { diff --git a/gen_input/templates/CORENAME_decoder.cpp.gtl b/gen_input/templates/CORENAME_decoder.cpp.gtl new file mode 100644 index 0000000..d6b7032 --- /dev/null +++ b/gen_input/templates/CORENAME_decoder.cpp.gtl @@ -0,0 +1,86 @@ +#include "${coreDef.name.toLowerCase()}.h" +#include +#include +#include +#include + +namespace iss { +namespace arch { +namespace { +// according to +// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation +#ifdef __GCC__ +constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); } +#elif __cplusplus < 201402L +constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); } +constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; } +#else +constexpr size_t bit_count(uint32_t u) { + size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); + return ((uCount + (uCount >> 3)) & 030707070707) % 63; +} +#endif + +using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e; + +/**************************************************************************** + * start opcode definitions + ****************************************************************************/ +struct instruction_desriptor { + size_t length; + uint32_t value; + uint32_t mask; + opcode_e op; +}; + +const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> + {${instr.length}, ${instr.encoding}, ${instr.mask}, opcode_e::${instr.instruction.name}},<%}%> +}}; + +} + +template<> +struct instruction_decoder<${coreDef.name.toLowerCase()}> { + using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e; + using code_word_t=traits<${coreDef.name.toLowerCase()}>::code_word_t; + + struct instruction_pattern { + uint32_t value; + uint32_t mask; + opcode_e id; + }; + + std::array, 4> qlut; + + template + unsigned decode_instruction(T); + + instruction_decoder() { + for (auto instr : instr_descr) { + auto quadrant = instr.value & 0x3; + qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); + } + for(auto& lut: qlut){ + std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ + return bit_count(a.mask) > bit_count(b.mask); + }); + } + } +}; + +template<> +unsigned instruction_decoder<${coreDef.name.toLowerCase()}>::decode_instruction::code_word_t>(traits<${coreDef.name.toLowerCase()}>::code_word_t instr){ + auto res = std::find_if(std::begin(qlut[instr&0x3]), std::end(qlut[instr&0x3]), [instr](instruction_pattern const& e){ + return !((instr&e.mask) ^ e.value ); + }); + return static_cast(res!=std::end(qlut[instr&0x3])? res->id : opcode_e::MAX_OPCODE); +} + + +std::unique_ptr> traits<${coreDef.name.toLowerCase()}>::get_decoder(){ + return std::make_unique>(); +} + +} +} diff --git a/gen_input/templates/CORENAME_instr.yaml.gtl b/gen_input/templates/CORENAME_instr.yaml.gtl index 122be5e..9b29705 100644 --- a/gen_input/templates/CORENAME_instr.yaml.gtl +++ b/gen_input/templates/CORENAME_instr.yaml.gtl @@ -12,5 +12,6 @@ ${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %> - ${it.instruction.name}: encoding: ${it.encoding} - mask: ${it.mask}<%}}%> + mask: ${it.mask}<%if(it.attributes.size) {%> + attributes: ${it.attributes}<%}}}%> diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 56dc1a1..1566f55 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -73,6 +73,7 @@ public: using addr_t = typename super::addr_t; using reg_t = typename traits::reg_t; using mem_type_e = typename traits::mem_type_e; + using opcode_e = typename traits::opcode_e; vm_impl(); @@ -94,7 +95,6 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} - typename arch::traits::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; // some compile time constants @@ -111,13 +111,7 @@ protected: std::array lut_00, lut_01, lut_10; std::array lut_11; - struct instruction_pattern { - uint32_t value; - uint32_t mask; - typename arch::traits::opcode_e id; - }; - - std::array, 4> qlut; + std::unique_ptr> decoder; inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; @@ -139,42 +133,7 @@ protected: template T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} - inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } + template::type> inline S sext(U from) { auto mask = (1ULL< <%}%> private: - /**************************************************************************** - * start opcode definitions - ****************************************************************************/ - struct InstructionDesriptor { - size_t length; - uint32_t value; - uint32_t mask; - typename arch::traits::opcode_e op; - }; - - const std::array instr_descr = {{ - /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> - {${instr.length}, ${instr.encoding}, ${instr.mask}, arch::traits::opcode_e::${instr.instruction.name}},<%}%> - }}; //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ @@ -247,16 +192,7 @@ constexpr size_t bit_count(uint32_t u) { template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - unsigned id=0; - for (auto instr : instr_descr) { - auto quadrant = instr.value & 0x3; - qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); - } - for(auto& lut: qlut){ - std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ - return bit_count(a.mask) > bit_count(b.mask); - }); - } + decoder = traits::get_decoder(); } inline bool is_count_limit_enabled(finish_cond_e cond){ @@ -267,19 +203,11 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){ return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; } -template -typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t instr){ - for(auto& e: qlut[instr&0x3]){ - if(!((instr&e.mask) ^ e.value )) return e.id; - } - return arch::traits::opcode_e::MAX_OPCODE; -} - template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ auto pc=start; - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + auto* PC = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::PC]); + auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::NEXT_PC]); auto& trap_state = this->core.trap_state; auto& icount = this->core.icount; auto& cycle = this->core.cycle; @@ -296,11 +224,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if (is_jump_to_self_enabled(cond) && (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = decode_inst_id(instr); + auto inst_id = static_cast(decoder->decode_instruction(instr)); // pre execution stuff if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> - case arch::traits::opcode_e::${instr.name}: { + case opcode_e::${instr.name}: { <%instr.fields.eachLine{%>${it} <%}%>if(this->disass_enabled){ /* generate console output when executing the command */<%instr.disass.eachLine{%> @@ -308,8 +236,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } // used registers<%instr.usedVariables.each{ k,v-> if(v.isArray) {%> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); + auto* ${k} = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::${k}0]);<% }else{ %> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::${k}]); <%}}%>// calculate next pc value *NEXT_PC = *PC + ${instr.length/8}; // execute instruction<%instr.behavior.eachLine{%> diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index 8e2ae8a..02b09b6 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -36,6 +36,7 @@ #include #include #include +#include #include namespace iss { @@ -176,6 +177,8 @@ template <> struct traits { DII = 89, MAX_OPCODE }; + + static std::unique_ptr> get_decoder(); }; struct tgc_c: public arch_if { diff --git a/src/iss/arch/tgc_c_decoder.cpp b/src/iss/arch/tgc_c_decoder.cpp new file mode 100644 index 0000000..3526fda --- /dev/null +++ b/src/iss/arch/tgc_c_decoder.cpp @@ -0,0 +1,175 @@ +#include "tgc_c.h" +#include +#include +#include +#include + +namespace iss { +namespace arch { +namespace { +// according to +// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation +#ifdef __GCC__ +constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); } +#elif __cplusplus < 201402L +constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); } +constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; } +#else +constexpr size_t bit_count(uint32_t u) { + size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); + return ((uCount + (uCount >> 3)) & 030707070707) % 63; +} +#endif + +using opcode_e = traits::opcode_e; + +/**************************************************************************** + * start opcode definitions + ****************************************************************************/ +struct instruction_desriptor { + size_t length; + uint32_t value; + uint32_t mask; + opcode_e op; +}; + +const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */ + {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, opcode_e::LUI}, + {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, opcode_e::AUIPC}, + {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, opcode_e::JAL}, + {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, opcode_e::JALR}, + {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, opcode_e::BEQ}, + {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, opcode_e::BNE}, + {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, opcode_e::BLT}, + {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, opcode_e::BGE}, + {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, opcode_e::BLTU}, + {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, opcode_e::BGEU}, + {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, opcode_e::LB}, + {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, opcode_e::LH}, + {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, opcode_e::LW}, + {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, opcode_e::LBU}, + {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, opcode_e::LHU}, + {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, opcode_e::SB}, + {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, opcode_e::SH}, + {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, opcode_e::SW}, + {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, opcode_e::ADDI}, + {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, opcode_e::SLTI}, + {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, opcode_e::SLTIU}, + {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, opcode_e::XORI}, + {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, opcode_e::ORI}, + {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, opcode_e::ANDI}, + {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, opcode_e::SLLI}, + {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, opcode_e::SRLI}, + {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, opcode_e::SRAI}, + {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::ADD}, + {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::SUB}, + {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, opcode_e::SLL}, + {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, opcode_e::SLT}, + {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, opcode_e::SLTU}, + {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, opcode_e::XOR}, + {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::SRL}, + {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::SRA}, + {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, opcode_e::OR}, + {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, opcode_e::AND}, + {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, opcode_e::FENCE}, + {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, opcode_e::ECALL}, + {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, opcode_e::EBREAK}, + {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::URET}, + {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::SRET}, + {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::MRET}, + {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, opcode_e::WFI}, + {32, 0b01111011001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::DRET}, + {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRW}, + {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRS}, + {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRC}, + {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRWI}, + {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRSI}, + {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRCI}, + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, opcode_e::FENCE_I}, + {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::MUL}, + {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, opcode_e::MULH}, + {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, opcode_e::MULHSU}, + {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, opcode_e::MULHU}, + {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, opcode_e::DIV}, + {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::DIVU}, + {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, opcode_e::REM}, + {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, opcode_e::REMU}, + {16, 0b0000000000000000, 0b1110000000000011, opcode_e::CADDI4SPN}, + {16, 0b0100000000000000, 0b1110000000000011, opcode_e::CLW}, + {16, 0b1100000000000000, 0b1110000000000011, opcode_e::CSW}, + {16, 0b0000000000000001, 0b1110000000000011, opcode_e::CADDI}, + {16, 0b0000000000000001, 0b1110111110000011, opcode_e::CNOP}, + {16, 0b0010000000000001, 0b1110000000000011, opcode_e::CJAL}, + {16, 0b0100000000000001, 0b1110000000000011, opcode_e::CLI}, + {16, 0b0110000000000001, 0b1110000000000011, opcode_e::CLUI}, + {16, 0b0110000100000001, 0b1110111110000011, opcode_e::CADDI16SP}, + {16, 0b0110000000000001, 0b1111000001111111, opcode_e::__reserved_clui}, + {16, 0b1000000000000001, 0b1111110000000011, opcode_e::CSRLI}, + {16, 0b1000010000000001, 0b1111110000000011, opcode_e::CSRAI}, + {16, 0b1000100000000001, 0b1110110000000011, opcode_e::CANDI}, + {16, 0b1000110000000001, 0b1111110001100011, opcode_e::CSUB}, + {16, 0b1000110000100001, 0b1111110001100011, opcode_e::CXOR}, + {16, 0b1000110001000001, 0b1111110001100011, opcode_e::COR}, + {16, 0b1000110001100001, 0b1111110001100011, opcode_e::CAND}, + {16, 0b1010000000000001, 0b1110000000000011, opcode_e::CJ}, + {16, 0b1100000000000001, 0b1110000000000011, opcode_e::CBEQZ}, + {16, 0b1110000000000001, 0b1110000000000011, opcode_e::CBNEZ}, + {16, 0b0000000000000010, 0b1111000000000011, opcode_e::CSLLI}, + {16, 0b0100000000000010, 0b1110000000000011, opcode_e::CLWSP}, + {16, 0b1000000000000010, 0b1111000000000011, opcode_e::CMV}, + {16, 0b1000000000000010, 0b1111000001111111, opcode_e::CJR}, + {16, 0b1000000000000010, 0b1111111111111111, opcode_e::__reserved_cmv}, + {16, 0b1001000000000010, 0b1111000000000011, opcode_e::CADD}, + {16, 0b1001000000000010, 0b1111000001111111, opcode_e::CJALR}, + {16, 0b1001000000000010, 0b1111111111111111, opcode_e::CEBREAK}, + {16, 0b1100000000000010, 0b1110000000000011, opcode_e::CSWSP}, + {16, 0b0000000000000000, 0b1111111111111111, opcode_e::DII}, +}}; + +} + +template<> +struct instruction_decoder { + using opcode_e = traits::opcode_e; + using code_word_t=traits::code_word_t; + + struct instruction_pattern { + uint32_t value; + uint32_t mask; + opcode_e id; + }; + + std::array, 4> qlut; + + template + unsigned decode_instruction(T); + + instruction_decoder() { + for (auto instr : instr_descr) { + auto quadrant = instr.value & 0x3; + qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); + } + for(auto& lut: qlut){ + std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ + return bit_count(a.mask) > bit_count(b.mask); + }); + } + } +}; + +template<> +unsigned instruction_decoder::decode_instruction::code_word_t>(traits::code_word_t instr){ + auto res = std::find_if(std::begin(qlut[instr&0x3]), std::end(qlut[instr&0x3]), [instr](instruction_pattern const& e){ + return !((instr&e.mask) ^ e.value ); + }); + return static_cast(res!=std::end(qlut[instr&0x3])? res->id : opcode_e::MAX_OPCODE); +} + + +std::unique_ptr> traits::get_decoder(){ + return std::make_unique>(); +} + +} +} diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index c8b2461..af51eed 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -67,6 +67,7 @@ public: using addr_t = typename super::addr_t; using reg_t = typename traits::reg_t; using mem_type_e = typename traits::mem_type_e; + using opcode_e = typename traits::opcode_e; vm_impl(); @@ -88,7 +89,6 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} - typename arch::traits::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; // some compile time constants @@ -105,13 +105,7 @@ protected: std::array lut_00, lut_01, lut_10; std::array lut_11; - struct instruction_pattern { - uint32_t value; - uint32_t mask; - typename arch::traits::opcode_e id; - }; - - std::array, 4> qlut; + std::unique_ptr> decoder; inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; @@ -133,42 +127,7 @@ protected: template T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} - inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } + template::type> inline S sext(U from) { auto mask = (1ULL<::opcode_e op; - }; - - const std::array instr_descr = {{ - /* entries are: size, valid value, valid mask, function ptr */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits::opcode_e::LUI}, - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, arch::traits::opcode_e::AUIPC}, - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, arch::traits::opcode_e::JAL}, - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, arch::traits::opcode_e::JALR}, - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BEQ}, - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BNE}, - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLT}, - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGE}, - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLTU}, - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGEU}, - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LB}, - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LH}, - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LW}, - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LBU}, - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LHU}, - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SB}, - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SH}, - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SW}, - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ADDI}, - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTI}, - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTIU}, - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::XORI}, - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ORI}, - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ANDI}, - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLLI}, - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRLI}, - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRAI}, - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::ADD}, - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SUB}, - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLL}, - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLT}, - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLTU}, - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::XOR}, - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRL}, - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRA}, - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::OR}, - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::AND}, - {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE}, - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::ECALL}, - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::EBREAK}, - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::URET}, - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::SRET}, - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::MRET}, - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::WFI}, - {32, 0b01111011001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::DRET}, - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRW}, - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRS}, - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRC}, - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRWI}, - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRSI}, - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRCI}, - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE_I}, - {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MUL}, - {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULH}, - {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULHSU}, - {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULHU}, - {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIV}, - {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIVU}, - {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REM}, - {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REMU}, - {16, 0b0000000000000000, 0b1110000000000011, arch::traits::opcode_e::CADDI4SPN}, - {16, 0b0100000000000000, 0b1110000000000011, arch::traits::opcode_e::CLW}, - {16, 0b1100000000000000, 0b1110000000000011, arch::traits::opcode_e::CSW}, - {16, 0b0000000000000001, 0b1110000000000011, arch::traits::opcode_e::CADDI}, - {16, 0b0000000000000001, 0b1110111110000011, arch::traits::opcode_e::CNOP}, - {16, 0b0010000000000001, 0b1110000000000011, arch::traits::opcode_e::CJAL}, - {16, 0b0100000000000001, 0b1110000000000011, arch::traits::opcode_e::CLI}, - {16, 0b0110000000000001, 0b1110000000000011, arch::traits::opcode_e::CLUI}, - {16, 0b0110000100000001, 0b1110111110000011, arch::traits::opcode_e::CADDI16SP}, - {16, 0b0110000000000001, 0b1111000001111111, arch::traits::opcode_e::__reserved_clui}, - {16, 0b1000000000000001, 0b1111110000000011, arch::traits::opcode_e::CSRLI}, - {16, 0b1000010000000001, 0b1111110000000011, arch::traits::opcode_e::CSRAI}, - {16, 0b1000100000000001, 0b1110110000000011, arch::traits::opcode_e::CANDI}, - {16, 0b1000110000000001, 0b1111110001100011, arch::traits::opcode_e::CSUB}, - {16, 0b1000110000100001, 0b1111110001100011, arch::traits::opcode_e::CXOR}, - {16, 0b1000110001000001, 0b1111110001100011, arch::traits::opcode_e::COR}, - {16, 0b1000110001100001, 0b1111110001100011, arch::traits::opcode_e::CAND}, - {16, 0b1010000000000001, 0b1110000000000011, arch::traits::opcode_e::CJ}, - {16, 0b1100000000000001, 0b1110000000000011, arch::traits::opcode_e::CBEQZ}, - {16, 0b1110000000000001, 0b1110000000000011, arch::traits::opcode_e::CBNEZ}, - {16, 0b0000000000000010, 0b1111000000000011, arch::traits::opcode_e::CSLLI}, - {16, 0b0100000000000010, 0b1110000000000011, arch::traits::opcode_e::CLWSP}, - {16, 0b1000000000000010, 0b1111000000000011, arch::traits::opcode_e::CMV}, - {16, 0b1000000000000010, 0b1111000001111111, arch::traits::opcode_e::CJR}, - {16, 0b1000000000000010, 0b1111111111111111, arch::traits::opcode_e::__reserved_cmv}, - {16, 0b1001000000000010, 0b1111000000000011, arch::traits::opcode_e::CADD}, - {16, 0b1001000000000010, 0b1111000001111111, arch::traits::opcode_e::CJALR}, - {16, 0b1001000000000010, 0b1111111111111111, arch::traits::opcode_e::CEBREAK}, - {16, 0b1100000000000010, 0b1110000000000011, arch::traits::opcode_e::CSWSP}, - {16, 0b0000000000000000, 0b1111111111111111, arch::traits::opcode_e::DII}, - }}; //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ @@ -328,16 +184,7 @@ constexpr size_t bit_count(uint32_t u) { template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - unsigned id=0; - for (auto instr : instr_descr) { - auto quadrant = instr.value & 0x3; - qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); - } - for(auto& lut: qlut){ - std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ - return bit_count(a.mask) > bit_count(b.mask); - }); - } + decoder = traits::get_decoder(); } inline bool is_count_limit_enabled(finish_cond_e cond){ @@ -348,19 +195,11 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){ return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; } -template -typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t instr){ - for(auto& e: qlut[instr&0x3]){ - if(!((instr&e.mask) ^ e.value )) return e.id; - } - return arch::traits::opcode_e::MAX_OPCODE; -} - template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ auto pc=start; - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + auto* PC = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::PC]); + auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::NEXT_PC]); auto& trap_state = this->core.trap_state; auto& icount = this->core.icount; auto& cycle = this->core.cycle; @@ -377,11 +216,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if (is_jump_to_self_enabled(cond) && (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = decode_inst_id(instr); + auto inst_id = static_cast(decoder->decode_instruction(instr)); // pre execution stuff if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); switch(inst_id){ - case arch::traits::opcode_e::LUI: { + case opcode_e::LUI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ @@ -392,7 +231,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -402,7 +241,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LUI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::AUIPC: { + case opcode_e::AUIPC: { uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ @@ -413,7 +252,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -423,7 +262,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_AUIPC:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::JAL: { + case opcode_e::JAL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); if(this->disass_enabled){ @@ -434,7 +273,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -451,7 +290,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_JAL:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::JALR: { + case opcode_e::JALR: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -463,7 +302,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -481,7 +320,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_JALR:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::BEQ: { + case opcode_e::BEQ: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -493,7 +332,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -509,7 +348,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BEQ:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::BNE: { + case opcode_e::BNE: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -521,7 +360,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -537,7 +376,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BNE:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::BLT: { + case opcode_e::BLT: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -549,7 +388,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -565,7 +404,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BLT:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::BGE: { + case opcode_e::BGE: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -577,7 +416,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -593,7 +432,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BGE:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::BLTU: { + case opcode_e::BLTU: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -605,7 +444,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -621,7 +460,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BLTU:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::BGEU: { + case opcode_e::BGEU: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -633,7 +472,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -649,7 +488,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BGEU:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::LB: { + case opcode_e::LB: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -661,7 +500,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -674,7 +513,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LB:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::LH: { + case opcode_e::LH: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -686,7 +525,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -700,7 +539,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LH:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::LW: { + case opcode_e::LW: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -712,7 +551,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -726,7 +565,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LW:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::LBU: { + case opcode_e::LBU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -738,7 +577,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -751,7 +590,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LBU:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::LHU: { + case opcode_e::LHU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -763,7 +602,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -777,7 +616,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LHU:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SB: { + case opcode_e::SB: { uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -789,7 +628,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -798,7 +637,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SB:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SH: { + case opcode_e::SH: { uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -810,7 +649,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -820,7 +659,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SH:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SW: { + case opcode_e::SW: { uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -832,7 +671,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -842,7 +681,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SW:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::ADDI: { + case opcode_e::ADDI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -854,7 +693,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -864,7 +703,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_ADDI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTI: { + case opcode_e::SLTI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -876,7 +715,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -886,7 +725,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLTI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTIU: { + case opcode_e::SLTIU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -898,7 +737,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -908,7 +747,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLTIU:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::XORI: { + case opcode_e::XORI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -920,7 +759,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -930,7 +769,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_XORI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::ORI: { + case opcode_e::ORI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -942,7 +781,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -952,7 +791,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_ORI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::ANDI: { + case opcode_e::ANDI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -964,7 +803,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -974,7 +813,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_ANDI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLLI: { + case opcode_e::SLLI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -986,7 +825,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1001,7 +840,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLLI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRLI: { + case opcode_e::SRLI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1013,7 +852,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1028,7 +867,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SRLI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRAI: { + case opcode_e::SRAI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1040,7 +879,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1055,7 +894,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SRAI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::ADD: { + case opcode_e::ADD: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1067,7 +906,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1077,7 +916,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_ADD:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SUB: { + case opcode_e::SUB: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1089,7 +928,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1099,7 +938,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SUB:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLL: { + case opcode_e::SLL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1111,7 +950,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1121,7 +960,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLL:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLT: { + case opcode_e::SLT: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1133,7 +972,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1143,7 +982,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLT:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTU: { + case opcode_e::SLTU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1155,7 +994,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1165,7 +1004,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLTU:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::XOR: { + case opcode_e::XOR: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1177,7 +1016,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1187,7 +1026,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_XOR:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRL: { + case opcode_e::SRL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1199,7 +1038,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1209,7 +1048,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SRL:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRA: { + case opcode_e::SRA: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1221,7 +1060,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1231,7 +1070,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SRA:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::OR: { + case opcode_e::OR: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1243,7 +1082,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1253,7 +1092,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_OR:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::AND: { + case opcode_e::AND: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1265,7 +1104,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1275,7 +1114,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_AND:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::FENCE: { + case opcode_e::FENCE: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t succ = ((bit_sub<20,4>(instr))); @@ -1297,7 +1136,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_FENCE:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::ECALL: { + case opcode_e::ECALL: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "ecall"); @@ -1310,7 +1149,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_ECALL:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::EBREAK: { + case opcode_e::EBREAK: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "ebreak"); @@ -1323,7 +1162,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_EBREAK:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::URET: { + case opcode_e::URET: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "uret"); @@ -1336,7 +1175,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_URET:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRET: { + case opcode_e::SRET: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "sret"); @@ -1349,7 +1188,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SRET:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::MRET: { + case opcode_e::MRET: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "mret"); @@ -1362,7 +1201,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_MRET:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::WFI: { + case opcode_e::WFI: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "wfi"); @@ -1375,15 +1214,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_WFI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::DRET: { + case opcode_e::DRET: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "dret"); } // used registers - auto* PRIV = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PRIV]); + auto* PRIV = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::PRIV]); - auto* DPC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::DPC]); + auto* DPC = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::DPC]); // calculate next pc value *NEXT_PC = *PC + 4; // execute instruction @@ -1399,7 +1238,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_DRET:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRW: { + case opcode_e::CSRRW: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1411,7 +1250,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1431,7 +1270,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRW:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRS: { + case opcode_e::CSRRS: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1443,7 +1282,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1461,7 +1300,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRS:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRC: { + case opcode_e::CSRRC: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1473,7 +1312,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1491,7 +1330,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRC:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRWI: { + case opcode_e::CSRRWI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1503,7 +1342,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1518,7 +1357,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRWI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRSI: { + case opcode_e::CSRRSI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1530,7 +1369,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1547,7 +1386,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRSI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRCI: { + case opcode_e::CSRRCI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1559,7 +1398,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1576,7 +1415,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRCI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::FENCE_I: { + case opcode_e::FENCE_I: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1596,7 +1435,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_FENCE_I:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::MUL: { + case opcode_e::MUL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1608,7 +1447,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1619,7 +1458,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_MUL:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::MULH: { + case opcode_e::MULH: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1631,7 +1470,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1642,7 +1481,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_MULH:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::MULHSU: { + case opcode_e::MULHSU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1654,7 +1493,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1665,7 +1504,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_MULHSU:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::MULHU: { + case opcode_e::MULHU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1677,7 +1516,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1688,7 +1527,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_MULHU:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::DIV: { + case opcode_e::DIV: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1700,7 +1539,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1721,7 +1560,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_DIV:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::DIVU: { + case opcode_e::DIVU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1733,7 +1572,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1748,7 +1587,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_DIVU:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::REM: { + case opcode_e::REM: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1760,7 +1599,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1781,7 +1620,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_REM:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::REMU: { + case opcode_e::REMU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1793,7 +1632,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1808,7 +1647,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_REMU:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI4SPN: { + case opcode_e::CADDI4SPN: { uint8_t rd = ((bit_sub<2,3>(instr))); uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); if(this->disass_enabled){ @@ -1819,7 +1658,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1832,7 +1671,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CADDI4SPN:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLW: { + case opcode_e::CLW: { uint8_t rd = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -1844,7 +1683,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1855,7 +1694,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CLW:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSW: { + case opcode_e::CSW: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -1867,7 +1706,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1877,7 +1716,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSW:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI: { + case opcode_e::CADDI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -1888,7 +1727,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1896,7 +1735,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CADDI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CNOP: { + case opcode_e::CNOP: { uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1909,7 +1748,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CNOP:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJAL: { + case opcode_e::CJAL: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1919,7 +1758,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1929,7 +1768,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CJAL:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLI: { + case opcode_e::CLI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -1940,7 +1779,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1950,7 +1789,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CLI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLUI: { + case opcode_e::CLUI: { uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -1961,7 +1800,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1974,7 +1813,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CLUI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI16SP: { + case opcode_e::CADDI16SP: { uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1984,7 +1823,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1997,7 +1836,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CADDI16SP:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::__reserved_clui: { + case opcode_e::__reserved_clui: { uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2011,7 +1850,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP___reserved_clui:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRLI: { + case opcode_e::CSRLI: { uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2022,7 +1861,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2031,7 +1870,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRLI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRAI: { + case opcode_e::CSRAI: { uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2042,7 +1881,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2059,7 +1898,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRAI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CANDI: { + case opcode_e::CANDI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2070,7 +1909,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2079,7 +1918,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CANDI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSUB: { + case opcode_e::CSUB: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2090,7 +1929,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2099,7 +1938,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSUB:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CXOR: { + case opcode_e::CXOR: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2110,7 +1949,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2119,7 +1958,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CXOR:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::COR: { + case opcode_e::COR: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2130,7 +1969,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2139,7 +1978,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_COR:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CAND: { + case opcode_e::CAND: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2150,7 +1989,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2159,7 +1998,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CAND:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJ: { + case opcode_e::CJ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2177,7 +2016,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CJ:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CBEQZ: { + case opcode_e::CBEQZ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2188,7 +2027,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2199,7 +2038,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CBEQZ:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CBNEZ: { + case opcode_e::CBNEZ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2210,7 +2049,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2221,7 +2060,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CBNEZ:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSLLI: { + case opcode_e::CSLLI: { uint8_t nzuimm = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2232,7 +2071,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2242,7 +2081,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSLLI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLWSP: { + case opcode_e::CLWSP: { uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2253,7 +2092,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2269,7 +2108,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CLWSP:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CMV: { + case opcode_e::CMV: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2280,7 +2119,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2290,7 +2129,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CMV:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJR: { + case opcode_e::CJR: { uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2300,7 +2139,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2314,7 +2153,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CJR:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::__reserved_cmv: { + case opcode_e::__reserved_cmv: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "__reserved_cmv"); @@ -2327,7 +2166,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP___reserved_cmv:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADD: { + case opcode_e::CADD: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2338,7 +2177,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2348,7 +2187,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CADD:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJALR: { + case opcode_e::CJALR: { uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2358,7 +2197,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2369,7 +2208,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CJALR:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CEBREAK: { + case opcode_e::CEBREAK: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "cebreak"); @@ -2382,7 +2221,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CEBREAK:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSWSP: { + case opcode_e::CSWSP: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); if(this->disass_enabled){ @@ -2393,7 +2232,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2403,7 +2242,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSWSP:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::DII: { + case opcode_e::DII: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "dii"); From 18f33b4a6809997a4d73824c5fdb4dd7c70e626a Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 19 Jun 2022 16:52:29 +0200 Subject: [PATCH 026/184] fixes ordering of instructions for decoding --- gen_input/templates/CORENAME_decoder.cpp.gtl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen_input/templates/CORENAME_decoder.cpp.gtl b/gen_input/templates/CORENAME_decoder.cpp.gtl index d6b7032..9291118 100644 --- a/gen_input/templates/CORENAME_decoder.cpp.gtl +++ b/gen_input/templates/CORENAME_decoder.cpp.gtl @@ -63,7 +63,7 @@ struct instruction_decoder<${coreDef.name.toLowerCase()}> { } for(auto& lut: qlut){ std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ - return bit_count(a.mask) > bit_count(b.mask); + return bit_count(a.mask) < bit_count(b.mask); }); } } From feaa49d367e1c9a4d0e8df884ca27c46c05c01b2 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 20 Jun 2022 00:39:11 +0200 Subject: [PATCH 027/184] removes decoder again as there is some issue --- CMakeLists.txt | 1 - gen_input/templates/CORENAME.h.gtl | 3 - gen_input/templates/interp/CORENAME.cpp.gtl | 91 +++- src/iss/arch/tgc_c.h | 3 - src/vm/interp/vm_tgc_c.cpp | 508 +++++++++++++------- 5 files changed, 417 insertions(+), 189 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ae4f32..775afc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,6 @@ FILE(GLOB GEN_SOURCES set(LIB_SOURCES src/iss/plugin/instruction_count.cpp src/iss/arch/tgc_c.cpp - src/iss/arch/tgc_c_decoder.cpp src/vm/interp/vm_tgc_c.cpp src/vm/fp_functions.cpp ${GEN_SOURCES} diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index bd42664..1765fde 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -69,7 +69,6 @@ def getCString(def val){ #include #include #include -#include #include namespace iss { @@ -121,8 +120,6 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { ${instr.instruction.name} = ${index},<%}%> MAX_OPCODE }; - - static std::unique_ptr> get_decoder(); }; struct ${coreDef.name.toLowerCase()}: public arch_if { diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 1566f55..1fd65a4 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -95,6 +95,7 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} + typename arch::traits::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; // some compile time constants @@ -111,7 +112,13 @@ protected: std::array lut_00, lut_01, lut_10; std::array lut_11; - std::unique_ptr> decoder; + struct instruction_pattern { + uint32_t value; + uint32_t mask; + typename arch::traits::opcode_e id; + }; + + std::array, 4> qlut; inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; @@ -133,7 +140,42 @@ protected: template T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} - + inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ + auto ret = super::template read_mem(space, addr); + if(this->core.trap_state) throw 0; + return ret; + } + inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){ + auto ret = super::template read_mem(space, addr); + if(this->core.trap_state) throw 0; + return ret; + } + inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){ + auto ret = super::template read_mem(space, addr); + if(this->core.trap_state) throw 0; + return ret; + } + inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){ + auto ret = super::template read_mem(space, addr); + if(this->core.trap_state) throw 0; + return ret; + } + inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){ + super::write_mem(space, addr, data); + if(this->core.trap_state) throw 0; + } + inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){ + super::write_mem(space, addr, data); + if(this->core.trap_state) throw 0; + } + inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){ + super::write_mem(space, addr, data); + if(this->core.trap_state) throw 0; + } + inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){ + super::write_mem(space, addr, data); + if(this->core.trap_state) throw 0; + } template::type> inline S sext(U from) { auto mask = (1ULL< <%}%> private: + /**************************************************************************** + * start opcode definitions + ****************************************************************************/ + struct InstructionDesriptor { + size_t length; + uint32_t value; + uint32_t mask; + typename arch::traits::opcode_e op; + }; + + const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> + {${instr.length}, ${instr.encoding}, ${instr.mask}, arch::traits::opcode_e::${instr.instruction.name}},<%}%> + }}; //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ @@ -192,7 +248,16 @@ constexpr size_t bit_count(uint32_t u) { template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - decoder = traits::get_decoder(); + unsigned id=0; + for (auto instr : instr_descr) { + auto quadrant = instr.value & 0x3; + qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); + } + for(auto& lut: qlut){ + std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ + return bit_count(a.mask) > bit_count(b.mask); + }); + } } inline bool is_count_limit_enabled(finish_cond_e cond){ @@ -203,11 +268,19 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){ return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; } +template +typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t instr){ + for(auto& e: qlut[instr&0x3]){ + if(!((instr&e.mask) ^ e.value )) return e.id; + } + return arch::traits::opcode_e::MAX_OPCODE; +} + template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ auto pc=start; - auto* PC = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::PC]); - auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::NEXT_PC]); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); auto& trap_state = this->core.trap_state; auto& icount = this->core.icount; auto& cycle = this->core.cycle; @@ -224,11 +297,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if (is_jump_to_self_enabled(cond) && (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = static_cast(decoder->decode_instruction(instr)); + auto inst_id = decode_inst_id(instr); // pre execution stuff if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> - case opcode_e::${instr.name}: { + case arch::traits::opcode_e::${instr.name}: { <%instr.fields.eachLine{%>${it} <%}%>if(this->disass_enabled){ /* generate console output when executing the command */<%instr.disass.eachLine{%> @@ -236,8 +309,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } // used registers<%instr.usedVariables.each{ k,v-> if(v.isArray) {%> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::${k}0]);<% }else{ %> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::${k}]); + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); <%}}%>// calculate next pc value *NEXT_PC = *PC + ${instr.length/8}; // execute instruction<%instr.behavior.eachLine{%> diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index 02b09b6..8e2ae8a 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -36,7 +36,6 @@ #include #include #include -#include #include namespace iss { @@ -177,8 +176,6 @@ template <> struct traits { DII = 89, MAX_OPCODE }; - - static std::unique_ptr> get_decoder(); }; struct tgc_c: public arch_if { diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index af51eed..2f31d63 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -89,6 +89,7 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} + typename arch::traits::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; // some compile time constants @@ -105,7 +106,13 @@ protected: std::array lut_00, lut_01, lut_10; std::array lut_11; - std::unique_ptr> decoder; + struct instruction_pattern { + uint32_t value; + uint32_t mask; + typename arch::traits::opcode_e id; + }; + + std::array, 4> qlut; inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; @@ -127,7 +134,42 @@ protected: template T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} - + inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ + auto ret = super::template read_mem(space, addr); + if(this->core.trap_state) throw 0; + return ret; + } + inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){ + auto ret = super::template read_mem(space, addr); + if(this->core.trap_state) throw 0; + return ret; + } + inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){ + auto ret = super::template read_mem(space, addr); + if(this->core.trap_state) throw 0; + return ret; + } + inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){ + auto ret = super::template read_mem(space, addr); + if(this->core.trap_state) throw 0; + return ret; + } + inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){ + super::write_mem(space, addr, data); + if(this->core.trap_state) throw 0; + } + inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){ + super::write_mem(space, addr, data); + if(this->core.trap_state) throw 0; + } + inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){ + super::write_mem(space, addr, data); + if(this->core.trap_state) throw 0; + } + inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){ + super::write_mem(space, addr, data); + if(this->core.trap_state) throw 0; + } template::type> inline S sext(U from) { auto mask = (1ULL<::opcode_e op; + }; + + const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */ + {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits::opcode_e::LUI}, + {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, arch::traits::opcode_e::AUIPC}, + {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, arch::traits::opcode_e::JAL}, + {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, arch::traits::opcode_e::JALR}, + {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BEQ}, + {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BNE}, + {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLT}, + {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGE}, + {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BLTU}, + {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::BGEU}, + {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LB}, + {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LH}, + {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LW}, + {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LBU}, + {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, arch::traits::opcode_e::LHU}, + {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SB}, + {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SH}, + {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SW}, + {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ADDI}, + {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTI}, + {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::SLTIU}, + {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::XORI}, + {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ORI}, + {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, arch::traits::opcode_e::ANDI}, + {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLLI}, + {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRLI}, + {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRAI}, + {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::ADD}, + {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SUB}, + {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLL}, + {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLT}, + {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SLTU}, + {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::XOR}, + {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRL}, + {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::SRA}, + {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::OR}, + {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::AND}, + {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE}, + {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::ECALL}, + {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::EBREAK}, + {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::URET}, + {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::SRET}, + {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::MRET}, + {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::WFI}, + {32, 0b01111011001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::DRET}, + {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRW}, + {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRS}, + {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRC}, + {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRWI}, + {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRSI}, + {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRCI}, + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE_I}, + {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MUL}, + {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULH}, + {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULHSU}, + {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::MULHU}, + {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIV}, + {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIVU}, + {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REM}, + {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REMU}, + {16, 0b0000000000000000, 0b1110000000000011, arch::traits::opcode_e::CADDI4SPN}, + {16, 0b0100000000000000, 0b1110000000000011, arch::traits::opcode_e::CLW}, + {16, 0b1100000000000000, 0b1110000000000011, arch::traits::opcode_e::CSW}, + {16, 0b0000000000000001, 0b1110000000000011, arch::traits::opcode_e::CADDI}, + {16, 0b0000000000000001, 0b1110111110000011, arch::traits::opcode_e::CNOP}, + {16, 0b0010000000000001, 0b1110000000000011, arch::traits::opcode_e::CJAL}, + {16, 0b0100000000000001, 0b1110000000000011, arch::traits::opcode_e::CLI}, + {16, 0b0110000000000001, 0b1110000000000011, arch::traits::opcode_e::CLUI}, + {16, 0b0110000100000001, 0b1110111110000011, arch::traits::opcode_e::CADDI16SP}, + {16, 0b0110000000000001, 0b1111000001111111, arch::traits::opcode_e::__reserved_clui}, + {16, 0b1000000000000001, 0b1111110000000011, arch::traits::opcode_e::CSRLI}, + {16, 0b1000010000000001, 0b1111110000000011, arch::traits::opcode_e::CSRAI}, + {16, 0b1000100000000001, 0b1110110000000011, arch::traits::opcode_e::CANDI}, + {16, 0b1000110000000001, 0b1111110001100011, arch::traits::opcode_e::CSUB}, + {16, 0b1000110000100001, 0b1111110001100011, arch::traits::opcode_e::CXOR}, + {16, 0b1000110001000001, 0b1111110001100011, arch::traits::opcode_e::COR}, + {16, 0b1000110001100001, 0b1111110001100011, arch::traits::opcode_e::CAND}, + {16, 0b1010000000000001, 0b1110000000000011, arch::traits::opcode_e::CJ}, + {16, 0b1100000000000001, 0b1110000000000011, arch::traits::opcode_e::CBEQZ}, + {16, 0b1110000000000001, 0b1110000000000011, arch::traits::opcode_e::CBNEZ}, + {16, 0b0000000000000010, 0b1111000000000011, arch::traits::opcode_e::CSLLI}, + {16, 0b0100000000000010, 0b1110000000000011, arch::traits::opcode_e::CLWSP}, + {16, 0b1000000000000010, 0b1111000000000011, arch::traits::opcode_e::CMV}, + {16, 0b1000000000000010, 0b1111000001111111, arch::traits::opcode_e::CJR}, + {16, 0b1000000000000010, 0b1111111111111111, arch::traits::opcode_e::__reserved_cmv}, + {16, 0b1001000000000010, 0b1111000000000011, arch::traits::opcode_e::CADD}, + {16, 0b1001000000000010, 0b1111000001111111, arch::traits::opcode_e::CJALR}, + {16, 0b1001000000000010, 0b1111111111111111, arch::traits::opcode_e::CEBREAK}, + {16, 0b1100000000000010, 0b1110000000000011, arch::traits::opcode_e::CSWSP}, + {16, 0b0000000000000000, 0b1111111111111111, arch::traits::opcode_e::DII}, + }}; //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ @@ -184,7 +329,16 @@ constexpr size_t bit_count(uint32_t u) { template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - decoder = traits::get_decoder(); + unsigned id=0; + for (auto instr : instr_descr) { + auto quadrant = instr.value & 0x3; + qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); + } + for(auto& lut: qlut){ + std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ + return bit_count(a.mask) > bit_count(b.mask); + }); + } } inline bool is_count_limit_enabled(finish_cond_e cond){ @@ -195,11 +349,19 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){ return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; } +template +typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t instr){ + for(auto& e: qlut[instr&0x3]){ + if(!((instr&e.mask) ^ e.value )) return e.id; + } + return arch::traits::opcode_e::MAX_OPCODE; +} + template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ auto pc=start; - auto* PC = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::PC]); - auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::NEXT_PC]); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); auto& trap_state = this->core.trap_state; auto& icount = this->core.icount; auto& cycle = this->core.cycle; @@ -216,11 +378,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if (is_jump_to_self_enabled(cond) && (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = static_cast(decoder->decode_instruction(instr)); + auto inst_id = decode_inst_id(instr); // pre execution stuff if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); switch(inst_id){ - case opcode_e::LUI: { + case arch::traits::opcode_e::LUI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ @@ -231,7 +393,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -241,7 +403,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LUI:break; }// @suppress("No break at end of case") - case opcode_e::AUIPC: { + case arch::traits::opcode_e::AUIPC: { uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ @@ -252,7 +414,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -262,7 +424,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_AUIPC:break; }// @suppress("No break at end of case") - case opcode_e::JAL: { + case arch::traits::opcode_e::JAL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); if(this->disass_enabled){ @@ -273,7 +435,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -290,7 +452,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_JAL:break; }// @suppress("No break at end of case") - case opcode_e::JALR: { + case arch::traits::opcode_e::JALR: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -302,7 +464,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -320,7 +482,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_JALR:break; }// @suppress("No break at end of case") - case opcode_e::BEQ: { + case arch::traits::opcode_e::BEQ: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -332,7 +494,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -348,7 +510,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BEQ:break; }// @suppress("No break at end of case") - case opcode_e::BNE: { + case arch::traits::opcode_e::BNE: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -360,7 +522,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -376,7 +538,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BNE:break; }// @suppress("No break at end of case") - case opcode_e::BLT: { + case arch::traits::opcode_e::BLT: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -388,7 +550,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -404,7 +566,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BLT:break; }// @suppress("No break at end of case") - case opcode_e::BGE: { + case arch::traits::opcode_e::BGE: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -416,7 +578,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -432,7 +594,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BGE:break; }// @suppress("No break at end of case") - case opcode_e::BLTU: { + case arch::traits::opcode_e::BLTU: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -444,7 +606,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -460,7 +622,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BLTU:break; }// @suppress("No break at end of case") - case opcode_e::BGEU: { + case arch::traits::opcode_e::BGEU: { uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -472,7 +634,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -488,7 +650,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_BGEU:break; }// @suppress("No break at end of case") - case opcode_e::LB: { + case arch::traits::opcode_e::LB: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -500,7 +662,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -513,7 +675,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LB:break; }// @suppress("No break at end of case") - case opcode_e::LH: { + case arch::traits::opcode_e::LH: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -525,7 +687,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -539,7 +701,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LH:break; }// @suppress("No break at end of case") - case opcode_e::LW: { + case arch::traits::opcode_e::LW: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -551,7 +713,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -565,7 +727,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LW:break; }// @suppress("No break at end of case") - case opcode_e::LBU: { + case arch::traits::opcode_e::LBU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -577,7 +739,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -590,7 +752,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LBU:break; }// @suppress("No break at end of case") - case opcode_e::LHU: { + case arch::traits::opcode_e::LHU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -602,7 +764,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -616,7 +778,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_LHU:break; }// @suppress("No break at end of case") - case opcode_e::SB: { + case arch::traits::opcode_e::SB: { uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -628,7 +790,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -637,7 +799,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SB:break; }// @suppress("No break at end of case") - case opcode_e::SH: { + case arch::traits::opcode_e::SH: { uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -649,7 +811,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -659,7 +821,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SH:break; }// @suppress("No break at end of case") - case opcode_e::SW: { + case arch::traits::opcode_e::SW: { uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -671,7 +833,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -681,7 +843,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SW:break; }// @suppress("No break at end of case") - case opcode_e::ADDI: { + case arch::traits::opcode_e::ADDI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -693,7 +855,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -703,7 +865,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_ADDI:break; }// @suppress("No break at end of case") - case opcode_e::SLTI: { + case arch::traits::opcode_e::SLTI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -715,7 +877,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -725,7 +887,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLTI:break; }// @suppress("No break at end of case") - case opcode_e::SLTIU: { + case arch::traits::opcode_e::SLTIU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -737,7 +899,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -747,7 +909,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLTIU:break; }// @suppress("No break at end of case") - case opcode_e::XORI: { + case arch::traits::opcode_e::XORI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -759,7 +921,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -769,7 +931,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_XORI:break; }// @suppress("No break at end of case") - case opcode_e::ORI: { + case arch::traits::opcode_e::ORI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -781,7 +943,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -791,7 +953,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_ORI:break; }// @suppress("No break at end of case") - case opcode_e::ANDI: { + case arch::traits::opcode_e::ANDI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -803,7 +965,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -813,7 +975,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_ANDI:break; }// @suppress("No break at end of case") - case opcode_e::SLLI: { + case arch::traits::opcode_e::SLLI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -825,7 +987,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -840,7 +1002,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLLI:break; }// @suppress("No break at end of case") - case opcode_e::SRLI: { + case arch::traits::opcode_e::SRLI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -852,7 +1014,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -867,7 +1029,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SRLI:break; }// @suppress("No break at end of case") - case opcode_e::SRAI: { + case arch::traits::opcode_e::SRAI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -879,7 +1041,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -894,7 +1056,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SRAI:break; }// @suppress("No break at end of case") - case opcode_e::ADD: { + case arch::traits::opcode_e::ADD: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -906,7 +1068,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -916,7 +1078,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_ADD:break; }// @suppress("No break at end of case") - case opcode_e::SUB: { + case arch::traits::opcode_e::SUB: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -928,7 +1090,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -938,7 +1100,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SUB:break; }// @suppress("No break at end of case") - case opcode_e::SLL: { + case arch::traits::opcode_e::SLL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -950,7 +1112,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -960,7 +1122,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLL:break; }// @suppress("No break at end of case") - case opcode_e::SLT: { + case arch::traits::opcode_e::SLT: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -972,7 +1134,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -982,7 +1144,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLT:break; }// @suppress("No break at end of case") - case opcode_e::SLTU: { + case arch::traits::opcode_e::SLTU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -994,7 +1156,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1004,7 +1166,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SLTU:break; }// @suppress("No break at end of case") - case opcode_e::XOR: { + case arch::traits::opcode_e::XOR: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1016,7 +1178,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1026,7 +1188,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_XOR:break; }// @suppress("No break at end of case") - case opcode_e::SRL: { + case arch::traits::opcode_e::SRL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1038,7 +1200,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1048,7 +1210,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SRL:break; }// @suppress("No break at end of case") - case opcode_e::SRA: { + case arch::traits::opcode_e::SRA: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1060,7 +1222,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1070,7 +1232,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SRA:break; }// @suppress("No break at end of case") - case opcode_e::OR: { + case arch::traits::opcode_e::OR: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1082,7 +1244,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1092,7 +1254,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_OR:break; }// @suppress("No break at end of case") - case opcode_e::AND: { + case arch::traits::opcode_e::AND: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1104,7 +1266,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1114,7 +1276,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_AND:break; }// @suppress("No break at end of case") - case opcode_e::FENCE: { + case arch::traits::opcode_e::FENCE: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t succ = ((bit_sub<20,4>(instr))); @@ -1136,7 +1298,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_FENCE:break; }// @suppress("No break at end of case") - case opcode_e::ECALL: { + case arch::traits::opcode_e::ECALL: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "ecall"); @@ -1149,7 +1311,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_ECALL:break; }// @suppress("No break at end of case") - case opcode_e::EBREAK: { + case arch::traits::opcode_e::EBREAK: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "ebreak"); @@ -1162,7 +1324,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_EBREAK:break; }// @suppress("No break at end of case") - case opcode_e::URET: { + case arch::traits::opcode_e::URET: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "uret"); @@ -1175,7 +1337,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_URET:break; }// @suppress("No break at end of case") - case opcode_e::SRET: { + case arch::traits::opcode_e::SRET: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "sret"); @@ -1188,7 +1350,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_SRET:break; }// @suppress("No break at end of case") - case opcode_e::MRET: { + case arch::traits::opcode_e::MRET: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "mret"); @@ -1201,7 +1363,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_MRET:break; }// @suppress("No break at end of case") - case opcode_e::WFI: { + case arch::traits::opcode_e::WFI: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "wfi"); @@ -1214,15 +1376,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_WFI:break; }// @suppress("No break at end of case") - case opcode_e::DRET: { + case arch::traits::opcode_e::DRET: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "dret"); } // used registers - auto* PRIV = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::PRIV]); + auto* PRIV = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PRIV]); - auto* DPC = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::DPC]); + auto* DPC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::DPC]); // calculate next pc value *NEXT_PC = *PC + 4; // execute instruction @@ -1238,7 +1400,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_DRET:break; }// @suppress("No break at end of case") - case opcode_e::CSRRW: { + case arch::traits::opcode_e::CSRRW: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1250,7 +1412,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1270,7 +1432,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRW:break; }// @suppress("No break at end of case") - case opcode_e::CSRRS: { + case arch::traits::opcode_e::CSRRS: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1282,7 +1444,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1300,7 +1462,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRS:break; }// @suppress("No break at end of case") - case opcode_e::CSRRC: { + case arch::traits::opcode_e::CSRRC: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1312,7 +1474,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1330,7 +1492,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRC:break; }// @suppress("No break at end of case") - case opcode_e::CSRRWI: { + case arch::traits::opcode_e::CSRRWI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1342,7 +1504,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1357,7 +1519,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRWI:break; }// @suppress("No break at end of case") - case opcode_e::CSRRSI: { + case arch::traits::opcode_e::CSRRSI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1369,7 +1531,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1386,7 +1548,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRSI:break; }// @suppress("No break at end of case") - case opcode_e::CSRRCI: { + case arch::traits::opcode_e::CSRRCI: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1398,7 +1560,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1415,7 +1577,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRRCI:break; }// @suppress("No break at end of case") - case opcode_e::FENCE_I: { + case arch::traits::opcode_e::FENCE_I: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1435,7 +1597,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_FENCE_I:break; }// @suppress("No break at end of case") - case opcode_e::MUL: { + case arch::traits::opcode_e::MUL: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1447,7 +1609,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1458,7 +1620,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_MUL:break; }// @suppress("No break at end of case") - case opcode_e::MULH: { + case arch::traits::opcode_e::MULH: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1470,7 +1632,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1481,7 +1643,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_MULH:break; }// @suppress("No break at end of case") - case opcode_e::MULHSU: { + case arch::traits::opcode_e::MULHSU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1493,7 +1655,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1504,7 +1666,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_MULHSU:break; }// @suppress("No break at end of case") - case opcode_e::MULHU: { + case arch::traits::opcode_e::MULHU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1516,7 +1678,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1527,7 +1689,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_MULHU:break; }// @suppress("No break at end of case") - case opcode_e::DIV: { + case arch::traits::opcode_e::DIV: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1539,7 +1701,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1560,7 +1722,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_DIV:break; }// @suppress("No break at end of case") - case opcode_e::DIVU: { + case arch::traits::opcode_e::DIVU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1572,7 +1734,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1587,7 +1749,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_DIVU:break; }// @suppress("No break at end of case") - case opcode_e::REM: { + case arch::traits::opcode_e::REM: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1599,7 +1761,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1620,7 +1782,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_REM:break; }// @suppress("No break at end of case") - case opcode_e::REMU: { + case arch::traits::opcode_e::REMU: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1632,7 +1794,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 4; // execute instruction { @@ -1647,7 +1809,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_REMU:break; }// @suppress("No break at end of case") - case opcode_e::CADDI4SPN: { + case arch::traits::opcode_e::CADDI4SPN: { uint8_t rd = ((bit_sub<2,3>(instr))); uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); if(this->disass_enabled){ @@ -1658,7 +1820,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1671,7 +1833,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CADDI4SPN:break; }// @suppress("No break at end of case") - case opcode_e::CLW: { + case arch::traits::opcode_e::CLW: { uint8_t rd = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -1683,7 +1845,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1694,7 +1856,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CLW:break; }// @suppress("No break at end of case") - case opcode_e::CSW: { + case arch::traits::opcode_e::CSW: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -1706,7 +1868,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1716,7 +1878,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSW:break; }// @suppress("No break at end of case") - case opcode_e::CADDI: { + case arch::traits::opcode_e::CADDI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -1727,7 +1889,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1735,7 +1897,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CADDI:break; }// @suppress("No break at end of case") - case opcode_e::CNOP: { + case arch::traits::opcode_e::CNOP: { uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1748,7 +1910,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CNOP:break; }// @suppress("No break at end of case") - case opcode_e::CJAL: { + case arch::traits::opcode_e::CJAL: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1758,7 +1920,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1768,7 +1930,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CJAL:break; }// @suppress("No break at end of case") - case opcode_e::CLI: { + case arch::traits::opcode_e::CLI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -1779,7 +1941,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1789,7 +1951,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CLI:break; }// @suppress("No break at end of case") - case opcode_e::CLUI: { + case arch::traits::opcode_e::CLUI: { uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -1800,7 +1962,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1813,7 +1975,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CLUI:break; }// @suppress("No break at end of case") - case opcode_e::CADDI16SP: { + case arch::traits::opcode_e::CADDI16SP: { uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1823,7 +1985,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1836,7 +1998,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CADDI16SP:break; }// @suppress("No break at end of case") - case opcode_e::__reserved_clui: { + case arch::traits::opcode_e::__reserved_clui: { uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1850,7 +2012,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP___reserved_clui:break; }// @suppress("No break at end of case") - case opcode_e::CSRLI: { + case arch::traits::opcode_e::CSRLI: { uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -1861,7 +2023,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1870,7 +2032,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRLI:break; }// @suppress("No break at end of case") - case opcode_e::CSRAI: { + case arch::traits::opcode_e::CSRAI: { uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -1881,7 +2043,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1898,7 +2060,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSRAI:break; }// @suppress("No break at end of case") - case opcode_e::CANDI: { + case arch::traits::opcode_e::CANDI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -1909,7 +2071,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1918,7 +2080,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CANDI:break; }// @suppress("No break at end of case") - case opcode_e::CSUB: { + case arch::traits::opcode_e::CSUB: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -1929,7 +2091,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1938,7 +2100,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSUB:break; }// @suppress("No break at end of case") - case opcode_e::CXOR: { + case arch::traits::opcode_e::CXOR: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -1949,7 +2111,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1958,7 +2120,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CXOR:break; }// @suppress("No break at end of case") - case opcode_e::COR: { + case arch::traits::opcode_e::COR: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -1969,7 +2131,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1978,7 +2140,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_COR:break; }// @suppress("No break at end of case") - case opcode_e::CAND: { + case arch::traits::opcode_e::CAND: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -1989,7 +2151,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -1998,7 +2160,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CAND:break; }// @suppress("No break at end of case") - case opcode_e::CJ: { + case arch::traits::opcode_e::CJ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2016,7 +2178,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CJ:break; }// @suppress("No break at end of case") - case opcode_e::CBEQZ: { + case arch::traits::opcode_e::CBEQZ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2027,7 +2189,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2038,7 +2200,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CBEQZ:break; }// @suppress("No break at end of case") - case opcode_e::CBNEZ: { + case arch::traits::opcode_e::CBNEZ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -2049,7 +2211,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2060,7 +2222,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CBNEZ:break; }// @suppress("No break at end of case") - case opcode_e::CSLLI: { + case arch::traits::opcode_e::CSLLI: { uint8_t nzuimm = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2071,7 +2233,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2081,7 +2243,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSLLI:break; }// @suppress("No break at end of case") - case opcode_e::CLWSP: { + case arch::traits::opcode_e::CLWSP: { uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2092,7 +2254,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2108,7 +2270,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CLWSP:break; }// @suppress("No break at end of case") - case opcode_e::CMV: { + case arch::traits::opcode_e::CMV: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2119,7 +2281,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2129,7 +2291,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CMV:break; }// @suppress("No break at end of case") - case opcode_e::CJR: { + case arch::traits::opcode_e::CJR: { uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2139,7 +2301,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2153,7 +2315,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CJR:break; }// @suppress("No break at end of case") - case opcode_e::__reserved_cmv: { + case arch::traits::opcode_e::__reserved_cmv: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "__reserved_cmv"); @@ -2166,7 +2328,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP___reserved_cmv:break; }// @suppress("No break at end of case") - case opcode_e::CADD: { + case arch::traits::opcode_e::CADD: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2177,7 +2339,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2187,7 +2349,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CADD:break; }// @suppress("No break at end of case") - case opcode_e::CJALR: { + case arch::traits::opcode_e::CJALR: { uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2197,7 +2359,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2208,7 +2370,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CJALR:break; }// @suppress("No break at end of case") - case opcode_e::CEBREAK: { + case arch::traits::opcode_e::CEBREAK: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "cebreak"); @@ -2221,7 +2383,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CEBREAK:break; }// @suppress("No break at end of case") - case opcode_e::CSWSP: { + case arch::traits::opcode_e::CSWSP: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); if(this->disass_enabled){ @@ -2232,7 +2394,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->core.disass_output(pc.val, mnemonic); } // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+traits::reg_byte_offsets[traits::X0]);// calculate next pc value + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value *NEXT_PC = *PC + 2; // execute instruction { @@ -2242,7 +2404,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_CSWSP:break; }// @suppress("No break at end of case") - case opcode_e::DII: { + case arch::traits::opcode_e::DII: { if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "dii"); From 12ccfc055a3e885da61a74dcf16cc047c8e272a7 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 11 Jul 2022 22:58:10 +0200 Subject: [PATCH 028/184] updates generate tgc_c definition --- src/iss/arch/tgc_c.h | 101 +++++++-------- src/vm/interp/vm_tgc_c.cpp | 258 ++++++++++++++----------------------- 2 files changed, 143 insertions(+), 216 deletions(-) diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index 8e2ae8a..239ea60 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -53,7 +53,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; - enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, RFS=32, INSTR_ALIGNMENT=2, XLEN=32, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; + enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; constexpr static unsigned FP_REGS_SIZE = 0; @@ -81,7 +81,7 @@ template <> struct traits { enum sreg_flag_e { FLAGS }; - enum mem_type_e { MEM, CSR, FENCE, RES }; + enum mem_type_e { MEM, FENCE, RES, CSR }; enum class opcode_e : unsigned short { LUI = 0, @@ -124,56 +124,53 @@ template <> struct traits { FENCE = 37, ECALL = 38, EBREAK = 39, - URET = 40, - SRET = 41, - MRET = 42, - WFI = 43, - DRET = 44, - CSRRW = 45, - CSRRS = 46, - CSRRC = 47, - CSRRWI = 48, - CSRRSI = 49, - CSRRCI = 50, - FENCE_I = 51, - MUL = 52, - MULH = 53, - MULHSU = 54, - MULHU = 55, - DIV = 56, - DIVU = 57, - REM = 58, - REMU = 59, - CADDI4SPN = 60, - CLW = 61, - CSW = 62, - CADDI = 63, - CNOP = 64, - CJAL = 65, - CLI = 66, - CLUI = 67, - CADDI16SP = 68, - __reserved_clui = 69, - CSRLI = 70, - CSRAI = 71, - CANDI = 72, - CSUB = 73, - CXOR = 74, - COR = 75, - CAND = 76, - CJ = 77, - CBEQZ = 78, - CBNEZ = 79, - CSLLI = 80, - CLWSP = 81, - CMV = 82, - CJR = 83, - __reserved_cmv = 84, - CADD = 85, - CJALR = 86, - CEBREAK = 87, - CSWSP = 88, - DII = 89, + MRET = 40, + WFI = 41, + CSRRW = 42, + CSRRS = 43, + CSRRC = 44, + CSRRWI = 45, + CSRRSI = 46, + CSRRCI = 47, + FENCE_I = 48, + MUL = 49, + MULH = 50, + MULHSU = 51, + MULHU = 52, + DIV = 53, + DIVU = 54, + REM = 55, + REMU = 56, + CADDI4SPN = 57, + CLW = 58, + CSW = 59, + CADDI = 60, + CNOP = 61, + CJAL = 62, + CLI = 63, + CLUI = 64, + CADDI16SP = 65, + __reserved_clui = 66, + CSRLI = 67, + CSRAI = 68, + CANDI = 69, + CSUB = 70, + CXOR = 71, + COR = 72, + CAND = 73, + CJ = 74, + CBEQZ = 75, + CBNEZ = 76, + CSLLI = 77, + CLWSP = 78, + CMV = 79, + CJR = 80, + __reserved_cmv = 81, + CADD = 82, + CJALR = 83, + CEBREAK = 84, + CSWSP = 85, + DII = 86, MAX_OPCODE }; }; diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 2f31d63..09d1480 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -197,7 +197,7 @@ private: typename arch::traits::opcode_e op; }; - const std::array instr_descr = {{ + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits::opcode_e::LUI}, {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, arch::traits::opcode_e::AUIPC}, @@ -239,11 +239,8 @@ private: {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, arch::traits::opcode_e::FENCE}, {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::ECALL}, {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::EBREAK}, - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::URET}, - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::SRET}, {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::MRET}, {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::WFI}, - {32, 0b01111011001000000000000001110011, 0b11111111111111111111111111111111, arch::traits::opcode_e::DRET}, {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRW}, {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRS}, {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, arch::traits::opcode_e::CSRRC}, @@ -397,7 +394,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { + if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = (int32_t)imm; } } @@ -418,7 +415,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { + if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = *PC + (int32_t)imm; } } @@ -443,8 +440,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 0); } else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *PC + 4; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *PC + 4; } *NEXT_PC = *PC + (int32_t)sext<21>(imm); super::ex_info.branch_taken=true; @@ -468,13 +465,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - int32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 1; + uint32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 0x1; if(new_pc % traits::INSTR_ALIGNMENT) { raise(0, 0); } else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *PC + 4; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *PC + 4; } *NEXT_PC = new_pc & ~ 0x1; super::ex_info.branch_taken=true; @@ -666,11 +663,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint8_t read_res = super::template read_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + int8_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.trap_state) goto TRAP_LB; int8_t res = (int8_t)read_res; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = res; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)res; } } TRAP_LB:break; @@ -692,11 +690,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - uint16_t read_res = super::template read_mem(traits::MEM, load_address); + int16_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.trap_state) goto TRAP_LH; int16_t res = (int16_t)read_res; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = res; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)res; } } TRAP_LH:break; @@ -718,11 +716,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - uint32_t read_res = super::template read_mem(traits::MEM, load_address); + int32_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.trap_state) goto TRAP_LW; int32_t res = (int32_t)read_res; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (uint32_t)res; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)res; } } TRAP_LW:break; @@ -743,11 +741,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint8_t read_res = super::template read_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)); + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint8_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.trap_state) goto TRAP_LBU; uint8_t res = (uint8_t)read_res; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = res; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (uint32_t)res; } } TRAP_LBU:break; @@ -772,8 +771,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint16_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.trap_state) goto TRAP_LHU; uint16_t res = (uint16_t)read_res; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = res; + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (uint32_t)res; } } TRAP_LHU:break; @@ -794,9 +793,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - super::template write_mem(traits::MEM, *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm), (int8_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state) goto TRAP_SB; - } + uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + super::template write_mem(traits::MEM, store_address, (int8_t)*(X+rs2 % traits::RFS)); + if(this->core.trap_state) goto TRAP_SB; + } TRAP_SB:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SH: { @@ -838,7 +838,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, *(X+rs2 % traits::RFS)); + super::template write_mem(traits::MEM, store_address, (int32_t)*(X+rs2 % traits::RFS)); if(this->core.trap_state) goto TRAP_SW; } TRAP_SW:break; @@ -882,7 +882,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm)? 1 : 0; + *(X+rd % traits::RFS) = ((int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm))? 1 : 0; } } TRAP_SLTI:break; @@ -991,13 +991,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << shamt; - } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << shamt; } } TRAP_SLLI:break; @@ -1018,13 +1013,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> shamt; - } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> shamt; } } TRAP_SRLI:break; @@ -1045,13 +1035,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if(shamt > 31) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; - } + if((rd % traits::RFS) != 0) { + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; } } TRAP_SRAI:break; @@ -1117,7 +1102,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); } } TRAP_SLL:break; @@ -1205,7 +1190,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); } } TRAP_SRL:break; @@ -1227,7 +1212,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); } } TRAP_SRA:break; @@ -1293,7 +1278,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - super::template write_mem(traits::FENCE, traits::fence, pred << 4 | succ); + super::template write_mem(traits::FENCE, traits::fence, pred << 4 | succ); if(this->core.trap_state) goto TRAP_FENCE; } TRAP_FENCE:break; @@ -1324,32 +1309,6 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_EBREAK:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::URET: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "uret"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - leave(0); - } - TRAP_URET:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRET: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "sret"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - leave(1); - } - TRAP_SRET:break; - }// @suppress("No break at end of case") case arch::traits::opcode_e::MRET: { if(this->disass_enabled){ /* generate console output when executing the command */ @@ -1376,30 +1335,6 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } TRAP_WFI:break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::DRET: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "dret"); - } - // used registers - auto* PRIV = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PRIV]); - - auto* DPC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::DPC]); - // calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(*PRIV < 4) { - raise(0, 2); - } - else { - *NEXT_PC = *DPC; - super::ex_info.branch_taken=true; - *PRIV &= 0x3; - } - } - TRAP_DRET:break; - }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRW: { uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); @@ -1417,7 +1352,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { uint32_t xrs1 = *(X+rs1 % traits::RFS); - if((rd % traits::RFS) != 0) { + if((rd % traits::RFS) != 0) { uint32_t read_res = super::template read_mem(traits::CSR, csr); if(this->core.trap_state) goto TRAP_CSRRW; uint32_t xrd = read_res; @@ -1452,11 +1387,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->core.trap_state) goto TRAP_CSRRS; uint32_t xrd = read_res; uint32_t xrs1 = *(X+rs1 % traits::RFS); - if(rs1 != 0) { + if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd | xrs1); if(this->core.trap_state) goto TRAP_CSRRS; } - if((rd % traits::RFS) != 0) { + if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = xrd; } } @@ -1482,11 +1417,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->core.trap_state) goto TRAP_CSRRC; uint32_t xrd = read_res; uint32_t xrs1 = *(X+rs1 % traits::RFS); - if(rs1 != 0) { + if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); if(this->core.trap_state) goto TRAP_CSRRC; } - if((rd % traits::RFS) != 0) { + if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = xrd; } } @@ -1513,7 +1448,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t xrd = read_res; super::template write_mem(traits::CSR, csr, (uint32_t)zimm); if(this->core.trap_state) goto TRAP_CSRRWI; - if((rd % traits::RFS) != 0) { + if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = xrd; } } @@ -1538,11 +1473,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t read_res = super::template read_mem(traits::CSR, csr); if(this->core.trap_state) goto TRAP_CSRRSI; uint32_t xrd = read_res; - if(zimm != 0) { + if(zimm != 0) { super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); if(this->core.trap_state) goto TRAP_CSRRSI; } - if((rd % traits::RFS) != 0) { + if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = xrd; } } @@ -1567,11 +1502,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t read_res = super::template read_mem(traits::CSR, csr); if(this->core.trap_state) goto TRAP_CSRRCI; uint32_t xrd = read_res; - if(zimm != 0) { + if(zimm != 0) { super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); if(this->core.trap_state) goto TRAP_CSRRCI; } - if((rd % traits::RFS) != 0) { + if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = xrd; } } @@ -1706,7 +1641,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) { uint32_t MMIN = 1 << (traits::XLEN - 1); if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) { *(X+rd % traits::RFS) = MMIN; @@ -1739,7 +1674,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) { *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) / *(X+rs2 % traits::RFS); } else { @@ -1766,7 +1701,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) { uint32_t MMIN = 1 << (traits::XLEN - 1); if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) { *(X+rd % traits::RFS) = 0; @@ -1799,7 +1734,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { + if(*(X+rs2 % traits::RFS) != 0) { *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) % *(X+rs2 % traits::RFS); } else { @@ -1825,7 +1760,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if(imm) { - *(X+rd + 8) = *(X+2) + imm; + *(X+rd + 8) = *(X+2) + imm; } else { raise(0, 2); @@ -1849,10 +1784,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint32_t load_address = *(X+rs1 + 8) + uimm; - uint32_t read_res = super::template read_mem(traits::MEM, load_address); + uint32_t load_address = *(X+rs1 + 8) + uimm; + int32_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.trap_state) goto TRAP_CLW; - *(X+rd + 8) = (int32_t)read_res; + *(X+rd + 8) = (int32_t)read_res; } TRAP_CLW:break; }// @suppress("No break at end of case") @@ -1872,8 +1807,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint32_t load_address = *(X+rs1 + 8) + uimm; - super::template write_mem(traits::MEM, load_address, *(X+rs2 + 8)); + uint32_t load_address = *(X+rs1 + 8) + uimm; + super::template write_mem(traits::MEM, load_address, (int32_t)*(X+rs2 + 8)); if(this->core.trap_state) goto TRAP_CSW; } TRAP_CSW:break; @@ -1893,7 +1828,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) + (int8_t)sext<6>(imm); + if((rs1 % traits::RFS) != 0) { + *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) + (int8_t)sext<6>(imm); + } } TRAP_CADDI:break; }// @suppress("No break at end of case") @@ -1924,7 +1861,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - *(X+1) = *PC + 2; + *(X+1) = *PC + 2; *NEXT_PC = *PC + (int16_t)sext<12>(imm); super::ex_info.branch_taken=true; } @@ -2027,8 +1964,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = *(X+rs1_idx) >> shamt; + *(X+rs1 + 8) = *(X+rs1 + 8) >> shamt; } TRAP_CSRLI:break; }// @suppress("No break at end of case") @@ -2047,17 +1983,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if(shamt) { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; - } - else { - if(traits::XLEN == 128) { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; - } - } - } + if(shamt) { + *(X+rs1 + 8) = ((int32_t)*(X+rs1 + 8)) >> shamt; + } + else { + if(traits::XLEN == 128) { + *(X+rs1 + 8) = ((int32_t)*(X+rs1 + 8)) >> 64; + } + } + } TRAP_CSRAI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CANDI: { @@ -2075,8 +2009,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm); + *(X+rs1 + 8) = *(X+rs1 + 8) & (int8_t)sext<6>(imm); } TRAP_CANDI:break; }// @suppress("No break at end of case") @@ -2095,8 +2028,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint8_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) - *(X+rs2 + 8); + *(X+rd + 8) = *(X+rd + 8) - *(X+rs2 + 8); } TRAP_CSUB:break; }// @suppress("No break at end of case") @@ -2115,8 +2047,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint8_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) ^ *(X+rs2 + 8); + *(X+rd + 8) = *(X+rd + 8) ^ *(X+rs2 + 8); } TRAP_CXOR:break; }// @suppress("No break at end of case") @@ -2135,8 +2066,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint8_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) | *(X+rs2 + 8); + *(X+rd + 8) = *(X+rd + 8) | *(X+rs2 + 8); } TRAP_COR:break; }// @suppress("No break at end of case") @@ -2155,8 +2085,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint8_t rd_idx = rd + 8; - *(X+rd_idx) = *(X+rd_idx) & *(X+rs2 + 8); + *(X+rd + 8) = *(X+rd + 8) & *(X+rs2 + 8); } TRAP_CAND:break; }// @suppress("No break at end of case") @@ -2193,7 +2122,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if(*(X+rs1 + 8) == 0) { + if(*(X+rs1 + 8) == 0) { *NEXT_PC = *PC + (int16_t)sext<9>(imm); super::ex_info.branch_taken=true; } @@ -2215,7 +2144,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if(*(X+rs1 + 8) != 0) { + if(*(X+rs1 + 8) != 0) { *NEXT_PC = *PC + (int16_t)sext<9>(imm); super::ex_info.branch_taken=true; } @@ -2258,16 +2187,17 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if(rd) { - uint32_t offs = *(X+2) + uimm; - uint32_t read_res = super::template read_mem(traits::MEM, offs); - if(this->core.trap_state) goto TRAP_CLWSP; - *(X+rd % traits::RFS) = (int32_t)read_res; - } - else { - raise(0, 2); - } - } + uint32_t offs = *(X+2) + uimm; + int32_t read_res = super::template read_mem(traits::MEM, offs); + if(this->core.trap_state) goto TRAP_CLWSP; + int32_t res = read_res; + if(rd % traits::RFS) { + *(X+rd % traits::RFS) = res; + } + else { + raise(0, 2); + } + } TRAP_CLWSP:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CMV: { @@ -2363,8 +2293,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - int32_t new_pc = *(X+rs1 % traits::RFS); - *(X+1) = *PC + 2; + uint32_t new_pc = *(X+rs1 % traits::RFS); + *(X+1) = *PC + 2; *NEXT_PC = new_pc & ~ 0x1; super::ex_info.branch_taken=true; } From a53ee42e13e59cb23336990edd034756a6df7cfb Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 12 Jul 2022 22:34:22 +0200 Subject: [PATCH 029/184] updates TGC_C according to CoreDSL description update --- src/vm/interp/vm_tgc_c.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 09d1480..14ff892 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -2187,12 +2187,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint32_t offs = *(X+2) + uimm; - int32_t read_res = super::template read_mem(traits::MEM, offs); - if(this->core.trap_state) goto TRAP_CLWSP; - int32_t res = read_res; if(rd % traits::RFS) { - *(X+rd % traits::RFS) = res; + int32_t read_res = super::template read_mem(traits::MEM, *(X+2) + uimm); + if(this->core.trap_state) goto TRAP_CLWSP; + int32_t res = read_res; + *(X+rd % traits::RFS) = (int32_t)res; } else { raise(0, 2); From 4876f18ba941f62176eeab8d902aaf7fa1211577 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 18 Jul 2022 11:02:17 +0200 Subject: [PATCH 030/184] adds windows compatibility fixes --- .../templates/llvm/vm-vm_CORENAME.cpp.gtl | 4 +- src/iss/plugin/cycle_estimate.h | 2 +- src/main.cpp | 471 +++++++++--------- src/sysc/core_complex.cpp | 34 +- src/vm/interp/vm_tgc_c.cpp | 5 +- 5 files changed, 262 insertions(+), 254 deletions(-) diff --git a/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl index 881cb30..d0a8067 100644 --- a/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl @@ -30,10 +30,10 @@ * *******************************************************************************/ -#include -#include #include #include +#include +#include #include #include #include diff --git a/src/iss/plugin/cycle_estimate.h b/src/iss/plugin/cycle_estimate.h index a8345f5..f35f106 100644 --- a/src/iss/plugin/cycle_estimate.h +++ b/src/iss/plugin/cycle_estimate.h @@ -45,7 +45,7 @@ namespace iss { namespace plugin { -class cycle_estimate: public iss::vm_plugin { +class cycle_estimate: public vm_plugin { BEGIN_BF_DECL(instr_desc, uint32_t) BF_FIELD(taken, 24, 8) BF_FIELD(not_taken, 16, 8) diff --git a/src/main.cpp b/src/main.cpp index c2b5254..2948993 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,236 +1,241 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -#include -#include - -#include -#include -#include "iss/arch/tgc_mapper.h" -#ifdef WITH_LLVM -#include -#endif -#include -#include "iss/plugin/cycle_estimate.h" -#include "iss/plugin/instruction_count.h" -#include "iss/plugin/pctrace.h" -#include -#if defined(HAS_LUA) -#include -#endif - -namespace po = boost::program_options; - -int main(int argc, char *argv[]) { - /* - * Define and parse the program options - */ - po::variables_map clim; - po::options_description desc("Options"); - // clang-format off - desc.add_options() - ("help,h", "Print help message") - ("verbose,v", po::value()->implicit_value(0), "Sets logging verbosity") - ("logfile,l", po::value(), "Sets default log file.") - ("disass,d", po::value()->implicit_value(""), "Enables disassembly") - ("gdb-port,g", po::value()->default_value(0), "enable gdb server and specify port to use") - ("instructions,i", po::value()->default_value(std::numeric_limits::max()), "max. number of instructions to simulate") - ("reset,r", po::value(), "reset address") - ("dump-ir", "dump the intermediate representation") - ("elf,f", po::value>(), "ELF file(s) to load") - ("mem,m", po::value(), "the memory input file") - ("plugin,p", po::value>(), "plugin to activate") - ("backend", po::value()->default_value("interp"), "the memory input file") - ("isa", po::value()->default_value("tgc_c"), "isa to use for simulation"); - // clang-format on - auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); - try { - po::store(parsed, clim); // can throw - // --help option - if (clim.count("help")) { - std::cout << "DBT-RISE-RiscV simulator for RISC-V" << std::endl << desc << std::endl; - return 0; - } - po::notify(clim); // throws on error, so do after help in case - } catch (po::error &e) { - // there are problems - std::cerr << "ERROR: " << e.what() << std::endl << std::endl; - std::cerr << desc << std::endl; - return 1; - } - std::vector args = collect_unrecognized(parsed.options, po::include_positional); - - LOGGER(DEFAULT)::print_time() = false; - LOGGER(connection)::print_time() = false; - if (clim.count("verbose")) { - auto l = logging::as_log_level(clim["verbose"].as()); - LOGGER(DEFAULT)::reporting_level() = l; - LOGGER(connection)::reporting_level() = l; - } - if (clim.count("logfile")) { - // configure the connection logger - auto f = fopen(clim["logfile"].as().c_str(), "w"); - LOG_OUTPUT(DEFAULT)::stream() = f; - LOG_OUTPUT(connection)::stream() = f; - } - - std::vector plugin_list; - auto res = 0; - try { -#ifdef WITH_LLVM - // application code comes here // - iss::init_jit_debug(argc, argv); -#endif - bool dump = clim.count("dump-ir"); - // instantiate the simulator - iss::vm_ptr vm{nullptr}; - iss::cpu_ptr cpu{nullptr}; - std::string isa_opt(clim["isa"].as()); - if (isa_opt == "tgc_c") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#ifdef CORE_TGC_B - if (isa_opt == "tgc_b") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_C_XRB_NN - if (isa_opt == "tgc_c_xrb_nn") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D - if (isa_opt == "tgc_d") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D_XRB_MAC - if (isa_opt == "tgc_d_xrb_mac") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D_XRB_NN - if (isa_opt == "tgc_d_xrb_nn") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_E - if (isa_opt == "tgc_e") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif - { +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#include +#include "iss/factory.h" + +#include +#include +#include "iss/arch/tgc_mapper.h" +#ifdef WITH_LLVM +#include +#endif +#include +#include "iss/plugin/cycle_estimate.h" +#include "iss/plugin/instruction_count.h" +#include "iss/plugin/pctrace.h" +#ifndef WIN32 +#include +#endif +#if defined(HAS_LUA) +#include +#endif + +namespace po = boost::program_options; + +int main(int argc, char *argv[]) { + /* + * Define and parse the program options + */ + po::variables_map clim; + po::options_description desc("Options"); + // clang-format off + desc.add_options() + ("help,h", "Print help message") + ("verbose,v", po::value()->implicit_value(0), "Sets logging verbosity") + ("logfile,l", po::value(), "Sets default log file.") + ("disass,d", po::value()->implicit_value(""), "Enables disassembly") + ("gdb-port,g", po::value()->default_value(0), "enable gdb server and specify port to use") + ("instructions,i", po::value()->default_value(std::numeric_limits::max()), "max. number of instructions to simulate") + ("reset,r", po::value(), "reset address") + ("dump-ir", "dump the intermediate representation") + ("elf,f", po::value>(), "ELF file(s) to load") + ("mem,m", po::value(), "the memory input file") + ("plugin,p", po::value>(), "plugin to activate") + ("backend", po::value()->default_value("interp"), "the memory input file") + ("isa", po::value()->default_value("tgc_c"), "isa to use for simulation"); + // clang-format on + auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); + try { + po::store(parsed, clim); // can throw + // --help option + if (clim.count("help")) { + std::cout << "DBT-RISE-RiscV simulator for RISC-V" << std::endl << desc << std::endl; + return 0; + } + po::notify(clim); // throws on error, so do after help in case + } catch (po::error &e) { + // there are problems + std::cerr << "ERROR: " << e.what() << std::endl << std::endl; + std::cerr << desc << std::endl; + return 1; + } + std::vector args = collect_unrecognized(parsed.options, po::include_positional); + + LOGGER(DEFAULT)::print_time() = false; + LOGGER(connection)::print_time() = false; + if (clim.count("verbose")) { + auto l = logging::as_log_level(clim["verbose"].as()); + LOGGER(DEFAULT)::reporting_level() = l; + LOGGER(connection)::reporting_level() = l; + } + if (clim.count("logfile")) { + // configure the connection logger + auto f = fopen(clim["logfile"].as().c_str(), "w"); + LOG_OUTPUT(DEFAULT)::stream() = f; + LOG_OUTPUT(connection)::stream() = f; + } + + std::vector plugin_list; + auto res = 0; + try { +#ifdef WITH_LLVM + // application code comes here // + iss::init_jit_debug(argc, argv); +#endif + bool dump = clim.count("dump-ir"); + // instantiate the simulator + iss::vm_ptr vm{nullptr}; + iss::cpu_ptr cpu{nullptr}; + std::string isa_opt(clim["isa"].as()); + if (isa_opt == "tgc_c") { + std::tie(cpu, vm) = + iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else +#ifdef CORE_TGC_B + if (isa_opt == "tgc_b") { + std::tie(cpu, vm) = + iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else +#endif +#ifdef CORE_TGC_C_XRB_NN + if (isa_opt == "tgc_c_xrb_nn") { + std::tie(cpu, vm) = + iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else +#endif +#ifdef CORE_TGC_D + if (isa_opt == "tgc_d") { + std::tie(cpu, vm) = + iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else +#endif +#ifdef CORE_TGC_D_XRB_MAC + if (isa_opt == "tgc_d_xrb_mac") { + std::tie(cpu, vm) = + iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else +#endif +#ifdef CORE_TGC_D_XRB_NN + if (isa_opt == "tgc_d_xrb_nn") { + std::tie(cpu, vm) = + iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else +#endif +#ifdef CORE_TGC_E + if (isa_opt == "tgc_e") { + std::tie(cpu, vm) = + iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else +#endif + { LOG(ERR) << "Illegal argument value for '--isa': " << isa_opt << std::endl; - return 127; - } - if (clim.count("plugin")) { - for (std::string const& opt_val : clim["plugin"].as>()) { - std::string plugin_name=opt_val; - std::string filename{"cycles.txt"}; - std::size_t found = opt_val.find('='); - if (found != std::string::npos) { - plugin_name = opt_val.substr(0, found); - filename = opt_val.substr(found + 1, opt_val.size()); - } - if (plugin_name == "ic") { - auto *ic_plugin = new iss::plugin::instruction_count(filename); - vm->register_plugin(*ic_plugin); - plugin_list.push_back(ic_plugin); - } else if (plugin_name == "ce") { - auto *ce_plugin = new iss::plugin::cycle_estimate(filename); - vm->register_plugin(*ce_plugin); - plugin_list.push_back(ce_plugin); - } else if (plugin_name == "pctrace") { - auto *plugin = new iss::plugin::pctrace(filename); - vm->register_plugin(*plugin); - plugin_list.push_back(plugin); - } else { - std::array a{{filename.c_str()}}; - iss::plugin::loader l(plugin_name, {{"initPlugin"}}); - auto* plugin = l.call_function("initPlugin", a.size(), a.data()); - if(plugin){ - vm->register_plugin(*plugin); - plugin_list.push_back(plugin); - } else { + return 127; + } + if (clim.count("plugin")) { + for (std::string const& opt_val : clim["plugin"].as>()) { + std::string plugin_name=opt_val; + std::string filename{"cycles.txt"}; + std::size_t found = opt_val.find('='); + if (found != std::string::npos) { + plugin_name = opt_val.substr(0, found); + filename = opt_val.substr(found + 1, opt_val.size()); + } + if (plugin_name == "ic") { + auto *ic_plugin = new iss::plugin::instruction_count(filename); + vm->register_plugin(*ic_plugin); + plugin_list.push_back(ic_plugin); + } else if (plugin_name == "ce") { + auto *ce_plugin = new iss::plugin::cycle_estimate(filename); + vm->register_plugin(*ce_plugin); + plugin_list.push_back(ce_plugin); + } else if (plugin_name == "pctrace") { + auto *plugin = new iss::plugin::pctrace(filename); + vm->register_plugin(*plugin); + plugin_list.push_back(plugin); + } else { +#ifndef WIN32 + std::array a{{filename.c_str()}}; + iss::plugin::loader l(plugin_name, {{"initPlugin"}}); + auto* plugin = l.call_function("initPlugin", a.size(), a.data()); + if(plugin){ + vm->register_plugin(*plugin); + plugin_list.push_back(plugin); + } else +#endif + { LOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl; - return 127; - } - } - } - } - if (clim.count("disass")) { - vm->setDisassEnabled(true); - LOGGER(disass)::reporting_level() = logging::INFO; - LOGGER(disass)::print_time() = false; - auto file_name = clim["disass"].as(); - if (file_name.length() > 0) { - LOG_OUTPUT(disass)::stream() = fopen(file_name.c_str(), "w"); - LOGGER(disass)::print_severity() = false; - } - } - uint64_t start_address = 0; - if (clim.count("mem")) - vm->get_arch()->load_file(clim["mem"].as()); - if (clim.count("elf")) - for (std::string input : clim["elf"].as>()) { - auto start_addr = vm->get_arch()->load_file(input); - if (start_addr.second) start_address = start_addr.first; - } - for (std::string input : args) { - auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files - if (start_addr.second) start_address = start_addr.first; - } - if (clim.count("reset")) { - auto str = clim["reset"].as(); - start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), nullptr, 16) : std::stoull(str, nullptr, 10); - } - vm->reset(start_address); - auto cycles = clim["instructions"].as(); - res = vm->start(cycles, dump); - } catch (std::exception &e) { + return 127; + } + } + } + } + if (clim.count("disass")) { + vm->setDisassEnabled(true); + LOGGER(disass)::reporting_level() = logging::INFO; + LOGGER(disass)::print_time() = false; + auto file_name = clim["disass"].as(); + if (file_name.length() > 0) { + LOG_OUTPUT(disass)::stream() = fopen(file_name.c_str(), "w"); + LOGGER(disass)::print_severity() = false; + } + } + uint64_t start_address = 0; + if (clim.count("mem")) + vm->get_arch()->load_file(clim["mem"].as()); + if (clim.count("elf")) + for (std::string input : clim["elf"].as>()) { + auto start_addr = vm->get_arch()->load_file(input); + if (start_addr.second) start_address = start_addr.first; + } + for (std::string input : args) { + auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files + if (start_addr.second) start_address = start_addr.first; + } + if (clim.count("reset")) { + auto str = clim["reset"].as(); + start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), nullptr, 16) : std::stoull(str, nullptr, 10); + } + vm->reset(start_address); + auto cycles = clim["instructions"].as(); + res = vm->start(cycles, dump); + } catch (std::exception &e) { LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" - << std::endl; - res = 2; - } - // cleanup to let plugins report of needed - for (auto *p : plugin_list) { - delete p; - } - return res; -} + << std::endl; + res = 2; + } + // cleanup to let plugins report of needed + for (auto *p : plugin_list) { + delete p; + } + return res; +} diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index ffd4737..e3730f2 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -30,14 +30,16 @@ * *******************************************************************************/ -// clang-format off -#include -#include -#include -#include -#include +// clang-format off +#include +#include +#include +#include +#include #include -#include +#ifndef WIN32 +#include +#endif #include "core_complex.h" #include #include @@ -49,7 +51,7 @@ #include #include -// clang-format on +// clang-format on #define STR(X) #X #define CREATE_CORE(CN) \ @@ -68,12 +70,12 @@ using namespace scv_tr; #define GET_PROP_VALUE(P) P.getValue() #endif -#ifdef _MSC_VER -// not #if defined(_WIN32) || defined(_WIN64) because we have strncasecmp in mingw -#define strncasecmp _strnicmp -#define strcasecmp _stricmp -#endif - +#ifdef _MSC_VER +// not #if defined(_WIN32) || defined(_WIN64) because we have strncasecmp in mingw +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + namespace sysc { namespace tgfs { using namespace std; @@ -296,7 +298,7 @@ public: CREATE_CORE(tgc_d_xrb_nn) #endif { - LOG(ERR) << "Illegal argument value for core type: " << type << std::endl; + LOG(ERR) << "Illegal argument value for core type: " << type << std::endl; } auto *srv = debugger::server::get(); if (srv) tgt_adapter = srv->get_target(); @@ -409,6 +411,7 @@ void core_complex::before_end_of_elaboration() { cpu->vm->register_plugin(*plugin); plugin_list.push_back(plugin); } else { +#ifndef WIN32 std::array a{{filename.c_str()}}; iss::plugin::loader l(plugin_name, {{"initPlugin"}}); auto* plugin = l.call_function("initPlugin", a.size(), a.data()); @@ -416,6 +419,7 @@ void core_complex::before_end_of_elaboration() { cpu->vm->register_plugin(*plugin); plugin_list.push_back(plugin); } else +#endif SCCERR(SCMOD) << "Unknown plugin '" << plugin_name << "' or plugin not found"; } } diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 14ff892..c51b1b1 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -30,11 +30,10 @@ * *******************************************************************************/ -#include -#include -#include #include #include +#include +#include #include #include #include From 57347ae4d9fc87bc6412c5afbe295299752fd369 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 23 Jul 2022 13:48:55 +0200 Subject: [PATCH 031/184] fixes cppcheck flagged issues --- src/iss/arch/riscv_hart_m_p.h | 22 +++++++++++----------- src/iss/arch/riscv_hart_mu_p.h | 26 +++++++++++++------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index c0059b2..8365a5d 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -477,10 +477,10 @@ template std::pair riscv_hart_m if (fp) { std::array buf; auto n = fread(buf.data(), 1, 4, fp); + fclose(fp); if (n != 4) throw std::runtime_error("input file has insufficient size"); buf[4] = 0; if (strcmp(buf.data() + 1, "ELF") == 0) { - fclose(fp); // Create elfio reader ELFIO::elfio reader; // Load ELF data @@ -571,12 +571,12 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { fault_data = addr; if (is_debug(access)) throw trap_access(0, addr); - this->trap_state = (1 << 31); // issue trap 0 + this->trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { if(!is_debug(access) && (addr&(alignment-1))){ - this->trap_state = 1<<31 | 4<<16; + this->trap_state = (1UL << 31) | 4<<16; fault_data=addr; return iss::Err; } @@ -595,12 +595,12 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce res = read_mem( phys_addr, length, data); } if (unlikely(res != iss::Ok)){ - this->trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault + this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; } return res; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -626,7 +626,7 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce } return iss::Ok; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -664,12 +664,12 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->trap_state = (1 << 31); // issue trap 0 + this->trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ - this->trap_state = 1<<31 | 6<<16; + this->trap_state = (1UL << 31) | 6<<16; fault_data=addr; return iss::Err; } @@ -688,12 +688,12 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc res = write_mem( phys_addr, length, data); } if (unlikely(res != iss::Ok)) { - this->trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) + this->trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } return res; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -753,7 +753,7 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc } return iss::Ok; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 1cf8484..87ff8b9 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -526,10 +526,10 @@ template std::pair riscv_hart_m if (fp) { std::array buf; auto n = fread(buf.data(), 1, 4, fp); + fclose(fp); if (n != 4) throw std::runtime_error("input file has insufficient size"); buf[4] = 0; if (strcmp(buf.data() + 1, "ELF") == 0) { - fclose(fp); // Create elfio reader ELFIO::elfio reader; // Load ELF data @@ -708,7 +708,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc if(!pmp_check(access, addr, length) && !is_debug(access)) { fault_data = addr; if (is_debug(access)) throw trap_access(0, addr); - this->trap_state = (1 << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1 + this->trap_state = (1UL << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1 return iss::Err; } } @@ -716,12 +716,12 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { fault_data = addr; if (is_debug(access)) throw trap_access(0, addr); - this->trap_state = (1 << 31); // issue trap 0 + this->trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { if(!is_debug(access) && (addr&(alignment-1))){ - this->trap_state = 1<<31 | 4<<16; + this->trap_state = (1UL << 31) | 4<<16; fault_data=addr; return iss::Err; } @@ -740,12 +740,12 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc res = read_mem( phys_addr, length, data); } if (unlikely(res != iss::Ok)){ - this->trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault + this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; } return res; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -771,7 +771,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc } return iss::Ok; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -810,19 +810,19 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->trap_state = (1 << 31) | (7 << 16); // issue trap 1 + this->trap_state = (1UL << 31) | (7 << 16); // issue trap 1 return iss::Err; } } if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->trap_state = (1 << 31); // issue trap 0 + this->trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ - this->trap_state = 1<<31 | 6<<16; + this->trap_state = (1UL << 31) | 6<<16; fault_data=addr; return iss::Err; } @@ -841,12 +841,12 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac res = write_mem( phys_addr, length, data); } if (unlikely(res != iss::Ok)) { - this->trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) + this->trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } return res; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -906,7 +906,7 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac } return iss::Ok; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } From 0833198d3434951c9648fc9304ec06371527d915 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 23 Jul 2022 14:36:23 +0200 Subject: [PATCH 032/184] aads missing windows compat firx to template --- gen_input/templates/interp/CORENAME.cpp.gtl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 1fd65a4..f3873b4 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -36,11 +36,10 @@ def nativeTypeSize(int size){ if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; } %> -#include -#include -#include #include #include +#include +#include #include #include #include From 8407f6287f38e1410affddeeac97a54e6241586b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 24 Jul 2022 20:52:16 +0200 Subject: [PATCH 033/184] replaces core_complex socket --- src/sysc/core_complex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sysc/core_complex.h b/src/sysc/core_complex.h index 33db30b..f764a8a 100644 --- a/src/sysc/core_complex.h +++ b/src/sysc/core_complex.h @@ -69,7 +69,7 @@ struct core_trace; class core_complex : public sc_core::sc_module, public scc::traceable { public: - tlm::scc::initiator_mixin> initiator{"intor"}; + tlm::scc::initiator_mixin> initiator{"intor"}; sc_core::sc_in rst_i{"rst_i"}; @@ -84,7 +84,7 @@ public: #ifndef CWR_SYSTEMC sc_core::sc_in clk_i{"clk_i"}; - sc_core::sc_port, 1, sc_core::SC_ZERO_OR_MORE_BOUND> mtime_o; + sc_core::sc_port, 1, sc_core::SC_ZERO_OR_MORE_BOUND> mtime_o{"mtime_o"}; cci::cci_param elf_file{"elf_file", ""}; From e60fa3d5e6b873742ab9e7a0130ccdb4df25f34b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 6 Aug 2022 09:49:32 +0200 Subject: [PATCH 034/184] adaptes to changes in dbt-rise-core --- src/iss/debugger/riscv_target_adapter.h | 170 +++++++++++++----------- 1 file changed, 91 insertions(+), 79 deletions(-) diff --git a/src/iss/debugger/riscv_target_adapter.h b/src/iss/debugger/riscv_target_adapter.h index b7c3036..0c008d9 100644 --- a/src/iss/debugger/riscv_target_adapter.h +++ b/src/iss/debugger/riscv_target_adapter.h @@ -85,7 +85,7 @@ public: 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; + std::vector &avail_buf) override; /* Write one register. buf is 4-byte aligned and it is in target byte order */ @@ -104,7 +104,7 @@ public: 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; + size_t &num, bool &done) override; status current_thread_query(rp_thread_ref &thread) override; @@ -120,12 +120,12 @@ public: status packetsize_query(std::string &out_buf) override; - status add_break(int type, uint64_t addr, unsigned int length) override; + status add_break(break_type type, uint64_t addr, unsigned int length) override; - status remove_break(int type, uint64_t addr, unsigned int length) override; + status remove_break(break_type type, uint64_t addr, unsigned int length) override; status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, - std::function stop_callback) override; + std::function stop_callback) override; status target_xml_query(std::string &out_buf) override; @@ -159,8 +159,8 @@ template status riscv_target_adapter::is_thread_alive(rp_t */ template status riscv_target_adapter::thread_list_query(int first, const rp_thread_ref &arg, - std::vector &result, size_t max_num, size_t &num, - bool &done) { + std::vector &result, size_t max_num, size_t &num, + bool &done) { if (first == 0) { result.clear(); result.push_back(thread_idx); @@ -193,20 +193,20 @@ status riscv_target_adapter::read_registers(std::vector &data, st } } // work around fill with F type registers -// if (arch::traits::NUM_REGS < 65) { -// auto reg_width = sizeof(typename arch::traits::reg_t); -// for (size_t reg_no = 0; reg_no < 33; ++reg_no) { -// for (size_t j = 0; j < reg_width; ++j) { -// data.push_back(0x0); -// avail.push_back(0x00); -// } -// // if(arch::traits::XLEN < 64) -// // for(unsigned j=0; j<4; ++j){ -// // data.push_back(0x0); -// // avail.push_back(0x00); -// // } -// } -// } + // if (arch::traits::NUM_REGS < 65) { + // auto reg_width = sizeof(typename arch::traits::reg_t); + // for (size_t reg_no = 0; reg_no < 33; ++reg_no) { + // for (size_t j = 0; j < reg_width; ++j) { + // data.push_back(0x0); + // avail.push_back(0x00); + // } + // // if(arch::traits::XLEN < 64) + // // for(unsigned j=0; j<4; ++j){ + // // data.push_back(0x0); + // // avail.push_back(0x00); + // // } + // } + // } return Ok; } @@ -240,7 +240,7 @@ template status riscv_target_adapter::write_registers(cons template status riscv_target_adapter::read_single_register(unsigned int reg_no, std::vector &data, - std::vector &avail) { + std::vector &avail) { if (reg_no < 65) { // auto reg_size = arch::traits::reg_bit_width(static_cast::reg_e>(reg_no))/8; @@ -331,34 +331,46 @@ template status riscv_target_adapter::packetsize_query(std return Ok; } -template status riscv_target_adapter::add_break(int type, uint64_t addr, unsigned int length) { - auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); - auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length}); - target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); - LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex - << saddr.val << std::dec; - LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; - return Ok; -} - -template status riscv_target_adapter::remove_break(int type, uint64_t addr, unsigned int length) { - auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); - unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); - if (handle) { - LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val - << std::dec; - // TODO: check length of addr range - target_adapter_base::bp_lut.removeEntry(handle); +template status riscv_target_adapter::add_break(break_type type, uint64_t addr, unsigned int length) { + switch(type) { + default: + return Err; + case HW_EXEC: { + auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); + auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length}); + target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); + LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex + << saddr.val << std::dec; LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; return Ok; } - LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; - return Err; + } +} + +template status riscv_target_adapter::remove_break(break_type type, uint64_t addr, unsigned int length) { + switch(type) { + default: + return Err; + case HW_EXEC: { + auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); + unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); + if (handle) { + LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val + << std::dec; + // TODO: check length of addr range + target_adapter_base::bp_lut.removeEntry(handle); + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Ok; + } + LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; + return Err; + } + } } template status riscv_target_adapter::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, - std::function stop_callback) { + std::function stop_callback) { auto *reg_base = core->get_regs_base_ptr(); auto reg_width = arch::traits::reg_bit_widths[arch::traits::PC] / 8; auto offset = traits::reg_byte_offsets[arch::traits::PC]; @@ -369,42 +381,42 @@ status riscv_target_adapter::resume_from_addr(bool step, int sig, uint64_t template status riscv_target_adapter::target_xml_query(std::string &out_buf) { const std::string res{"" - "riscv:rv32" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - ""}; + "riscv:rv32" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + ""}; out_buf = res; return Ok; } From 1ad66a71d8e706b37b4d3b2868ac9917c712b00a Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 6 Aug 2022 09:53:24 +0200 Subject: [PATCH 035/184] extends supported break point types --- src/iss/debugger/riscv_target_adapter.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/iss/debugger/riscv_target_adapter.h b/src/iss/debugger/riscv_target_adapter.h index 0c008d9..d8d105e 100644 --- a/src/iss/debugger/riscv_target_adapter.h +++ b/src/iss/debugger/riscv_target_adapter.h @@ -335,6 +335,7 @@ template status riscv_target_adapter::add_break(break_type switch(type) { default: return Err; + case SW_EXEC: case HW_EXEC: { auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length}); @@ -351,6 +352,7 @@ template status riscv_target_adapter::remove_break(break_t switch(type) { default: return Err; + case SW_EXEC: case HW_EXEC: { auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); From 00e02bf5656af608632bc31eeec04470d27e3a52 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 8 Aug 2022 06:30:37 +0200 Subject: [PATCH 036/184] adds support for different branch types in tracing --- gen_input/templates/interp/CORENAME.cpp.gtl | 41 ++------------------- src/vm/interp/vm_tgc_c.cpp | 41 ++------------------- 2 files changed, 6 insertions(+), 76 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index f3873b4..930a818 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -137,44 +137,6 @@ protected: using coro_t = boost::coroutines2::coroutine::pull_type; std::vector spawn_blocks; - template - T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} - inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } template::type> inline S sext(U from) { auto mask = (1ULL< ${it}<%}%> diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index c51b1b1..291eea8 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -131,44 +131,6 @@ protected: using coro_t = boost::coroutines2::coroutine::pull_type; std::vector spawn_blocks; - template - T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;} - inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){ - auto ret = super::template read_mem(space, addr); - if(this->core.trap_state) throw 0; - return ret; - } - inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } - inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){ - super::write_mem(space, addr, data); - if(this->core.trap_state) throw 0; - } template::type> inline S sext(U from) { auto mask = (1ULL< Date: Wed, 31 Aug 2022 11:45:53 +0200 Subject: [PATCH 037/184] fixes wrong check for exception --- src/vm/interp/vm_tgc_c.cpp | 54 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 291eea8..a71d8c5 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -629,7 +629,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); int8_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state) goto TRAP_LB; + if(this->core.trap_state>=0x80000000UL) goto TRAP_LB; int8_t res = (int8_t)read_res; if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = (int32_t)res; @@ -655,7 +655,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); int16_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state) goto TRAP_LH; + if(this->core.trap_state>=0x80000000UL) goto TRAP_LH; int16_t res = (int16_t)read_res; if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = (int32_t)res; @@ -681,7 +681,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); int32_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state) goto TRAP_LW; + if(this->core.trap_state>=0x80000000UL) goto TRAP_LW; int32_t res = (int32_t)read_res; if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = (int32_t)res; @@ -707,7 +707,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); uint8_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state) goto TRAP_LBU; + if(this->core.trap_state>=0x80000000UL) goto TRAP_LBU; uint8_t res = (uint8_t)read_res; if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = (uint32_t)res; @@ -733,7 +733,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); uint16_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state) goto TRAP_LHU; + if(this->core.trap_state>=0x80000000UL) goto TRAP_LHU; uint16_t res = (uint16_t)read_res; if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = (uint32_t)res; @@ -759,7 +759,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); super::template write_mem(traits::MEM, store_address, (int8_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state) goto TRAP_SB; + if(this->core.trap_state>=0x80000000UL) goto TRAP_SB; } TRAP_SB:break; }// @suppress("No break at end of case") @@ -781,7 +781,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); super::template write_mem(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state) goto TRAP_SH; + if(this->core.trap_state>=0x80000000UL) goto TRAP_SH; } TRAP_SH:break; }// @suppress("No break at end of case") @@ -803,7 +803,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); super::template write_mem(traits::MEM, store_address, (int32_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state) goto TRAP_SW; + if(this->core.trap_state>=0x80000000UL) goto TRAP_SW; } TRAP_SW:break; }// @suppress("No break at end of case") @@ -1243,7 +1243,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { super::template write_mem(traits::FENCE, traits::fence, pred << 4 | succ); - if(this->core.trap_state) goto TRAP_FENCE; + if(this->core.trap_state>=0x80000000UL) goto TRAP_FENCE; } TRAP_FENCE:break; }// @suppress("No break at end of case") @@ -1318,15 +1318,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t xrs1 = *(X+rs1 % traits::RFS); if((rd % traits::RFS) != 0) { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRW; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; uint32_t xrd = read_res; super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.trap_state) goto TRAP_CSRRW; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; *(X+rd % traits::RFS) = xrd; } else { super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.trap_state) goto TRAP_CSRRW; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; } } TRAP_CSRRW:break; @@ -1348,12 +1348,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRS; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; uint32_t xrd = read_res; uint32_t xrs1 = *(X+rs1 % traits::RFS); if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd | xrs1); - if(this->core.trap_state) goto TRAP_CSRRS; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; } if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = xrd; @@ -1378,12 +1378,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRC; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; uint32_t xrd = read_res; uint32_t xrs1 = *(X+rs1 % traits::RFS); if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); - if(this->core.trap_state) goto TRAP_CSRRC; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; } if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = xrd; @@ -1408,10 +1408,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRWI; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI; uint32_t xrd = read_res; super::template write_mem(traits::CSR, csr, (uint32_t)zimm); - if(this->core.trap_state) goto TRAP_CSRRWI; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI; if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = xrd; } @@ -1435,11 +1435,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRSI; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI; uint32_t xrd = read_res; if(zimm != 0) { super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); - if(this->core.trap_state) goto TRAP_CSRRSI; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI; } if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = xrd; @@ -1464,11 +1464,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state) goto TRAP_CSRRCI; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI; uint32_t xrd = read_res; if(zimm != 0) { super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); - if(this->core.trap_state) goto TRAP_CSRRCI; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI; } if((rd % traits::RFS) != 0) { *(X+rd % traits::RFS) = xrd; @@ -1492,7 +1492,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { super::template write_mem(traits::FENCE, traits::fencei, imm); - if(this->core.trap_state) goto TRAP_FENCE_I; + if(this->core.trap_state>=0x80000000UL) goto TRAP_FENCE_I; } TRAP_FENCE_I:break; }// @suppress("No break at end of case") @@ -1750,7 +1750,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t load_address = *(X+rs1 + 8) + uimm; int32_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state) goto TRAP_CLW; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CLW; *(X+rd + 8) = (int32_t)read_res; } TRAP_CLW:break; @@ -1773,7 +1773,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t load_address = *(X+rs1 + 8) + uimm; super::template write_mem(traits::MEM, load_address, (int32_t)*(X+rs2 + 8)); - if(this->core.trap_state) goto TRAP_CSW; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSW; } TRAP_CSW:break; }// @suppress("No break at end of case") @@ -2153,7 +2153,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { if(rd % traits::RFS) { int32_t read_res = super::template read_mem(traits::MEM, *(X+2) + uimm); - if(this->core.trap_state) goto TRAP_CLWSP; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CLWSP; int32_t res = read_res; *(X+rd % traits::RFS) = (int32_t)res; } @@ -2293,7 +2293,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t offs = *(X+2) + uimm; super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state) goto TRAP_CSWSP; + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSWSP; } TRAP_CSWSP:break; }// @suppress("No break at end of case") From ad7bb28b4c2c3e7041771f57e6d1995c34965e5e Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 17 Sep 2022 12:14:03 +0200 Subject: [PATCH 038/184] fixes write mask of clic memory mapped registers --- src/iss/arch/riscv_hart_mu_p.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 87ff8b9..55c8f0c 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -487,7 +487,7 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_rd_cb[mclicbase] = &this_class::read_csr_reg; csr_wr_cb[mclicbase] = &this_class::write_null; - clic_int_reg.resize(cfg.clic_num_irq); + clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; mcause_max_irq=cfg.clic_num_irq+16; @@ -1261,6 +1261,7 @@ iss::status riscv_hart_mu_p::write_clic(uint64_t addr, unsigned leng } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl auto offset = ((addr&0x7fff)-0x1000)/4; write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); + clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1 } return iss::Ok; } From 6ba7c82f803c853e6b6956bb329139b52963871b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 26 Sep 2022 13:31:36 +0200 Subject: [PATCH 039/184] fixes wrapper definitions for hwl cores --- src/iss/arch/tgc_mapper.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/iss/arch/tgc_mapper.h b/src/iss/arch/tgc_mapper.h index e79c065..ebacac0 100644 --- a/src/iss/arch/tgc_mapper.h +++ b/src/iss/arch/tgc_mapper.h @@ -16,8 +16,9 @@ using tgc_b_plat_type = iss::arch::riscv_hart_m_p; #endif #ifdef CORE_TGC_C_XRB_NN #include "riscv_hart_m_p.h" +#include "hwl.h" #include -using tgc_c_xrb_nn_plat_type = iss::arch::riscv_hart_m_p; +using tgc_c_xrb_nn_plat_type = iss::arch::hwl>; #endif #ifdef CORE_TGC_D #include "riscv_hart_mu_p.h" @@ -31,8 +32,9 @@ using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p -using tgc_d_xrb_nn_plat_type = iss::arch::riscv_hart_mu_p; +using tgc_d_xrb_nn_plat_type = iss::arch::hwl>; #endif #ifdef CORE_TGC_E #include "riscv_hart_mu_p.h" From b1a18459e76c93e110b78e0bcdd069b8cbd3b834 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 26 Sep 2022 13:57:24 +0200 Subject: [PATCH 040/184] adds more flexible use of availabel targets --- CMakeLists.txt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 775afc0..047c824 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ set(LIB_SOURCES src/vm/fp_functions.cpp ${GEN_SOURCES} ) -if(TARGET RapidJSON) +if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON) list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp src/iss/plugin/pctrace.cpp) endif() @@ -73,7 +73,12 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") endif() target_include_directories(${PROJECT_NAME} PUBLIC src) target_include_directories(${PROJECT_NAME} PUBLIC src-gen) -target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp Boost::coroutine) +target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util Boost::coroutine) +if(TARGET jsoncpp::jsoncpp) + target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp::jsoncpp) +else() + target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp) +endif() if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive) else() @@ -90,7 +95,9 @@ if(TARGET lz4::lz4) target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_LZ4) target_link_libraries(${PROJECT_NAME} PUBLIC lz4::lz4) endif() -if(TARGET RapidJSON) +if(TARGET RapidJSON::RapidJSON) + target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON::RapidJSON) +elseif(TARGET RapidJSON) target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON) endif() From b20daa1ac2d60b2ce61c1b13d16e0dbcacac2682 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 27 Sep 2022 09:11:41 +0200 Subject: [PATCH 041/184] fixes wrong path in install --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 047c824..fd7cceb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,7 +179,7 @@ if(SystemC_FOUND) target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) endif() - set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/incl/sysc/core_complex.h) + set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h) set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} FRAMEWORK FALSE From b20fd3eba5335d75656df3005a9b80a80aa8070a Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 28 Sep 2022 19:37:47 +0200 Subject: [PATCH 042/184] fix static build --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd7cceb..7693201 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ if(TARGET jsoncpp::jsoncpp) else() target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp) endif() -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND BUILD_SHARED_LIBS) target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive) else() target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core) From a977200284440219ad3ead3334c0e7197b143f93 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 5 Oct 2022 08:58:57 +0200 Subject: [PATCH 043/184] cleans up priv wrappers --- src/iss/arch/riscv_hart_m_p.h | 86 ++++++++++++++------------------ src/iss/arch/riscv_hart_msu_vp.h | 12 ----- src/iss/arch/riscv_hart_mu_p.h | 32 +++--------- 3 files changed, 46 insertions(+), 84 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 8365a5d..59b16f9 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -182,7 +182,7 @@ public: return traits::MISA_VAL&0b0100?~1:~3; } - riscv_hart_m_p(); + riscv_hart_m_p(feature_config cfg = feature_config{}); virtual ~riscv_hart_m_p() = default; void reset(uint64_t address) override; @@ -194,9 +194,9 @@ public: iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, const uint8_t *const data) override; - virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); } - virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; - virtual uint64_t leave_trap(uint64_t flags) override; + uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); } + uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; + uint64_t leave_trap(uint64_t flags) override; const reg_t& get_mhartid() const { return mhartid_reg; } void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; @@ -208,14 +208,6 @@ public: iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } - void setMemReadCb(std::function const& memReadCb) { - mem_read_cb = memReadCb; - } - - void setMemWriteCb(std::function const& memWriteCb) { - mem_write_cb = memWriteCb; - } - void set_csr(unsigned addr, reg_t val){ csr[addr & csr.page_addr_mask] = val; } @@ -337,8 +329,6 @@ protected: } reg_t mhartid_reg{0x0}; - std::functionmem_read_cb; - std::function mem_write_cb; void check_interrupt(); bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); @@ -346,23 +336,22 @@ protected: std::vector> memfn_read; std::vector> memfn_write; void insert_mem_range(uint64_t, uint64_t, std::function, std::function); - uint64_t clic_base_addr{0}; - unsigned clic_num_irq{0}; - unsigned clic_num_trigger{0}; + feature_config cfg; unsigned mcause_max_irq{16}; inline bool debug_mode_active() {return this->reg.PRIV&0x4;} }; template -riscv_hart_m_p::riscv_hart_m_p() +riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) : state() -, instr_if(*this) { +, instr_if(*this) +, cfg(cfg) { // reset values csr[misa] = traits::MISA_VAL; csr[mvendorid] = 0x669; csr[marchid] = traits::MARCHID_VAL; csr[mimpid] = 1; - csr[mclicbase] = 0xc0000000; // TODO: should be taken from YAML file + csr[mclicbase] = cfg.clic_base; // TODO: should be taken from YAML file uart_buf.str(""); for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ @@ -385,7 +374,10 @@ riscv_hart_m_p::riscv_hart_m_p() //csr_wr_cb[addr] = &this_class::write_csr_reg; } // common regs - const std::array addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause, mtval, mscratch}}; + const std::array addrs{{ + misa, mvendorid, marchid, mimpid, + mepc, mtvec, mscratch, mcause, mtval + }}; for(auto addr: addrs) { csr_rd_cb[addr] = &this_class::read_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg; @@ -416,6 +408,8 @@ riscv_hart_m_p::riscv_hart_m_p() csr_rd_cb[mie] = &this_class::read_ie; csr_wr_cb[mie] = &this_class::write_ie; csr_rd_cb[mhartid] = &this_class::read_hartid; + csr_rd_cb[mcounteren] = &this_class::read_null; + csr_wr_cb[mcounteren] = &this_class::write_null; csr_wr_cb[misa] = &this_class::write_null; csr_wr_cb[mvendorid] = &this_class::write_null; csr_wr_cb[marchid] = &this_class::write_null; @@ -436,29 +430,27 @@ riscv_hart_m_p::riscv_hart_m_p() csr_rd_cb[mclicbase] = &this_class::read_csr_reg; csr_wr_cb[mclicbase] = &this_class::write_null; - clic_base_addr=0xC0000000; - clic_num_irq=16; - clic_int_reg.resize(clic_num_irq); + clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; - clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + clic_num_irq; - mcause_max_irq=clic_num_irq+16; - insert_mem_range(clic_base_addr, 0x5000UL, + clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; + mcause_max_irq=cfg.clic_num_irq+16; + insert_mem_range(cfg.clic_base, 0x5000UL, [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); } if(FEAT & FEAT_TCM) { - tcm.resize(0x8000); + tcm.resize(cfg.tcm_size); std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) { - auto offset=addr.val-0x10000000; + auto offset=addr.val-this->cfg.tcm_base; std::copy(tcm.data() + offset, tcm.data() + offset + length, data); return iss::Ok; }; std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const * const data) { - auto offset=addr.val-0x10000000; + auto offset=addr.val-this->cfg.tcm_base; std::copy(data, data + length, tcm.data() + offset); return iss::Ok; }; - insert_mem_range(0x10000000, 0x8000UL, read_clic_cb, write_clic_cb); + insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb); } if(FEAT & FEAT_DEBUG){ csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; @@ -582,7 +574,7 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce } auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); auto res = iss::Err; - if(!is_fetch(access) && memfn_range.size()){ + if(access != access_type::FETCH && memfn_range.size()){ auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; }); @@ -863,7 +855,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t &val) { - val = csr[mtvec] & ~2; + val = csr[addr] & ~2; return iss::Ok; } @@ -879,7 +871,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { - csr[mcause] = val & ((1UL<<(traits::XLEN-1))| (mcause_max_irq-1)); + csr[addr] = val & ((1UL<<(traits::XLEN-1))| (mcause_max_irq-1)); return iss::Ok; } @@ -959,7 +951,6 @@ iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val template iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - if(mem_read_cb) return mem_read_cb(paddr, length, data); switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg if (sizeof(reg_t) < length) return iss::Err; @@ -984,14 +975,12 @@ iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned len template iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - if(mem_write_cb) return mem_write_cb(paddr, length, data); switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg uart_buf << (char)data[0]; if (((char)data[0]) == '\n' || data[0] == 0) { - // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send - // '"<>16)&0x3)<<" send '"<::write_mem(phys_addr_t paddr, unsigned le template iss::status riscv_hart_m_p::read_clic(uint64_t addr, unsigned length, uint8_t *const data) { - if(addr==clic_base_addr) { // cliccfg + if(addr==cfg.clic_base) { // cliccfg *data=clic_cfg_reg; for(auto i=1; i=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+8)){ // clicinfo + } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+8)){ // clicinfo read_reg_uint32(addr, clic_info_reg, data, length); - } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0x40+clic_num_trigger*4)){ // clicinttrig + } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig auto offset = ((addr&0x7fff)-0x40)/4; read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl + } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl auto offset = ((addr&0x7fff)-0x1000)/4; read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); } else { @@ -1081,17 +1070,18 @@ iss::status riscv_hart_m_p::read_clic(uint64_t addr, unsigned length template iss::status riscv_hart_m_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { - if(addr==clic_base_addr) { // cliccfg + if(addr==cfg.clic_base) { // cliccfg clic_cfg_reg = *data; clic_cfg_reg&= 0x7e; -// } else if(addr>=(clic_base_addr+4) && (addr+length)<=(clic_base_addr+4)){ // clicinfo +// } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+4)){ // clicinfo // write_uint32(addr, clic_info_reg, data, length); - } else if(addr>=(clic_base_addr+0x40) && (addr+length)<=(clic_base_addr+0xC0)){ // clicinttrig + } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig auto offset = ((addr&0x7fff)-0x40)/4; write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(clic_base_addr+0x1000) && (addr+length)<=(clic_base_addr+clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl + } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl auto offset = ((addr&0x7fff)-0x1000)/4; write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); + clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1 } return iss::Ok; } @@ -1109,8 +1099,8 @@ template void riscv_hart_m_p::check // any synchronous traps. auto ena_irq = csr[mip] & csr[mie]; - bool mie = state.mstatus.MIE; - auto m_enabled = this->reg.PRIV < PRIV_M || (this->reg.PRIV == PRIV_M && mie); + bool mstatus_mie = state.mstatus.MIE; + auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie; auto enabled_interrupts = m_enabled ? ena_irq : 0; if (enabled_interrupts != 0) { diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index a742d08..54e93fd 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -312,14 +312,6 @@ public: iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } - void setMemReadCb(std::function const& memReadCb) { - mem_read_cb = memReadCb; - } - - void setMemWriteCb(std::function const& memWriteCb) { - mem_write_cb = memWriteCb; - } - void set_csr(unsigned addr, reg_t val){ csr[addr & csr.page_addr_mask] = val; } @@ -422,8 +414,6 @@ private: } reg_t mhartid_reg{0x0}; - std::functionmem_read_cb; - std::function mem_write_cb; protected: void check_interrupt(); @@ -1031,7 +1021,6 @@ template iss::status riscv_hart_msu_vp::write_fcsr(unsigne template iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - if(mem_read_cb) return mem_read_cb(paddr, length, data); switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg if (sizeof(reg_t) < length) return iss::Err; @@ -1056,7 +1045,6 @@ iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length template iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - if(mem_write_cb) return mem_write_cb(paddr, length, data); switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 55c8f0c..eb05618 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -223,14 +223,6 @@ public: iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } - void setMemReadCb(std::function const& memReadCb) { - mem_read_cb = memReadCb; - } - - void setMemWriteCb(std::function const& memWriteCb) { - mem_write_cb = memWriteCb; - } - void set_csr(unsigned addr, reg_t val){ csr[addr & csr.page_addr_mask] = val; } @@ -250,26 +242,24 @@ protected: */ const std::string core_type_name() const override { return traits::core_type; } - virtual uint64_t get_pc() { return arch.get_pc(); }; + uint64_t get_pc() override { return arch.reg.PC; }; - virtual uint64_t get_next_pc() { return arch.get_next_pc(); }; + uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; uint64_t get_instr_word() override { return arch.instruction; } - uint64_t get_instr_count() { return arch.icount; } + uint64_t get_instr_count() override { return arch.icount; } uint64_t get_pendig_traps() override { return arch.trap_state; } uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } - virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; + void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; riscv_hart_mu_p &arch; }; friend struct riscv_instrumentation_if; - addr_t get_pc() { return this->reg.PC; } - addr_t get_next_pc() { return this->reg.NEXT_PC; } 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); @@ -357,8 +347,6 @@ protected: } reg_t mhartid_reg{0x0}; - std::functionmem_read_cb; - std::function mem_write_cb; void check_interrupt(); bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); @@ -1020,14 +1008,12 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_status(unsigned addr, reg_t &val) { - auto req_priv_lvl = (addr >> 8) & 0x3; - val = state.mstatus & hart_state_type::get_mask(req_priv_lvl); + val = state.mstatus & hart_state_type::get_mask((addr >> 8) & 0x3); return iss::Ok; } template iss::status riscv_hart_mu_p::write_status(unsigned addr, reg_t val) { - auto req_priv_lvl = (addr >> 8) & 0x3; - state.write_mstatus(val, req_priv_lvl); + state.write_mstatus(val, (addr >> 8) & 0x3); check_interrupt(); return iss::Ok; } @@ -1129,7 +1115,6 @@ iss::status riscv_hart_mu_p::write_intthresh(unsigned addr, reg_t va template iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - if(mem_read_cb) return mem_read_cb(paddr, length, data); switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg if (sizeof(reg_t) < length) return iss::Err; @@ -1154,7 +1139,6 @@ iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned le template iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - if(mem_write_cb) return mem_write_cb(paddr, length, data); switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg @@ -1279,8 +1263,8 @@ template void riscv_hart_mu_p::chec // any synchronous traps. auto ena_irq = csr[mip] & csr[mie]; - bool mie = state.mstatus.MIE; - auto m_enabled = this->reg.PRIV < PRIV_M || mie; + bool mstatus_mie = state.mstatus.MIE; + auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie; auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0; if (enabled_interrupts != 0) { From 40d1966e9a8e28076127389a36be6e848a1b0b09 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 8 Oct 2022 11:20:52 +0200 Subject: [PATCH 044/184] fixes pending irq within irq hander behavior --- src/iss/arch/riscv_hart_m_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 59b16f9..a729115 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -1200,6 +1200,7 @@ template uint64_t riscv_hart_m_p::l this->reg.NEXT_PC = csr[mepc] & get_pc_mask(); CLOG(INFO, disass) << "Executing xRET"; check_interrupt(); + this->trap_state = this->pending_trap; return this->reg.NEXT_PC; } From 1a0fc4bd5d544dc6809979ab4829daefc321d2e2 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 10 Oct 2022 08:59:27 +0200 Subject: [PATCH 045/184] fixes wrong mcounteren in M-mode only priv wrapper --- src/iss/arch/riscv_hart_m_p.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index a729115..46078a1 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -408,8 +408,6 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr_rd_cb[mie] = &this_class::read_ie; csr_wr_cb[mie] = &this_class::write_ie; csr_rd_cb[mhartid] = &this_class::read_hartid; - csr_rd_cb[mcounteren] = &this_class::read_null; - csr_wr_cb[mcounteren] = &this_class::write_null; csr_wr_cb[misa] = &this_class::write_null; csr_wr_cb[mvendorid] = &this_class::write_null; csr_wr_cb[marchid] = &this_class::write_null; From 7113683ee0fc96dc99a252f6aed63df7dd73ddf1 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 15 Oct 2022 10:47:35 +0200 Subject: [PATCH 046/184] moves pending interrupt check before handling trap thus saving 1 cycle --- gen_input/templates/interp/CORENAME.cpp.gtl | 3 ++- src/vm/interp/vm_tgc_c.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 930a818..3b62ca7 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -289,6 +289,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // post execution stuff process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); + if(!this->core.trap_state) // update trap state if there is a pending interrupt + this->core.trap_state = this->core.pending_trap; // trap check if(trap_state!=0){ super::core.enter_trap(trap_state, pc.val, instr); @@ -299,7 +301,6 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co cycle++; pc.val=*NEXT_PC; this->core.reg.PC = this->core.reg.NEXT_PC; - this->core.trap_state = this->core.pending_trap; } } return pc; diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index a71d8c5..6a0f8cb 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -2318,6 +2318,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // post execution stuff process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); + if(!this->core.trap_state) // update trap state if there is a pending interrupt + this->core.trap_state = this->core.pending_trap; // trap check if(trap_state!=0){ super::core.enter_trap(trap_state, pc.val, instr); @@ -2328,7 +2330,6 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co cycle++; pc.val=*NEXT_PC; this->core.reg.PC = this->core.reg.NEXT_PC; - this->core.trap_state = this->core.pending_trap; } } return pc; From f585489ff5af76d8e5cac139285dc57af8c95e64 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 26 Oct 2022 17:21:44 +0200 Subject: [PATCH 047/184] fixes pin naming --- src/sysc/core_complex.cpp | 29 ++++++++++++++++++++--------- src/sysc/core_complex.h | 5 +++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index e3730f2..c3776cf 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -186,17 +186,17 @@ public: void local_irq(short id, bool value) { reg_t mask = 0; switch (id) { - case 16: // SW + case 3: // SW mask = 1 << 3; break; - case 17: // timer + case 7: // timer mask = 1 << 7; break; - case 18: // external + case 11: // external mask = 1 << 11; break; default: - /* do nothing*/ + if(id>15) mask = 1 << id; break; } if (value) { @@ -357,8 +357,11 @@ void core_complex::init(){ sensitive << sw_irq_i; SC_METHOD(timer_irq_cb); sensitive << timer_irq_i; - SC_METHOD(global_irq_cb); - sensitive << global_irq_i; + SC_METHOD(ext_irq_cb); + sensitive << ext_irq_i; + SC_METHOD(local_irq_cb); + for(auto pin:local_irq_i) + sensitive << pin; trc->m_db=scv_tr_db::get_default_db(); SC_METHOD(forward); @@ -480,11 +483,19 @@ void core_complex::rst_cb() { if (rst_i.read()) cpu->set_interrupt_execution(true); } -void core_complex::sw_irq_cb() { cpu->local_irq(16, sw_irq_i.read()); } +void core_complex::sw_irq_cb() { cpu->local_irq(3, sw_irq_i.read()); } -void core_complex::timer_irq_cb() { cpu->local_irq(17, timer_irq_i.read()); } +void core_complex::timer_irq_cb() { cpu->local_irq(7, timer_irq_i.read()); } -void core_complex::global_irq_cb() { cpu->local_irq(18, global_irq_i.read()); } +void core_complex::ext_irq_cb() { cpu->local_irq(11, ext_irq_i.read()); } + +void core_complex::local_irq_cb() { + for(auto i=0U; ilocal_irq(16+i, local_irq_i[i].read()); + } + } +} void core_complex::run() { wait(SC_ZERO_TIME); // separate from elaboration phase diff --git a/src/sysc/core_complex.h b/src/sysc/core_complex.h index f764a8a..f7d8d73 100644 --- a/src/sysc/core_complex.h +++ b/src/sysc/core_complex.h @@ -73,7 +73,7 @@ public: sc_core::sc_in rst_i{"rst_i"}; - sc_core::sc_in global_irq_i{"global_irq_i"}; + sc_core::sc_in ext_irq_i{"ext_irq_i"}; sc_core::sc_in timer_irq_i{"timer_irq_i"}; @@ -181,7 +181,8 @@ protected: void rst_cb(); void sw_irq_cb(); void timer_irq_cb(); - void global_irq_cb(); + void ext_irq_cb(); + void local_irq_cb(); uint64_t last_sync_cycle = 0; util::range_lut read_lut, write_lut; tlm_utils::tlm_quantumkeeper quantum_keeper; From 8c701d55c1afe10cfa9d82bb215487b8ab9d0a28 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 5 Dec 2022 09:15:48 +0100 Subject: [PATCH 048/184] adapt to latest changes in SCC --- CMakeLists.txt | 1 + src/vm/interp/vm_tgc_c.cpp | 712 ++++++++++++++++++++++++------------- 2 files changed, 467 insertions(+), 246 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7693201..c0a92a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ include(GNUInstallDirs) find_package(elfio QUIET) find_package(Boost COMPONENTS coroutine) +find_package(jsoncpp) if(WITH_LLVM) if(DEFINED ENV{LLVM_HOME}) diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 6a0f8cb..826c770 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -358,8 +358,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)imm; + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (int32_t)imm; + } } } TRAP_LUI:break; @@ -379,8 +384,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *PC + (int32_t)imm; + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *PC + (int32_t)imm; + } } } TRAP_AUIPC:break; @@ -400,17 +410,22 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *PC + 4; - } - *NEXT_PC = *PC + (int32_t)sext<21>(imm); - super::ex_info.branch_taken=true; - } - } + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if(rd != 0) { + *(X+rd) = *PC + 4; + } + *NEXT_PC = *PC + (int32_t)sext<21>(imm); + super::ex_info.branch_taken=true; + } + } + } TRAP_JAL:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::JALR: { @@ -429,18 +444,23 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 0x1; - if(new_pc % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *PC + 4; - } - *NEXT_PC = new_pc & ~ 0x1; - super::ex_info.branch_taken=true; - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 0x1; + if(new_pc % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if(rd != 0) { + *(X+rd) = *PC + 4; + } + *NEXT_PC = new_pc & ~ 0x1; + super::ex_info.branch_taken=true; + } + } + } TRAP_JALR:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BEQ: { @@ -459,16 +479,21 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } - } - } + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + } TRAP_BEQ:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BNE: { @@ -487,16 +512,21 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } - } - } + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + } TRAP_BNE:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BLT: { @@ -515,16 +545,21 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } - } - } + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + } TRAP_BLT:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BGE: { @@ -543,16 +578,21 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } - } - } + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + } TRAP_BGE:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BLTU: { @@ -571,16 +611,21 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } - } - } + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + } TRAP_BLTU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::BGEU: { @@ -599,16 +644,21 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; - } - } - } + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = *PC + (int16_t)sext<13>(imm); + super::ex_info.branch_taken=true; + } + } + } + } TRAP_BGEU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::LB: { @@ -627,14 +677,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - int8_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state>=0x80000000UL) goto TRAP_LB; - int8_t res = (int8_t)read_res; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)res; - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + int8_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state>=0x80000000UL) goto TRAP_LB; + int8_t res = (int8_t)read_res; + if(rd != 0) { + *(X+rd) = (int32_t)res; + } + } + } TRAP_LB:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::LH: { @@ -653,14 +708,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - int16_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state>=0x80000000UL) goto TRAP_LH; - int16_t res = (int16_t)read_res; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)res; - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + int16_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state>=0x80000000UL) goto TRAP_LH; + int16_t res = (int16_t)read_res; + if(rd != 0) { + *(X+rd) = (int32_t)res; + } + } + } TRAP_LH:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::LW: { @@ -679,14 +739,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - int32_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state>=0x80000000UL) goto TRAP_LW; - int32_t res = (int32_t)read_res; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)res; - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + int32_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state>=0x80000000UL) goto TRAP_LW; + int32_t res = (int32_t)read_res; + if(rd != 0) { + *(X+rd) = (int32_t)res; + } + } + } TRAP_LW:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::LBU: { @@ -705,14 +770,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - uint8_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state>=0x80000000UL) goto TRAP_LBU; - uint8_t res = (uint8_t)read_res; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (uint32_t)res; - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint8_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state>=0x80000000UL) goto TRAP_LBU; + uint8_t res = (uint8_t)read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } TRAP_LBU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::LHU: { @@ -731,14 +801,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - uint16_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state>=0x80000000UL) goto TRAP_LHU; - uint16_t res = (uint16_t)read_res; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (uint32_t)res; - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint16_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.trap_state>=0x80000000UL) goto TRAP_LHU; + uint16_t res = (uint16_t)read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } TRAP_LHU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SB: { @@ -757,10 +832,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, (int8_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state>=0x80000000UL) goto TRAP_SB; - } + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + super::template write_mem(traits::MEM, store_address, (int8_t)*(X+rs2 % traits::RFS)); + if(this->core.trap_state>=0x80000000UL) goto TRAP_SB; + } + } TRAP_SB:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SH: { @@ -779,10 +859,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state>=0x80000000UL) goto TRAP_SH; - } + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + super::template write_mem(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); + if(this->core.trap_state>=0x80000000UL) goto TRAP_SH; + } + } TRAP_SH:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::SW: { @@ -801,10 +886,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, (int32_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state>=0x80000000UL) goto TRAP_SW; - } + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + super::template write_mem(traits::MEM, store_address, (int32_t)*(X+rs2 % traits::RFS)); + if(this->core.trap_state>=0x80000000UL) goto TRAP_SW; + } + } TRAP_SW:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::ADDI: { @@ -823,8 +913,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + } } } TRAP_ADDI:break; @@ -845,8 +940,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = ((int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm))? 1 : 0; + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = ((int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm))? 1 : 0; + } } } TRAP_SLTI:break; @@ -867,8 +967,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; + } } } TRAP_SLTIU:break; @@ -889,8 +994,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm); + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm); + } } } TRAP_XORI:break; @@ -911,8 +1021,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm); + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm); + } } } TRAP_ORI:break; @@ -933,8 +1048,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm); + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm); + } } } TRAP_ANDI:break; @@ -955,8 +1075,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << shamt; + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) << shamt; + } } } TRAP_SLLI:break; @@ -977,8 +1102,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> shamt; + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) >> shamt; + } } } TRAP_SRLI:break; @@ -999,8 +1129,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; + } } } TRAP_SRAI:break; @@ -1021,8 +1156,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS); + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS); + } } } TRAP_ADD:break; @@ -1043,8 +1183,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS); + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS); + } } } TRAP_SUB:break; @@ -1065,8 +1210,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } } } TRAP_SLL:break; @@ -1087,8 +1237,18 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0; + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0; + } + } } } TRAP_SLT:break; @@ -1109,8 +1269,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0; + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0; + } } } TRAP_SLTU:break; @@ -1131,8 +1296,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS); + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS); + } } } TRAP_XOR:break; @@ -1153,8 +1323,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } } } TRAP_SRL:break; @@ -1175,8 +1350,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + } } } TRAP_SRA:break; @@ -1197,8 +1377,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS); + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS); + } } } TRAP_OR:break; @@ -1219,8 +1404,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS); + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS); + } } } TRAP_AND:break; @@ -1315,20 +1505,25 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t xrs1 = *(X+rs1 % traits::RFS); - if((rd % traits::RFS) != 0) { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; - uint32_t xrd = read_res; - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; - *(X+rd % traits::RFS) = xrd; - } - else { - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t xrs1 = *(X+rs1 % traits::RFS); + if(rd != 0) { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; + uint32_t xrd = read_res; + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; + *(X+rd) = xrd; + } + else { + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; + } + } + } TRAP_CSRRW:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRS: { @@ -1347,18 +1542,23 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; - uint32_t xrd = read_res; - uint32_t xrs1 = *(X+rs1 % traits::RFS); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd | xrs1); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; - } - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = xrd; - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; + uint32_t xrd = read_res; + uint32_t xrs1 = *(X+rs1 % traits::RFS); + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd | xrs1); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } TRAP_CSRRS:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRC: { @@ -1377,18 +1577,23 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; - uint32_t xrd = read_res; - uint32_t xrs1 = *(X+rs1 % traits::RFS); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; - } - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = xrd; - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; + uint32_t xrd = read_res; + uint32_t xrs1 = *(X+rs1 % traits::RFS); + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } TRAP_CSRRC:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRWI: { @@ -1407,15 +1612,20 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI; - uint32_t xrd = read_res; - super::template write_mem(traits::CSR, csr, (uint32_t)zimm); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI; - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = xrd; - } - } + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI; + uint32_t xrd = read_res; + super::template write_mem(traits::CSR, csr, (uint32_t)zimm); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI; + if(rd != 0) { + *(X+rd) = xrd; + } + } + } TRAP_CSRRWI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRSI: { @@ -1434,17 +1644,22 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI; - uint32_t xrd = read_res; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI; - } - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = xrd; - } - } + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI; + uint32_t xrd = read_res; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI; + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } TRAP_CSRRSI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CSRRCI: { @@ -1463,17 +1678,22 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI; - uint32_t xrd = read_res; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI; - } - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = xrd; - } - } + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI; + uint32_t xrd = read_res; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI; + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } TRAP_CSRRCI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::FENCE_I: { From 3187cbdfe2c728c89b4d65d03347cd6e3273315a Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 12 Dec 2022 02:55:44 +0100 Subject: [PATCH 049/184] removes CONAN_PKG from build system --- CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c0a92a6..3e59c6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,9 +85,7 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND BUILD_SHARED_LIBS) else() target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core) endif() -if(TARGET CONAN_PKG::elfio) - target_link_libraries(${PROJECT_NAME} PUBLIC CONAN_PKG::elfio) -elseif(TARGET elfio::elfio) +if(TARGET elfio::elfio) target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio) else() message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing") From 65dca13b42853ec79cce9d66c91cd51267774175 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 14 Jan 2023 17:40:21 +0100 Subject: [PATCH 050/184] fixes WFI miss of interrupt --- gen_input/templates/interp/CORENAME.cpp.gtl | 5 +++-- src/vm/interp/vm_tgc_c.cpp | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 3b62ca7..4b84520 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -289,8 +289,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // post execution stuff process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); - if(!this->core.trap_state) // update trap state if there is a pending interrupt - this->core.trap_state = this->core.pending_trap; + // if(!this->core.trap_state) // update trap state if there is a pending interrupt + // this->core.trap_state = this->core.pending_trap; // trap check if(trap_state!=0){ super::core.enter_trap(trap_state, pc.val, instr); @@ -301,6 +301,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co cycle++; pc.val=*NEXT_PC; this->core.reg.PC = this->core.reg.NEXT_PC; + this->core.trap_state = this->core.pending_trap; } } return pc; diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 826c770..9ef0760 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -2538,8 +2538,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // post execution stuff process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); - if(!this->core.trap_state) // update trap state if there is a pending interrupt - this->core.trap_state = this->core.pending_trap; + // if(!this->core.trap_state) // update trap state if there is a pending interrupt + // this->core.trap_state = this->core.pending_trap; // trap check if(trap_state!=0){ super::core.enter_trap(trap_state, pc.val, instr); @@ -2550,6 +2550,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co cycle++; pc.val=*NEXT_PC; this->core.reg.PC = this->core.reg.NEXT_PC; + this->core.trap_state = this->core.pending_trap; } } return pc; From 62c118e5016a998b960977124f12e87d3e65ecba Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 20 Jan 2023 16:21:04 +0100 Subject: [PATCH 051/184] fixes CSR to match latest fast interrupts spec --- src/iss/arch/riscv_hart_common.h | 3 +-- src/iss/arch/riscv_hart_m_p.h | 3 --- src/iss/arch/riscv_hart_mu_p.h | 3 --- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index 345fbeb..3e8eb83 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -115,10 +115,9 @@ enum riscv_csr { mip = 0x344, mxnti = 0x345, //CLIC mintstatus = 0x346, // MRW Current interrupt levels (CLIC) - addr subject to change + mintthresh = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC) mscratchcswl = 0x349, // MRW Conditional scratch swap on level change (CLIC) - mintthresh = 0x350, // MRW Interrupt-level threshold (CLIC) - addr subject to change - mclicbase = 0x351, // MRW Base address for CLIC memory mapped registers (CLIC) - addr subject to change // Physical Memory Protection pmpcfg0 = 0x3A0, pmpcfg1 = 0x3A1, diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 46078a1..101b096 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -351,7 +351,6 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr[mvendorid] = 0x669; csr[marchid] = traits::MARCHID_VAL; csr[mimpid] = 1; - csr[mclicbase] = cfg.clic_base; // TODO: should be taken from YAML file uart_buf.str(""); for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ @@ -425,8 +424,6 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_wr_cb[mintthresh] = &this_class::write_intthresh; - csr_rd_cb[mclicbase] = &this_class::read_csr_reg; - csr_wr_cb[mclicbase] = &this_class::write_null; clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index eb05618..45b932b 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -369,7 +369,6 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr[mvendorid] = 0x669; csr[marchid] = traits::MARCHID_VAL; csr[mimpid] = 1; - csr[mclicbase] = cfg.clic_base; // TODO: should be taken from YAML file uart_buf.str(""); for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ @@ -472,8 +471,6 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_wr_cb[mintthresh] = &this_class::write_intthresh; - csr_rd_cb[mclicbase] = &this_class::read_csr_reg; - csr_wr_cb[mclicbase] = &this_class::write_null; clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; From 207dbf1071702952c701009f86a97f5c4cf3aae6 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 17 Feb 2023 06:28:30 +0100 Subject: [PATCH 052/184] fixes out of range access for register alias names --- gen_input/templates/interp/CORENAME.cpp.gtl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 4b84520..ebedab0 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -92,7 +92,7 @@ protected: using compile_ret_t = virt_addr_t; using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); - inline const char *name(size_t index){return traits::reg_aliases.at(index);} + inline const char *name(size_t index){return index::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; From 8c3709f92ae9ee6878f62b889e1acaf6be19dd2f Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 17 Feb 2023 06:29:27 +0100 Subject: [PATCH 053/184] adds generator changed files --- src/vm/interp/vm_tgc_c.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 9ef0760..196d106 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -86,7 +86,7 @@ protected: using compile_ret_t = virt_addr_t; using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); - inline const char *name(size_t index){return traits::reg_aliases.at(index);} + inline const char *name(size_t index){return index::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; From ec55efd3229b201dde1778d5b7f6e68876d2c99f Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 17 Feb 2023 06:36:34 +0100 Subject: [PATCH 054/184] adds generator changed files --- src/vm/interp/vm_tgc_c.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 196d106..8319ffa 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -86,7 +86,7 @@ protected: using compile_ret_t = virt_addr_t; using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); - inline const char *name(size_t index){return index::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; From a83928fd8ce9fc4c5793e7fa967f5285b8e7399f Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 10 Mar 2023 20:40:21 +0100 Subject: [PATCH 055/184] fixes CSR/CLIC implementation --- src/iss/arch/riscv_hart_common.h | 2 +- src/iss/arch/riscv_hart_m_p.h | 33 +++++++++++++++++++------------- src/iss/arch/riscv_hart_mu_p.h | 30 ++++++++++++++++++++--------- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index 3e8eb83..704fc2f 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -114,7 +114,7 @@ enum riscv_csr { mtval = 0x343, mip = 0x344, mxnti = 0x345, //CLIC - mintstatus = 0x346, // MRW Current interrupt levels (CLIC) - addr subject to change + mintstatus = 0xFB1, // MRW Current interrupt levels (CLIC) - addr subject to change mintthresh = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC) mscratchcswl = 0x349, // MRW Conditional scratch swap on level change (CLIC) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 101b096..5b0c92a 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -212,9 +212,9 @@ public: csr[addr & csr.page_addr_mask] = val; } - void set_irq_num(unsigned i) { - mcause_max_irq=1<> memfn_write; void insert_mem_range(uint64_t, uint64_t, std::function, std::function); feature_config cfg; - unsigned mcause_max_irq{16}; + unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; inline bool debug_mode_active() {return this->reg.PRIV&0x4;} }; @@ -428,7 +428,6 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; - mcause_max_irq=cfg.clic_num_irq+16; insert_mem_range(cfg.clic_base, 0x5000UL, [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); @@ -850,7 +849,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t &val) { - val = csr[addr] & ~2; + val = FEAT & features_e::FEAT_CLIC? csr[addr] : csr[addr] & ~2; return iss::Ok; } @@ -866,7 +865,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { - csr[addr] = val & ((1UL<<(traits::XLEN-1))| (mcause_max_irq-1)); + csr[addr] = val & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); return iss::Ok; } @@ -1111,7 +1110,7 @@ template void riscv_hart_m_p::check template uint64_t riscv_hart_m_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val - auto trap_id = bit_sub<0, 16>(flags); + auto const trap_id = bit_sub<0, 16>(flags); auto cause = bit_sub<16, 15>(flags); // calculate effective privilege level unsigned new_priv = PRIV_M; @@ -1167,11 +1166,19 @@ template uint64_t riscv_hart_m_p::e state.mstatus.MIE = false; // get trap vector - auto ivec = csr[mtvec]; - // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE - // bits in mtvec - this->reg.NEXT_PC = ivec & ~0x3UL; - if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; + auto xtvec = csr[mtvec]; + // calculate adds// set NEXT_PC to trap addressess to jump to based on MODE + if((FEAT & features_e::FEAT_CLIC) && trap_id!=0 && (xtvec & 0x3UL)==3UL) { + reg_t data; + auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast(&data)); + if(ret == iss::Err) + return this->reg.PC; + this->reg.NEXT_PC = data; + } else { + // bits in mtvec + this->reg.NEXT_PC = xtvec & ~0x3UL; + if ((xtvec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; + } // reset trap state this->reg.PRIV = new_priv; this->trap_state = 0; diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 45b932b..7cf099f 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -227,9 +227,9 @@ public: csr[addr & csr.page_addr_mask] = val; } - void set_irq_num(unsigned i) { - mcause_max_irq=1<> memfn_write; void insert_mem_range(uint64_t, uint64_t, std::function, std::function); feature_config cfg; - unsigned mcause_max_irq{16}; + unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; inline bool debug_mode_active() {return this->reg.PRIV&0x4;} }; @@ -475,7 +475,6 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; - mcause_max_irq=cfg.clic_num_irq+16; insert_mem_range(cfg.clic_base, 0x5000UL, [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); @@ -1001,7 +1000,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_tvec(unsigned addr, reg_t &val) { - val = csr[addr] & ~2; + val = FEAT & features_e::FEAT_CLIC? csr[addr] : csr[addr] & ~2; return iss::Ok; } template iss::status riscv_hart_mu_p::read_status(unsigned addr, reg_t &val) { @@ -1350,13 +1349,26 @@ template uint64_t riscv_hart_mu_p:: } // get trap vector - auto ivec = csr[utvec | (new_priv << 8)]; + auto xtvec = csr[utvec | (new_priv << 8)]; // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE // bits in mtvec - this->reg.NEXT_PC = ivec & ~0x3UL; - if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; + if((FEAT & features_e::FEAT_CLIC) && trap_id!=0 && (xtvec & 0x3UL)==3UL) { + reg_t data; + auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast(&data)); + if(ret == iss::Err) + return this->reg.PC; + this->reg.NEXT_PC = data; + } else { + this->reg.NEXT_PC = xtvec & ~0x3UL; + if ((xtvec & 0x1) == 1 && trap_id != 0) + this->reg.NEXT_PC += 4 * cause; + } std::array buffer; +#if defined(_MSC_VER) + sprintf(buffer.data(), "0x%016llx", addr); +#else sprintf(buffer.data(), "0x%016lx", addr); +#endif if((flags&0xffffffff) != 0xffffffff) CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" From 83f54b5074c2c311ccf69881e5a0bf15613102f1 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 11 Mar 2023 08:48:03 +0100 Subject: [PATCH 056/184] fixes CLICCFG settings --- src/iss/arch/riscv_hart_m_p.h | 3 +-- src/iss/arch/riscv_hart_mu_p.h | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 5b0c92a..6abd9d0 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -1065,8 +1065,7 @@ iss::status riscv_hart_m_p::read_clic(uint64_t addr, unsigned length template iss::status riscv_hart_m_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { if(addr==cfg.clic_base) { // cliccfg - clic_cfg_reg = *data; - clic_cfg_reg&= 0x7e; + clic_cfg_reg = (clic_cfg_reg&~0x1e) | (*data&0x1e); // } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+4)){ // clicinfo // write_uint32(addr, clic_info_reg, data, length); } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 7cf099f..2a6c29e 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -473,7 +473,7 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_wr_cb[mintthresh] = &this_class::write_intthresh; clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); - clic_cfg_reg=0x20; + clic_cfg_reg=0x30; clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; insert_mem_range(cfg.clic_base, 0x5000UL, [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, @@ -1231,8 +1231,7 @@ iss::status riscv_hart_mu_p::read_clic(uint64_t addr, unsigned lengt template iss::status riscv_hart_mu_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { if(addr==cfg.clic_base) { // cliccfg - clic_cfg_reg = *data; - clic_cfg_reg&= 0x7e; + clic_cfg_reg = (clic_cfg_reg&~0x1e) | (*data&0x1e); // } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+4)){ // clicinfo // write_uint32(addr, clic_info_reg, data, length); } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig From ad1cbedf008d589bc9a37eb1bced5e0457e009c2 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 11 Mar 2023 12:47:10 +0100 Subject: [PATCH 057/184] adds back missing max irq functions --- src/iss/arch/riscv_hart_m_p.h | 6 +++--- src/iss/arch/riscv_hart_mu_p.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 6abd9d0..b8f63ca 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -212,9 +212,9 @@ public: csr[addr & csr.page_addr_mask] = val; } -// void set_irq_num(unsigned i) { -// mcause_max_irq=1< Date: Sat, 11 Mar 2023 14:03:03 +0100 Subject: [PATCH 058/184] fixes CLIC mtvt register behavior --- src/iss/arch/riscv_hart_m_p.h | 9 ++++++++- src/iss/arch/riscv_hart_mu_p.h | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index b8f63ca..c57263c 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -312,6 +312,7 @@ protected: iss::status write_epc(unsigned addr, reg_t val); iss::status write_intstatus(unsigned addr, reg_t val); iss::status write_intthresh(unsigned addr, reg_t val); + iss::status write_xtvt(unsigned addr, reg_t val); iss::status write_dcsr_dcsr(unsigned addr, reg_t val); iss::status read_dcsr_reg(unsigned addr, reg_t &val); iss::status write_dcsr_reg(unsigned addr, reg_t val); @@ -413,7 +414,7 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr_wr_cb[mimpid] = &this_class::write_null; if(FEAT & FEAT_CLIC) { csr_rd_cb[mtvt] = &this_class::read_csr_reg; - csr_wr_cb[mtvt] = &this_class::write_csr_reg; + csr_wr_cb[mtvt] = &this_class::write_xtvt; csr_rd_cb[mxnti] = &this_class::read_csr_reg; csr_wr_cb[mxnti] = &this_class::write_csr_reg; csr_rd_cb[mintstatus] = &this_class::read_csr_reg; @@ -943,6 +944,12 @@ iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val return iss::Ok; } +template +iss::status riscv_hart_mu_p::write_xtvt(unsigned addr, reg_t val) { + csr[addr]= val & ~0x3fULL; + return iss::Ok; +} + template iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { switch (paddr.val) { diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 7ed92ea..d4032c3 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -329,6 +329,7 @@ protected: iss::status write_epc(unsigned addr, reg_t val); iss::status write_intstatus(unsigned addr, reg_t val); iss::status write_intthresh(unsigned addr, reg_t val); + iss::status write_xtvt(unsigned addr, reg_t val); iss::status write_dcsr_dcsr(unsigned addr, reg_t val); iss::status read_dcsr_reg(unsigned addr, reg_t &val); iss::status write_dcsr_reg(unsigned addr, reg_t val); @@ -460,7 +461,7 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) } if(FEAT & FEAT_CLIC) { csr_rd_cb[mtvt] = &this_class::read_csr_reg; - csr_wr_cb[mtvt] = &this_class::write_csr_reg; + csr_wr_cb[mtvt] = &this_class::write_xtvt; csr_rd_cb[mxnti] = &this_class::read_csr_reg; csr_wr_cb[mxnti] = &this_class::write_csr_reg; csr_rd_cb[mintstatus] = &this_class::read_csr_reg; @@ -1109,6 +1110,12 @@ iss::status riscv_hart_mu_p::write_intthresh(unsigned addr, reg_t va return iss::Ok; } +template +iss::status riscv_hart_mu_p::write_xtvt(unsigned addr, reg_t val) { + csr[addr]= val & ~0x3fULL; + return iss::Ok; +} + template iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { switch (paddr.val) { From 8be5fe71dfe60277e1635ae79a3cb25a4634cbc9 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 12 Mar 2023 07:42:09 +0100 Subject: [PATCH 059/184] fixes template name typo --- src/iss/arch/riscv_hart_m_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index c57263c..c0d5805 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -945,7 +945,7 @@ iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val } template -iss::status riscv_hart_mu_p::write_xtvt(unsigned addr, reg_t val) { +iss::status riscv_hart_m_p::write_xtvt(unsigned addr, reg_t val) { csr[addr]= val & ~0x3fULL; return iss::Ok; } From c2758e832187c79f93a72cc403eb54c5648003bf Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 15 Mar 2023 09:07:00 +0100 Subject: [PATCH 060/184] removes mscratchcsw from CLIC feature --- src/iss/arch/riscv_hart_m_p.h | 8 ++++---- src/iss/arch/riscv_hart_mu_p.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index c0d5805..0652bd6 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -419,10 +419,10 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr_wr_cb[mxnti] = &this_class::write_csr_reg; csr_rd_cb[mintstatus] = &this_class::read_csr_reg; csr_wr_cb[mintstatus] = &this_class::write_null; - csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; - csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; - csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; - csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; +// csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; +// csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; +// csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; +// csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_wr_cb[mintthresh] = &this_class::write_intthresh; diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index d4032c3..1ca4f96 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -466,10 +466,10 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_wr_cb[mxnti] = &this_class::write_csr_reg; csr_rd_cb[mintstatus] = &this_class::read_csr_reg; csr_wr_cb[mintstatus] = &this_class::write_null; - csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; - csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; - csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; - csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; +// csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; +// csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; +// csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; +// csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_wr_cb[mintthresh] = &this_class::write_intthresh; From fedbff59713e6f44214d9b05d407cb3008dedfdf Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 15 Mar 2023 12:27:39 +0100 Subject: [PATCH 061/184] fixes xcause and u-mode clic CSRs --- src/iss/arch/riscv_hart_common.h | 6 ++++ src/iss/arch/riscv_hart_m_p.h | 23 ++++++++++++--- src/iss/arch/riscv_hart_mu_p.h | 50 ++++++++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index 704fc2f..4bb2f43 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -51,12 +51,18 @@ enum riscv_csr { ustatus = 0x000, uie = 0x004, utvec = 0x005, + utvt = 0x007, //CLIC // User Trap Handling uscratch = 0x040, uepc = 0x041, ucause = 0x042, utval = 0x043, uip = 0x044, + uxnti = 0x045, //CLIC + uintstatus = 0xCB1, // MRW Current interrupt levels (CLIC) - addr subject to change + uintthresh = 0x047, // MRW Interrupt-level threshold (CLIC) - addr subject to change + uscratchcsw = 0x048, // MRW Conditional scratch swap on priv mode change (CLIC) + uscratchcswl = 0x049, // MRW Conditional scratch swap on level change (CLIC) // User Floating-Point CSRs fflags = 0x001, frm = 0x002, diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 0652bd6..86d5877 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -304,6 +304,7 @@ protected: iss::status read_time(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_cause(unsigned addr, reg_t &val); iss::status write_cause(unsigned addr, reg_t val); iss::status read_ie(unsigned addr, reg_t &val); iss::status write_ie(unsigned addr, reg_t val); @@ -376,7 +377,7 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) // common regs const std::array addrs{{ misa, mvendorid, marchid, mimpid, - mepc, mtvec, mscratch, mcause, mtval + mepc, mtvec, mscratch, mtval }}; for(auto addr: addrs) { csr_rd_cb[addr] = &this_class::read_csr_reg; @@ -400,6 +401,7 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[mstatus] = &this_class::read_status; csr_wr_cb[mstatus] = &this_class::write_status; + csr_rd_cb[mcause] = &this_class::read_cause; csr_wr_cb[mcause] = &this_class::write_cause; csr_rd_cb[mtvec] = &this_class::read_tvec; csr_wr_cb[mepc] = &this_class::write_epc; @@ -415,8 +417,8 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) if(FEAT & FEAT_CLIC) { csr_rd_cb[mtvt] = &this_class::read_csr_reg; csr_wr_cb[mtvt] = &this_class::write_xtvt; - csr_rd_cb[mxnti] = &this_class::read_csr_reg; - csr_wr_cb[mxnti] = &this_class::write_csr_reg; +// csr_rd_cb[mxnti] = &this_class::read_csr_reg; +// csr_wr_cb[mxnti] = &this_class::write_csr_reg; csr_rd_cb[mintstatus] = &this_class::read_csr_reg; csr_wr_cb[mintstatus] = &this_class::write_null; // csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; @@ -425,7 +427,6 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) // csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_wr_cb[mintthresh] = &this_class::write_intthresh; - clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; @@ -865,8 +866,22 @@ template iss::status riscv_hart_m_p return iss::Ok; } +template iss::status riscv_hart_m_p::read_cause(unsigned addr, reg_t &val) { + auto res = csr[addr]; + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { + res |= state.mstatus.MPIE<<27; + res |= state.mstatus.MPP<<28; + } + val=res; + return iss::Ok; +} + template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { csr[addr] = val & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { + state.mstatus.MPIE=(val>>27)&0x1; + state.mstatus.MPP=(val>>28)&0x3; + } return iss::Ok; } diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 1ca4f96..1c377eb 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -319,6 +319,7 @@ protected: iss::status read_time(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_cause(unsigned addr, reg_t &val); iss::status write_cause(unsigned addr, reg_t val); iss::status read_ie(unsigned addr, reg_t &val); iss::status write_ie(unsigned addr, reg_t val); @@ -394,8 +395,8 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) // common regs const std::array addrs{{ misa, mvendorid, marchid, mimpid, - mepc, mtvec, mscratch, mcause, mtval, - uepc, utvec, uscratch, ucause, utval, + mepc, mtvec, mscratch, mtval, + uepc, utvec, uscratch, utval, }}; for(auto addr: addrs) { csr_rd_cb[addr] = &this_class::read_csr_reg; @@ -419,6 +420,7 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[mstatus] = &this_class::read_status; csr_wr_cb[mstatus] = &this_class::write_status; + csr_rd_cb[mcause] = &this_class::read_cause; csr_wr_cb[mcause] = &this_class::write_cause; csr_rd_cb[mtvec] = &this_class::read_tvec; csr_wr_cb[mepc] = &this_class::write_epc; @@ -456,14 +458,15 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_wr_cb[uepc] = &this_class::write_epc; csr_rd_cb[ustatus] = &this_class::read_status; csr_wr_cb[ustatus] = &this_class::write_status; + csr_rd_cb[ucause] = &this_class::read_cause; csr_wr_cb[ucause] = &this_class::write_cause; csr_rd_cb[utvec] = &this_class::read_tvec; } if(FEAT & FEAT_CLIC) { csr_rd_cb[mtvt] = &this_class::read_csr_reg; csr_wr_cb[mtvt] = &this_class::write_xtvt; - csr_rd_cb[mxnti] = &this_class::read_csr_reg; - csr_wr_cb[mxnti] = &this_class::write_csr_reg; +// csr_rd_cb[mxnti] = &this_class::read_csr_reg; +// csr_wr_cb[mxnti] = &this_class::write_csr_reg; csr_rd_cb[mintstatus] = &this_class::read_csr_reg; csr_wr_cb[mintstatus] = &this_class::write_null; // csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; @@ -472,7 +475,14 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) // csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_wr_cb[mintthresh] = &this_class::write_intthresh; - + if(FEAT & FEAT_EXT_N){ + csr_rd_cb[utvt] = &this_class::read_csr_reg; + csr_wr_cb[utvt] = &this_class::write_xtvt; + csr_rd_cb[uintstatus] = &this_class::read_csr_reg; + csr_wr_cb[uintstatus] = &this_class::write_null; + csr_rd_cb[uintthresh] = &this_class::read_csr_reg; + csr_wr_cb[uintthresh] = &this_class::write_intthresh; + } clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x30; clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; @@ -1015,8 +1025,38 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_cause(unsigned addr, reg_t &val) { + auto res = csr[addr]; + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { + auto mode = (addr >> 8) & 0x3; + switch(mode) { + case 0: + res |= state.mstatus.UPIE<<27; + break; + default: + res |= state.mstatus.MPIE<<27; + res |= state.mstatus.MPP<<28; + break; + } + } + val=res; + return iss::Ok; +} + template iss::status riscv_hart_mu_p::write_cause(unsigned addr, reg_t val) { csr[addr] = val & ((1UL<<(traits::XLEN-1))|(mcause_max_irq-1)); + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { + auto mode = (addr >> 8) & 0x3; + switch(mode) { + case 0: + state.mstatus.UPIE=(val>>27)&0x1; + break; + default: + state.mstatus.MPIE=(val>>27)&0x1; + state.mstatus.MPP=(val>>28)&0x3; + break; + } + } return iss::Ok; } From a943dd3bdfef992dea9ff3d7a559389c89bd1a32 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 15 Mar 2023 14:16:08 +0100 Subject: [PATCH 062/184] fixes wrong array size which led to unintended CSR definitions --- src/iss/arch/riscv_hart_m_p.h | 2 +- src/iss/arch/riscv_hart_mu_p.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 86d5877..36aec51 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -375,7 +375,7 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) //csr_wr_cb[addr] = &this_class::write_csr_reg; } // common regs - const std::array addrs{{ + const std::array addrs{{ misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mtval }}; diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 1c377eb..ac2e6b7 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -393,7 +393,7 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) //csr_wr_cb[addr] = &this_class::write_csr_reg; } // common regs - const std::array addrs{{ + const std::array addrs{{ misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mtval, uepc, utvec, uscratch, utval, From 39b2788b7e5559507bb967257a25fa13aa52aaa4 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 17 Mar 2023 09:09:09 +0100 Subject: [PATCH 063/184] implements and fixes CLIC CSR behavior --- src/iss/arch/riscv_hart_common.h | 1 + src/iss/arch/riscv_hart_m_p.h | 23 +++++++++++++++++----- src/iss/arch/riscv_hart_mu_p.h | 33 +++++++++++++++++++++++--------- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index 4bb2f43..45fc000 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -221,6 +221,7 @@ struct vm_info { struct feature_config { uint64_t clic_base{0xc0000000}; + unsigned clic_int_ctl_bits{4}; unsigned clic_num_irq{16}; unsigned clic_num_trigger{0}; uint64_t tcm_base{0x10000000}; diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 36aec51..9273cab 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -289,6 +289,8 @@ protected: uint32_t raw; }; std::vector clic_int_reg; + uint8_t clic_mprev_lvl{0}; + uint8_t clic_mact_lvl{0}; std::vector tcm; @@ -430,6 +432,8 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; + clic_mact_lvl = clic_mprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; + csr[mintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; insert_mem_range(cfg.clic_base, 0x5000UL, [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); @@ -869,18 +873,26 @@ template iss::status riscv_hart_m_p template iss::status riscv_hart_m_p::read_cause(unsigned addr, reg_t &val) { auto res = csr[addr]; if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { - res |= state.mstatus.MPIE<<27; - res |= state.mstatus.MPP<<28; - } - val=res; + val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); + val |= clic_mprev_lvl<<16; + val |= state.mstatus.MPIE<<27; + val |= state.mstatus.MPP<<28; + } else + val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); return iss::Ok; } template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { csr[addr] = val & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { + auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); + clic_mprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; state.mstatus.MPIE=(val>>27)&0x1; state.mstatus.MPP=(val>>28)&0x3; + } else { + auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); } return iss::Ok; } @@ -955,7 +967,7 @@ template iss::status riscv_hart_m_p template iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val) { - csr[addr]= val &0xff; + csr[addr]= (val &0xff) | (1<<(cfg.clic_int_ctl_bits)) - 1; return iss::Ok; } @@ -1107,6 +1119,7 @@ template inline void riscv_hart_m_p } template void riscv_hart_m_p::check_interrupt() { + //TODO: Implement CLIC functionality //auto ideleg = csr[mideleg]; // Multiple simultaneous interrupts and traps at the same privilege level are // handled in the following decreasing priority order: diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index ac2e6b7..1459f7c 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -304,6 +304,8 @@ protected: uint32_t raw; }; std::vector clic_int_reg; + uint8_t clic_mprev_lvl{0}, clic_uprev_lvl{0}; + uint8_t clic_mact_lvl{0}, clic_uact_lvl{0}; std::vector tcm; @@ -486,6 +488,10 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x30; clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; + clic_mact_lvl = clic_mprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; + clic_uact_lvl = clic_uprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; + csr[mintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; + csr[uintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; insert_mem_range(cfg.clic_base, 0x5000UL, [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); @@ -715,7 +721,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc return iss::Err; } try { - if(!is_debug(access) && (addr&(alignment-1))){ + if(!is_debug(access) && (addr&(alignment-1))){ this->trap_state = (1UL << 31) | 4<<16; fault_data=addr; return iss::Err; @@ -1026,36 +1032,44 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_cause(unsigned addr, reg_t &val) { - auto res = csr[addr]; if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { + val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); auto mode = (addr >> 8) & 0x3; switch(mode) { case 0: - res |= state.mstatus.UPIE<<27; + val |= clic_uprev_lvl<<16; + val |= state.mstatus.UPIE<<27; break; default: - res |= state.mstatus.MPIE<<27; - res |= state.mstatus.MPP<<28; + val |= clic_mprev_lvl<<16; + val |= state.mstatus.MPIE<<27; + val |= state.mstatus.MPP<<28; break; } - } - val=res; + } else + val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); return iss::Ok; } template iss::status riscv_hart_mu_p::write_cause(unsigned addr, reg_t val) { - csr[addr] = val & ((1UL<<(traits::XLEN-1))|(mcause_max_irq-1)); if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { + auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); auto mode = (addr >> 8) & 0x3; switch(mode) { case 0: + clic_uprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; state.mstatus.UPIE=(val>>27)&0x1; break; default: + clic_mprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; state.mstatus.MPIE=(val>>27)&0x1; state.mstatus.MPP=(val>>28)&0x3; break; } + } else { + auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); + csr[addr] = (val & mask) | (csr[addr] & ~mask); } return iss::Ok; } @@ -1146,7 +1160,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_intthresh(unsigned addr, reg_t val) { - csr[addr]= val &0xff; + csr[addr]= (val &0xff) | (1<<(cfg.clic_int_ctl_bits)) - 1; return iss::Ok; } @@ -1298,6 +1312,7 @@ template inline void riscv_hart_mu_p void riscv_hart_mu_p::check_interrupt() { + //TODO: Implement CLIC functionality auto ideleg = csr[mideleg]; // Multiple simultaneous interrupts and traps at the same privilege level are // handled in the following decreasing priority order: From febbc4fff036a1c6da9896d6ab079817c938e5a3 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 17 Mar 2023 10:23:05 +0100 Subject: [PATCH 064/184] fixes m/uintstatus read --- src/iss/arch/riscv_hart_m_p.h | 10 ++++++++-- src/iss/arch/riscv_hart_mu_p.h | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 9273cab..0c766b5 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -313,7 +313,7 @@ protected: iss::status read_ip(unsigned addr, reg_t &val); iss::status read_hartid(unsigned addr, reg_t &val); iss::status write_epc(unsigned addr, reg_t val); - iss::status write_intstatus(unsigned addr, reg_t val); + iss::status read_intstatus(unsigned addr, reg_t& val); iss::status write_intthresh(unsigned addr, reg_t val); iss::status write_xtvt(unsigned addr, reg_t val); iss::status write_dcsr_dcsr(unsigned addr, reg_t val); @@ -421,7 +421,7 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr_wr_cb[mtvt] = &this_class::write_xtvt; // csr_rd_cb[mxnti] = &this_class::read_csr_reg; // csr_wr_cb[mxnti] = &this_class::write_csr_reg; - csr_rd_cb[mintstatus] = &this_class::read_csr_reg; + csr_rd_cb[mintstatus] = &this_class::read_intstatus; csr_wr_cb[mintstatus] = &this_class::write_null; // csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; // csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; @@ -965,6 +965,12 @@ template iss::status riscv_hart_m_p return iss::Ok; } +template +iss::status riscv_hart_m_p::read_intstatus(unsigned addr, reg_t& val) { + val = (clic_mprev_lvl&0xff) <<24; + return iss::Ok; +} + template iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val) { csr[addr]= (val &0xff) | (1<<(cfg.clic_int_ctl_bits)) - 1; diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 1459f7c..bb9684a 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -330,7 +330,7 @@ protected: iss::status write_edeleg(unsigned addr, reg_t val); iss::status read_hartid(unsigned addr, reg_t &val); iss::status write_epc(unsigned addr, reg_t val); - iss::status write_intstatus(unsigned addr, reg_t val); + iss::status read_intstatus(unsigned addr, reg_t& val); iss::status write_intthresh(unsigned addr, reg_t val); iss::status write_xtvt(unsigned addr, reg_t val); iss::status write_dcsr_dcsr(unsigned addr, reg_t val); @@ -469,7 +469,7 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_wr_cb[mtvt] = &this_class::write_xtvt; // csr_rd_cb[mxnti] = &this_class::read_csr_reg; // csr_wr_cb[mxnti] = &this_class::write_csr_reg; - csr_rd_cb[mintstatus] = &this_class::read_csr_reg; + csr_rd_cb[mintstatus] = &this_class::read_intstatus; csr_wr_cb[mintstatus] = &this_class::write_null; // csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; // csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; @@ -480,7 +480,7 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) if(FEAT & FEAT_EXT_N){ csr_rd_cb[utvt] = &this_class::read_csr_reg; csr_wr_cb[utvt] = &this_class::write_xtvt; - csr_rd_cb[uintstatus] = &this_class::read_csr_reg; + csr_rd_cb[uintstatus] = &this_class::read_intstatus; csr_wr_cb[uintstatus] = &this_class::write_null; csr_rd_cb[uintthresh] = &this_class::read_csr_reg; csr_wr_cb[uintthresh] = &this_class::write_intthresh; @@ -1158,6 +1158,15 @@ template iss::status riscv_hart_mu_p +iss::status riscv_hart_mu_p::read_intstatus(unsigned addr, reg_t& val) { + auto mode = (addr >> 8) & 0x3; + val = clic_uprev_lvl&0xff; + if(mode==0x3) + val += (clic_mprev_lvl&0xff) <<24; + return iss::Ok; +} + template iss::status riscv_hart_mu_p::write_intthresh(unsigned addr, reg_t val) { csr[addr]= (val &0xff) | (1<<(cfg.clic_int_ctl_bits)) - 1; From 7efa92451068be3db9334681d1c337a5b29ebf1b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 17 Mar 2023 10:51:39 +0100 Subject: [PATCH 065/184] fixes m/uintstatus read --- src/iss/arch/riscv_hart_m_p.h | 2 +- src/iss/arch/riscv_hart_mu_p.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 0c766b5..123f8a6 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -967,7 +967,7 @@ template iss::status riscv_hart_m_p template iss::status riscv_hart_m_p::read_intstatus(unsigned addr, reg_t& val) { - val = (clic_mprev_lvl&0xff) <<24; + val = (clic_mact_lvl&0xff) <<24; return iss::Ok; } diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index bb9684a..1b828fe 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -1161,9 +1161,9 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_intstatus(unsigned addr, reg_t& val) { auto mode = (addr >> 8) & 0x3; - val = clic_uprev_lvl&0xff; + val = clic_uact_lvl&0xff; if(mode==0x3) - val += (clic_mprev_lvl&0xff) <<24; + val += (clic_mact_lvl&0xff) <<24; return iss::Ok; } From 8e1951f2986d56ac29efb243b8eadc09fe35eebd Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 23 Mar 2023 07:47:21 +0100 Subject: [PATCH 066/184] adds 64bit mstatus --- src/iss/arch/riscv_hart_m_p.h | 60 +++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 123f8a6..95f4b36 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -172,6 +172,66 @@ public: return 0b00000000000000000001100010001000; } }; + + // specialization 64bit + template class hart_state::value>::type> { + public: + BEGIN_BF_DECL(mstatus_t, T); + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) + BF_FIELD(SD, 63, 1); + // value of XLEN for S-mode + BF_FIELD(SXL, 34, 2); + // value of XLEN for U-mode + BF_FIELD(UXL, 32, 2); + // Trap SRET + BF_FIELD(TSR, 22, 1); + // Timeout Wait + BF_FIELD(TW, 21, 1); + // Trap Virtual Memory + BF_FIELD(TVM, 20, 1); + // Make eXecutable Readable + BF_FIELD(MXR, 19, 1); + // permit Supervisor User Memory access + BF_FIELD(SUM, 18, 1); + // Modify PRiVilege + BF_FIELD(MPRV, 17, 1); + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty + BF_FIELD(XS, 15, 2); + // floating-point unit status Off/Initial/Clean/Dirty + BF_FIELD(FS, 13, 2); + // machine previous privilege + BF_FIELD(MPP, 11, 2); + // supervisor previous privilege + BF_FIELD(SPP, 8, 1); + // previous machine interrupt-enable + BF_FIELD(MPIE, 7, 1); + // previous supervisor interrupt-enable + BF_FIELD(SPIE, 5, 1); + // previous user interrupt-enable + BF_FIELD(UPIE, 4, 1); + // machine interrupt-enable + BF_FIELD(MIE, 3, 1); + // supervisor interrupt-enable + BF_FIELD(SIE, 1, 1); + // user interrupt-enable + BF_FIELD(UIE, 0, 1); + END_BF_DECL(); + + mstatus_t mstatus; + + static const reg_t mstatus_reset_val = 0xa00000000; + + void write_mstatus(T val) { + auto mask = get_mask() &0xff; // MPP is hardcode as 0x3 + auto new_val = (mstatus.backing.val & ~mask) | (val & mask); + mstatus = new_val; + } + + static constexpr T get_mask() { + return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + } + }; + using hart_state_type = hart_state; constexpr reg_t get_irq_mask() { From 2e4faa4d50da990f2a5d72accc5530b832ded3f9 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 25 Mar 2023 09:14:56 +0100 Subject: [PATCH 067/184] fixes mstatus mask --- src/iss/arch/riscv_hart_m_p.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 95f4b36..11b3739 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -219,7 +219,7 @@ public: mstatus_t mstatus; - static const reg_t mstatus_reset_val = 0xa00000000; + static const reg_t mstatus_reset_val = 0x1800; void write_mstatus(T val) { auto mask = get_mask() &0xff; // MPP is hardcode as 0x3 @@ -228,7 +228,21 @@ public: } static constexpr T get_mask() { - return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + //return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + // + // +-TSR + // |+-TW + // ||+-TVM + // |||+-MXR + // ||||+-SUM + // |||||+-MPRV + // |||||| +-XS + // |||||| | +-FS + // |||||| | | +-MPP + // |||||| | | | +-SPP + // |||||| | | | |+-MPIE + // ||||||/|/|/| || +-MIE + return 0b00000000000000000001100010001000; } }; From d881cb6e639f9482686ae020ffa72ec62256994d Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 26 Mar 2023 12:12:34 +0200 Subject: [PATCH 068/184] fix data width of generated code --- gen_input/templates/interp/CORENAME.cpp.gtl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index ebedab0..7a3f88f 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -122,7 +122,7 @@ protected: inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; this->core.trap_state = trap_val; - this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); + this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); } inline void leave(unsigned lvl){ @@ -243,8 +243,8 @@ typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ auto pc=start; - auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); auto& trap_state = this->core.trap_state; auto& icount = this->core.icount; auto& cycle = this->core.cycle; From c5465bf9e27275d56a6a3cfa36ed5af6627b1f2c Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 26 Mar 2023 14:44:15 +0200 Subject: [PATCH 069/184] fixes according to fixed generator --- src/vm/interp/vm_tgc_c.cpp | 95 ++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 50 deletions(-) diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 8319ffa..55434d8 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -363,7 +363,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = (int32_t)imm; + *(X+rd) = (uint32_t)((int32_t)imm); } } } @@ -448,7 +448,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t new_pc = (*(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm)) & ~ 0x1; + uint32_t new_pc = (*(X+rs1) + (int16_t)sext<12>(imm)) & ~ 0x1; if(new_pc % traits::INSTR_ALIGNMENT) { raise(0, 0); } @@ -483,7 +483,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - if(*(X+rs1 % traits::RFS) == *(X+rs2 % traits::RFS)) { + if(*(X+rs1) == *(X+rs2)) { if(imm % traits::INSTR_ALIGNMENT) { raise(0, 0); } @@ -516,7 +516,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - if(*(X+rs1 % traits::RFS) != *(X+rs2 % traits::RFS)) { + if(*(X+rs1) != *(X+rs2)) { if(imm % traits::INSTR_ALIGNMENT) { raise(0, 0); } @@ -549,7 +549,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - if((int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)) { + if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) { if(imm % traits::INSTR_ALIGNMENT) { raise(0, 0); } @@ -582,7 +582,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - if((int32_t)*(X+rs1 % traits::RFS) >= (int32_t)*(X+rs2 % traits::RFS)) { + if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) { if(imm % traits::INSTR_ALIGNMENT) { raise(0, 0); } @@ -615,7 +615,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - if(*(X+rs1 % traits::RFS) < *(X+rs2 % traits::RFS)) { + if(*(X+rs1) < *(X+rs2)) { if(imm % traits::INSTR_ALIGNMENT) { raise(0, 0); } @@ -648,7 +648,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - if(*(X+rs1 % traits::RFS) >= *(X+rs2 % traits::RFS)) { + if(*(X+rs1) >= *(X+rs2)) { if(imm % traits::INSTR_ALIGNMENT) { raise(0, 0); } @@ -681,12 +681,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); int8_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.trap_state>=0x80000000UL) goto TRAP_LB; int8_t res = (int8_t)read_res; if(rd != 0) { - *(X+rd) = (int32_t)res; + *(X+rd) = (uint32_t)res; } } } @@ -712,12 +712,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); int16_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.trap_state>=0x80000000UL) goto TRAP_LH; int16_t res = (int16_t)read_res; if(rd != 0) { - *(X+rd) = (int32_t)res; + *(X+rd) = (uint32_t)res; } } } @@ -743,12 +743,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); int32_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.trap_state>=0x80000000UL) goto TRAP_LW; int32_t res = (int32_t)read_res; if(rd != 0) { - *(X+rd) = (int32_t)res; + *(X+rd) = (uint32_t)res; } } } @@ -774,7 +774,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); uint8_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.trap_state>=0x80000000UL) goto TRAP_LBU; uint8_t res = (uint8_t)read_res; @@ -805,7 +805,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t load_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); uint16_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.trap_state>=0x80000000UL) goto TRAP_LHU; uint16_t res = (uint16_t)read_res; @@ -836,8 +836,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, (int8_t)*(X+rs2 % traits::RFS)); + uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); + super::template write_mem(traits::MEM, store_address, (int8_t)*(X+rs2)); if(this->core.trap_state>=0x80000000UL) goto TRAP_SB; } } @@ -863,8 +863,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, (int16_t)*(X+rs2 % traits::RFS)); + uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); + super::template write_mem(traits::MEM, store_address, (int16_t)*(X+rs2)); if(this->core.trap_state>=0x80000000UL) goto TRAP_SH; } } @@ -890,8 +890,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t store_address = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, (int32_t)*(X+rs2 % traits::RFS)); + uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); + super::template write_mem(traits::MEM, store_address, (int32_t)*(X+rs2)); if(this->core.trap_state>=0x80000000UL) goto TRAP_SW; } } @@ -918,7 +918,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) + (int16_t)sext<12>(imm); + *(X+rd) = *(X+rs1) + (int16_t)sext<12>(imm); } } } @@ -945,7 +945,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = ((int32_t)*(X+rs1 % traits::RFS) < (int16_t)sext<12>(imm))? 1 : 0; + *(X+rd) = ((int32_t)*(X+rs1) < (int16_t)sext<12>(imm))? 1 : 0; } } } @@ -972,7 +972,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = (*(X+rs1 % traits::RFS) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; + *(X+rd) = (*(X+rs1) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; } } } @@ -999,7 +999,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) ^ (int16_t)sext<12>(imm); + *(X+rd) = *(X+rs1) ^ (uint32_t)((int16_t)sext<12>(imm)); } } } @@ -1026,7 +1026,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) | (int16_t)sext<12>(imm); + *(X+rd) = *(X+rs1) | (uint32_t)((int16_t)sext<12>(imm)); } } } @@ -1053,7 +1053,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) & (int16_t)sext<12>(imm); + *(X+rd) = *(X+rs1) & (uint32_t)((int16_t)sext<12>(imm)); } } } @@ -1080,7 +1080,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) << shamt; + *(X+rd) = *(X+rs1) << shamt; } } } @@ -1107,7 +1107,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) >> shamt; + *(X+rd) = *(X+rs1) >> shamt; } } } @@ -1134,7 +1134,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = (int32_t)*(X+rs1 % traits::RFS) >> shamt; + *(X+rd) = (int32_t)*(X+rs1) >> shamt; } } } @@ -1161,7 +1161,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) + *(X+rs2 % traits::RFS); + *(X+rd) = *(X+rs1) + *(X+rs2); } } } @@ -1188,7 +1188,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) - *(X+rs2 % traits::RFS); + *(X+rd) = *(X+rs1) - *(X+rs2); } } } @@ -1215,7 +1215,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) << (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); } } } @@ -1241,13 +1241,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (int32_t)*(X+rs1 % traits::RFS) < (int32_t)*(X+rs2 % traits::RFS)? 1 : 0; - } + if(rd != 0) { + *(X+rd) = (int32_t)*(X+rs1) < (int32_t)*(X+rs2)? 1 : 0; } } } @@ -1274,7 +1269,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = (uint32_t)*(X+rs1 % traits::RFS) < (uint32_t)*(X+rs2 % traits::RFS)? 1 : 0; + *(X+rd) = *(X+rs1) < *(X+rs2)? 1 : 0; } } } @@ -1301,7 +1296,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) ^ *(X+rs2 % traits::RFS); + *(X+rd) = *(X+rs1) ^ *(X+rs2); } } } @@ -1328,7 +1323,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + *(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); } } } @@ -1355,7 +1350,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = (int32_t)*(X+rs1 % traits::RFS) >> (*(X+rs2 % traits::RFS) & (traits::XLEN - 1)); + *(X+rd) = (int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); } } } @@ -1382,7 +1377,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) | *(X+rs2 % traits::RFS); + *(X+rd) = *(X+rs1) | *(X+rs2); } } } @@ -1409,7 +1404,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1 % traits::RFS) & *(X+rs2 % traits::RFS); + *(X+rd) = *(X+rs1) & *(X+rs2); } } } @@ -1509,7 +1504,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t xrs1 = *(X+rs1 % traits::RFS); + uint32_t xrs1 = *(X+rs1); if(rd != 0) { uint32_t read_res = super::template read_mem(traits::CSR, csr); if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; @@ -1549,7 +1544,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t read_res = super::template read_mem(traits::CSR, csr); if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; uint32_t xrd = read_res; - uint32_t xrs1 = *(X+rs1 % traits::RFS); + uint32_t xrs1 = *(X+rs1); if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd | xrs1); if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; @@ -1584,7 +1579,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t read_res = super::template read_mem(traits::CSR, csr); if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; uint32_t xrd = read_res; - uint32_t xrs1 = *(X+rs1 % traits::RFS); + uint32_t xrs1 = *(X+rs1); if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; From 6213445bc403009624b530251415d3ddcd007eec Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 27 Mar 2023 12:04:43 +0200 Subject: [PATCH 070/184] fixes 64bit behavior of CSR regs --- src/iss/arch/riscv_hart_m_p.h | 27 ++++++++++++--------------- src/iss/arch/riscv_hart_mu_p.h | 27 ++++++++++++--------------- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 11b3739..890bf6c 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -252,8 +252,11 @@ public: return 0b100010001000; // only machine mode is supported } + constexpr bool has_compressed() { + return traits::MISA_VAL&0b0100; + } constexpr reg_t get_pc_mask() { - return traits::MISA_VAL&0b0100?~1:~3; + return has_compressed()?~1:~3; } riscv_hart_m_p(feature_config cfg = feature_config{}); @@ -435,7 +438,7 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr_rd_cb[addr] = &this_class::read_null; csr_wr_cb[addr] = &this_class::write_csr_reg; } - for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ + if(traits::XLEN==32) for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ csr_rd_cb[addr] = &this_class::read_null; csr_wr_cb[addr] = &this_class::write_csr_reg; } @@ -446,7 +449,7 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) for (unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr){ csr_rd_cb[addr] = &this_class::read_null; } - for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){ + if(traits::XLEN==32) for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){ csr_rd_cb[addr] = &this_class::read_null; //csr_wr_cb[addr] = &this_class::write_csr_reg; } @@ -469,12 +472,12 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr_rd_cb[mcycle] = &this_class::read_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle; - csr_rd_cb[mcycleh] = &this_class::read_cycle; - csr_wr_cb[mcycleh] = &this_class::write_cycle; + if(traits::XLEN==32) csr_rd_cb[mcycleh] = &this_class::read_cycle; + if(traits::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle; csr_rd_cb[minstret] = &this_class::read_instret; csr_wr_cb[minstret] = &this_class::write_instret; - csr_rd_cb[minstreth] = &this_class::read_instret; - csr_wr_cb[minstreth] = &this_class::write_instret; + if(traits::XLEN==32) csr_rd_cb[minstreth] = &this_class::read_instret; + if(traits::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[mstatus] = &this_class::read_status; csr_wr_cb[mstatus] = &this_class::write_status; csr_rd_cb[mcause] = &this_class::read_cause; @@ -633,7 +636,7 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce try { switch (space) { case traits::MEM: { - auto alignment = is_fetch(access)? (traits::MISA_VAL&0x100? 2 : 4) : length; + auto alignment = is_fetch(access)? (has_compressed()? 2 : 4) : length; if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { fault_data = addr; if (is_debug(access)) throw trap_access(0, addr); @@ -869,7 +872,6 @@ template iss::status riscv_hart_m_p if (addr == mcycle) { val = static_cast(cycle_val); } else if (addr == mcycleh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; val = static_cast(cycle_val >> 32); } return iss::Ok; @@ -877,8 +879,6 @@ template iss::status riscv_hart_m_p template iss::status riscv_hart_m_p::write_cycle(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { - if (addr == mcycleh) - return iss::Err; mcycle_csr = static_cast(val); } else { if (addr == mcycle) { @@ -895,7 +895,6 @@ template iss::status riscv_hart_m_p if ((addr&0xff) == (minstret&0xff)) { val = static_cast(this->instret); } else if ((addr&0xff) == (minstreth&0xff)) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; val = static_cast(this->instret >> 32); } return iss::Ok; @@ -903,8 +902,6 @@ template iss::status riscv_hart_m_p template iss::status riscv_hart_m_p::write_instret(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { - if ((addr&0xff) == (minstreth&0xff)) - return iss::Err; this->instret = static_cast(val); } else { if ((addr&0xff) == (minstret&0xff)) { @@ -1244,7 +1241,7 @@ template uint64_t riscv_hart_m_p::e csr[mtval] = static_cast(addr); break; case 2: - csr[mtval] = (instr & 0x3)==3?instr:instr&0xffff; + csr[mtval] = (!has_compressed() || (instr & 0x3)==3)?instr:instr&0xffff; break; case 3: if((FEAT & FEAT_DEBUG) && (csr[dcsr] & 0x8000)) { diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 1b828fe..c896701 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -193,8 +193,11 @@ public: return m[mode]; } + constexpr bool has_compressed() { + return traits::MISA_VAL&0b0100; + } constexpr reg_t get_pc_mask() { - return traits::MISA_VAL&0b0100?~1:~3; + return has_compressed()?~1:~3; } riscv_hart_mu_p(feature_config cfg = feature_config{}); @@ -379,7 +382,7 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_rd_cb[addr] = &this_class::read_null; csr_wr_cb[addr] = &this_class::write_csr_reg; } - for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ + if(traits::XLEN==32) for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ csr_rd_cb[addr] = &this_class::read_null; csr_wr_cb[addr] = &this_class::write_csr_reg; } @@ -390,7 +393,7 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) for (unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr){ csr_rd_cb[addr] = &this_class::read_null; } - for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){ + if(traits::XLEN==32) for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){ csr_rd_cb[addr] = &this_class::read_null; //csr_wr_cb[addr] = &this_class::write_csr_reg; } @@ -414,12 +417,12 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_rd_cb[mcycle] = &this_class::read_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle; - csr_rd_cb[mcycleh] = &this_class::read_cycle; - csr_wr_cb[mcycleh] = &this_class::write_cycle; + if(traits::XLEN==32) csr_rd_cb[mcycleh] = &this_class::read_cycle; + if(traits::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle; csr_rd_cb[minstret] = &this_class::read_instret; csr_wr_cb[minstret] = &this_class::write_instret; - csr_rd_cb[minstreth] = &this_class::read_instret; - csr_wr_cb[minstreth] = &this_class::write_instret; + if(traits::XLEN==32) csr_rd_cb[minstreth] = &this_class::read_instret; + if(traits::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[mstatus] = &this_class::read_status; csr_wr_cb[mstatus] = &this_class::write_status; csr_rd_cb[mcause] = &this_class::read_cause; @@ -713,7 +716,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc return iss::Err; } } - auto alignment = is_fetch(access)? (traits::MISA_VAL&0x100? 2 : 4) : length; + auto alignment = is_fetch(access)? (has_compressed()? 2 : 4) : length; if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { fault_data = addr; if (is_debug(access)) throw trap_access(0, addr); @@ -957,7 +960,6 @@ template iss::status riscv_hart_mu_p(cycle_val); } else if (addr == mcycleh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; val = static_cast(cycle_val >> 32); } return iss::Ok; @@ -965,8 +967,6 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_cycle(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { - if (addr == mcycleh) - return iss::Err; mcycle_csr = static_cast(val); } else { if (addr == mcycle) { @@ -983,7 +983,6 @@ template iss::status riscv_hart_mu_p(this->instret); } else if ((addr&0xff) == (minstreth&0xff)) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; val = static_cast(this->instret >> 32); } return iss::Ok; @@ -991,8 +990,6 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_instret(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { - if ((addr&0xff) == (minstreth&0xff)) - return iss::Err; this->instret = static_cast(val); } else { if ((addr&0xff) == (minstret&0xff)) { @@ -1369,7 +1366,7 @@ template uint64_t riscv_hart_mu_p:: csr[utval | (new_priv << 8)] = static_cast(addr); break; case 2: - csr[utval | (new_priv << 8)] = (instr & 0x3)==3?instr:instr&0xffff; + csr[utval | (new_priv << 8)] = (!has_compressed() || (instr & 0x3)==3)?instr:instr&0xffff; break; case 3: if((FEAT & FEAT_DEBUG) && (csr[dcsr] & 0x8000)) { From 98dd329833515428237698a01e1883934356e748 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 4 Apr 2023 09:23:08 +0200 Subject: [PATCH 071/184] fixes CSR access rights --- src/iss/arch/riscv_hart_m_p.h | 12 +++++++----- src/iss/arch/riscv_hart_mu_p.h | 10 +++++++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 890bf6c..5967c29 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -454,11 +454,13 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) //csr_wr_cb[addr] = &this_class::write_csr_reg; } // common regs - const std::array addrs{{ - misa, mvendorid, marchid, mimpid, - mepc, mtvec, mscratch, mtval - }}; - for(auto addr: addrs) { + const std::array roaddrs{{misa, mvendorid, marchid, mimpid}}; + for(auto addr: roaddrs) { + csr_rd_cb[addr] = &this_class::read_csr_reg; + csr_wr_cb[addr] = &this_class::write_null; + } + const std::array rwaddrs{{mepc, mtvec, mscratch, mtval}}; + for(auto addr: rwaddrs) { csr_rd_cb[addr] = &this_class::read_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg; } diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index c896701..8a1ce3d 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -398,12 +398,16 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) //csr_wr_cb[addr] = &this_class::write_csr_reg; } // common regs - const std::array addrs{{ - misa, mvendorid, marchid, mimpid, + const std::array roaddrs{{misa, mvendorid, marchid, mimpid}}; + for(auto addr: roaddrs) { + csr_rd_cb[addr] = &this_class::read_csr_reg; + csr_wr_cb[addr] = &this_class::write_null; + } + const std::array rwaddrs{{ mepc, mtvec, mscratch, mtval, uepc, utvec, uscratch, utval, }}; - for(auto addr: addrs) { + for(auto addr: rwaddrs) { csr_rd_cb[addr] = &this_class::read_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg; } From a8a27823293af3f8454f07046406146d8ee32982 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 4 Apr 2023 16:10:12 +0200 Subject: [PATCH 072/184] adds changes from latest CoreDSL description --- src/vm/interp/vm_tgc_c.cpp | 277 ++++++++++++++++++++++++------------- 1 file changed, 181 insertions(+), 96 deletions(-) diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 55434d8..eaef390 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -1727,11 +1727,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); - *(X+rd % traits::RFS) = (uint32_t)res; - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int64_t res = (int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2); + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } TRAP_MUL:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::MULH: { @@ -1750,11 +1755,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (int64_t)(int32_t)*(X+rs2 % traits::RFS); - *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int64_t res = (int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2); + if(rd != 0) { + *(X+rd) = (uint32_t)(res >> traits::XLEN); + } + } + } TRAP_MULH:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::MULHSU: { @@ -1773,11 +1783,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - int64_t res = (int64_t)(int32_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); - *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int64_t res = (int64_t)(int32_t)*(X+rs1) * (uint64_t)*(X+rs2); + if(rd != 0) { + *(X+rd) = (uint32_t)(res >> traits::XLEN); + } + } + } TRAP_MULHSU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::MULHU: { @@ -1796,11 +1811,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - uint64_t res = (uint64_t)*(X+rs1 % traits::RFS) * (uint64_t)*(X+rs2 % traits::RFS); - *(X+rd % traits::RFS) = (uint32_t)(res >> traits::XLEN); - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + uint64_t res = (uint64_t)*(X+rs1) * (uint64_t)*(X+rs2); + if(rd != 0) { + *(X+rd) = (uint32_t)(res >> traits::XLEN); + } + } + } TRAP_MULHU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::DIV: { @@ -1819,21 +1839,28 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { - uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) { - *(X+rd % traits::RFS) = MMIN; + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int32_t dividend = (int32_t)*(X+rs1); + int32_t divisor = (int32_t)*(X+rs2); + if(rd != 0) { + if(divisor != 0) { + uint32_t MMIN = ((uint32_t)1) << (traits::XLEN - 1); + if(*(X+rs1) == MMIN && divisor == - 1) { + *(X+rd) = MMIN; + } + else { + *(X+rd) = dividend / divisor; + } + } + else { + *(X+rd) = (int32_t)- 1; + } + } + } } - else { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) / (int32_t)*(X+rs2 % traits::RFS); - } - } - else { - *(X+rd % traits::RFS) = - 1; - } - } - } TRAP_DIV:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::DIVU: { @@ -1852,15 +1879,22 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) / *(X+rs2 % traits::RFS); - } - else { - *(X+rd % traits::RFS) = - 1; - } - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs2) != 0) { + if(rd != 0) { + *(X+rd) = *(X+rs1) / *(X+rs2); + } + } + else { + if(rd != 0) { + *(X+rd) = (int32_t)- 1; + } + } + } + } TRAP_DIVU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::REM: { @@ -1879,21 +1913,30 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { - uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1 % traits::RFS) == MMIN && (int32_t)*(X+rs2 % traits::RFS) == - 1) { - *(X+rd % traits::RFS) = 0; + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs2) != 0) { + uint32_t MMIN = 1 << (traits::XLEN - 1); + if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) { + if(rd != 0) { + *(X+rd) = 0; + } + } + else { + if(rd != 0) { + *(X+rd) = (int32_t)*(X+rs1) % (int32_t)*(X+rs2); + } + } + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1); + } + } + } } - else { - *(X+rd % traits::RFS) = (int32_t)*(X+rs1 % traits::RFS) % (int32_t)*(X+rs2 % traits::RFS); - } - } - else { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); - } - } - } TRAP_REM:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::REMU: { @@ -1912,15 +1955,22 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - if((rd % traits::RFS) != 0) { - if(*(X+rs2 % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS) % *(X+rs2 % traits::RFS); - } - else { - *(X+rd % traits::RFS) = *(X+rs1 % traits::RFS); - } - } - } + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs2) != 0) { + if(rd != 0) { + *(X+rd) = *(X+rs1) % *(X+rs2); + } + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1); + } + } + } + } TRAP_REMU:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CADDI4SPN: { @@ -2007,8 +2057,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if((rs1 % traits::RFS) != 0) { - *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) + (int8_t)sext<6>(imm); + if(rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rs1 != 0) { + *(X+rs1) = *(X+rs1) + (int8_t)sext<6>(imm); + } } } TRAP_CADDI:break; @@ -2061,10 +2116,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int8_t)sext<6>(imm); - } - } + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (int8_t)sext<6>(imm); + } + } + } TRAP_CLI:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CLUI: { @@ -2082,11 +2142,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if(imm == 0) { + if(imm == 0 || rd >= traits::RFS) { raise(0, 2); } - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = (int32_t)sext<18>(imm); + if(rd != 0) { + *(X+rd) = (int32_t)sext<18>(imm); } } TRAP_CLUI:break; @@ -2345,8 +2405,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if(nzuimm) { - *(X+rs1 % traits::RFS) = *(X+rs1 % traits::RFS) << nzuimm; + if(rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rs1 != 0) { + *(X+rs1) = *(X+rs1) << nzuimm; + } } } TRAP_CSLLI:break; @@ -2366,14 +2431,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if(rd % traits::RFS) { + if(rd >= traits::RFS || rd == 0) { + raise(0, 2); + } + else { int32_t read_res = super::template read_mem(traits::MEM, *(X+2) + uimm); if(this->core.trap_state>=0x80000000UL) goto TRAP_CLWSP; int32_t res = read_res; - *(X+rd % traits::RFS) = (int32_t)res; - } - else { - raise(0, 2); + *(X+rd) = (int32_t)res; } } TRAP_CLWSP:break; @@ -2393,8 +2458,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rs2 % traits::RFS); + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs2); + } } } TRAP_CMV:break; @@ -2413,7 +2483,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if(rs1) { + if(rs1 && rs1 < traits::RFS) { *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; super::ex_info.branch_taken=true; } @@ -2451,8 +2521,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - if((rd % traits::RFS) != 0) { - *(X+rd % traits::RFS) = *(X+rd % traits::RFS) + *(X+rs2 % traits::RFS); + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rd) + *(X+rs2); + } } } TRAP_CADD:break; @@ -2471,11 +2546,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint32_t new_pc = *(X+rs1 % traits::RFS); - *(X+1) = *PC + 2; - *NEXT_PC = new_pc & ~ 0x1; - super::ex_info.branch_taken=true; - } + if(rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t new_pc = *(X+rs1); + *(X+1) = *PC + 2; + *NEXT_PC = new_pc & ~ 0x1; + super::ex_info.branch_taken=true; + } + } TRAP_CJALR:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::CEBREAK: { @@ -2506,10 +2586,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint32_t offs = *(X+2) + uimm; - super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 % traits::RFS)); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSWSP; - } + if(rs2 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t offs = *(X+2) + uimm; + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2)); + if(this->core.trap_state>=0x80000000UL) goto TRAP_CSWSP; + } + } TRAP_CSWSP:break; }// @suppress("No break at end of case") case arch::traits::opcode_e::DII: { From f626ee26845b7fc92e70578d85e6ae1b75b0c704 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 5 Apr 2023 15:38:25 +0200 Subject: [PATCH 073/184] fixes privilege wrapper for M/U to cope with 64bit --- src/iss/arch/riscv_hart_mu_p.h | 88 +++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 8a1ce3d..fc2f16e 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -181,6 +181,89 @@ public: #endif } }; + + // specialization 64bit + template class hart_state::value>::type> { + public: + BEGIN_BF_DECL(mstatus_t, T); + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) + BF_FIELD(SD, 63, 1); + // value of XLEN for S-mode + BF_FIELD(SXL, 34, 2); + // value of XLEN for U-mode + BF_FIELD(UXL, 32, 2); + // Trap SRET + BF_FIELD(TSR, 22, 1); + // Timeout Wait + BF_FIELD(TW, 21, 1); + // Trap Virtual Memory + BF_FIELD(TVM, 20, 1); + // Make eXecutable Readable + BF_FIELD(MXR, 19, 1); + // permit Supervisor User Memory access + BF_FIELD(SUM, 18, 1); + // Modify PRiVilege + BF_FIELD(MPRV, 17, 1); + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty + BF_FIELD(XS, 15, 2); + // floating-point unit status Off/Initial/Clean/Dirty + BF_FIELD(FS, 13, 2); + // machine previous privilege + BF_FIELD(MPP, 11, 2); + // supervisor previous privilege + BF_FIELD(SPP, 8, 1); + // previous machine interrupt-enable + BF_FIELD(MPIE, 7, 1); + // previous supervisor interrupt-enable + BF_FIELD(SPIE, 5, 1); + // previous user interrupt-enable + BF_FIELD(UPIE, 4, 1); + // machine interrupt-enable + BF_FIELD(MIE, 3, 1); + // supervisor interrupt-enable + BF_FIELD(SIE, 1, 1); + // user interrupt-enable + BF_FIELD(UIE, 0, 1); + END_BF_DECL(); + + mstatus_t mstatus; + + static const reg_t mstatus_reset_val = 0x1800; + + void write_mstatus(T val, unsigned priv_lvl) { + auto mask = get_mask(priv_lvl); + auto new_val = (mstatus.backing.val & ~mask) | (val & mask); + mstatus = new_val; + } + + static constexpr uint64_t get_mask(unsigned priv_lvl) { +#if __cplusplus < 201402L + return priv_lvl == PRIV_U ? 0x011ULL : priv_lvl == PRIV_S ? 0x000de133ULL : 0x007ff9ddULL; +#else + switch (priv_lvl) { + case PRIV_U: return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 + default: + // +-SD + // | +-TSR + // | |+-TW + // | ||+-TVM + // | |||+-MXR + // | ||||+-SUM + // | |||||+-MPRV + // | |||||| +-XS + // | |||||| | +-FS + // | |||||| | | +-MPP + // | |||||| | | | +-SPP + // | |||||| | | | |+-MPIE + // | |||||| | | | || +-UPIE + // | ||||||/|/|/| || |+-MIE + // | ||||||/|/|/| || || +-UIE + return 0b00000000000000000001100010011001; + } +#endif + } + }; + using hart_state_type = hart_state; constexpr reg_t get_irq_mask(size_t mode) { @@ -450,7 +533,7 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_rd_cb[i] = &this_class::read_csr_reg; csr_wr_cb[i] = &this_class::write_csr_reg; } - for(size_t i=pmpcfg0; i<=pmpcfg3; ++i){ + for(size_t i=pmpcfg0; i bool riscv_hart_mu_p::pmp_ constexpr auto PMP_NAPOT =0x3U; reg_t base = 0; auto any_active = false; + auto const cfg_reg_size=sizeof(reg_t); for (size_t i = 0; i < 16; i++) { reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; - uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); + uint8_t cfg = csr[pmpcfg0+(i/cfg_reg_size)]>>(i%cfg_reg_size); if (cfg & PMP_A) { any_active=true; auto pmp_a = (cfg & PMP_A) >> 3; From 8ff55d7b92b3e45e633090efb68d85de181a6e3a Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 14 Apr 2023 19:34:41 +0200 Subject: [PATCH 074/184] updates CWR dependent core_complex definition --- src/sysc/core_complex.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sysc/core_complex.h b/src/sysc/core_complex.h index f7d8d73..9b53397 100644 --- a/src/sysc/core_complex.h +++ b/src/sysc/core_complex.h @@ -140,6 +140,7 @@ public: , gdb_server_port{"gdb_server_port", 0} , dump_ir{"dump_ir", false} , mhartid{"mhartid", 0} + , plugins{"plugins", ""} , read_lut(tlm_dmi_ext()) , write_lut(tlm_dmi_ext()) { From 0304aac9e5610522be4f54ee5a6d6b58912d03f1 Mon Sep 17 00:00:00 2001 From: Rocco Jonack Date: Wed, 19 Apr 2023 05:20:58 -0700 Subject: [PATCH 075/184] fixed some issues in import script; added README for reference; added initial testbench script(to be improved) --- contrib/README.md | 19 +++++++++++++++++++ contrib/tgc_import.tcl | 11 ++++------- contrib/tgc_import_tb.pct | 29 +++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 contrib/README.md create mode 100644 contrib/tgc_import_tb.pct diff --git a/contrib/README.md b/contrib/README.md new file mode 100644 index 0000000..ea9a647 --- /dev/null +++ b/contrib/README.md @@ -0,0 +1,19 @@ + # requires conan version 1.59 + # requires decent cmake version 3.23 for instance + git clone --recursive -b develop https://git.minres.com/TGFS/TGC-ISS.git + cd TGC-ISS/ + setenv COWAREHOME /scratch/rocco/workarea/tools/synopsys/T-2022.06-3 + setenv SNPSLMD_LICENSE_FILE 27001@lic02.arteris.com:5285@lic-node0:5285@lic03:5285@lic-node1 + source $COWAREHOME/SLS/linux/setup.csh pae + setenv SNPS_ENABLE_MEM_ON_DEMAND_IN_GENERIC_MEM 1 + setenv PATH $COWAREHOME/common/bin/:${PATH} + setenv LD_LIBRARY_PATH /scratch/rocco/workarea/tools/gcc-9.3.0-install/lib64/ + setenv CC /scratch/rocco/workarea/tools/synopsys/T-2022.06-3/SLS/linux/common/bin//gcc + setenv CXX /scratch/rocco/workarea/tools/synopsys/T-2022.06-3/SLS/linux/common/bin//g++ + cmake -S . -B build/Debug-PA -DCMAKE_BUILD_TYPE=Debug -DUSE_CWR_SYSTEMC=ON -DBUILD_SHARED_LIBS=ON -DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=/scratch/rocco/partners/minres/TGC-ISS/install + cd build/Debug-PA/ + make -j 16 install + cd ../../dbt-rise-tgc/contrib + setenv TGFS_INSTALL_ROOT /scratch/rocco/partners/minres/TGC-ISS/install/ + # import the TGC core itself + pct tgc_import.tcl diff --git a/contrib/tgc_import.tcl b/contrib/tgc_import.tcl index 9726408..04e0262 100644 --- a/contrib/tgc_import.tcl +++ b/contrib/tgc_import.tcl @@ -6,13 +6,10 @@ proc getScriptDirectory {} { set scriptFolder [file dirname $dispScriptFile] return $scriptFolder } -if { $::env(SNPS_VP_PRODUCT) == "PAULTRA" } { set hardware /HARDWARE/HW/HW -} else { - set hardware /HARDWARE -} set scriptDir [getScriptDirectory] +#set top_design_name sysc::tgfs::core_complex set top_design_name core_complex set clocks clk_i set resets rst_i @@ -38,13 +35,13 @@ foreach clock ${clocks} { foreach reset ${resets} { ::pct::set_block_port_protocol --set-category SYSTEM_LIBRARY:$block/${reset} SYSTEM_LIBRARY:RESET } -::pct::set_encap_port_array_size SYSTEM_LIBRARY:$block/local_irq_i 16 +#::pct::set_encap_port_array_size SYSTEM_LIBRARY:$block/local_irq_i 16 # Set compile settings and look set block SYSTEM_LIBRARY:${top_design_name} -::pct::set_encap_build_script $block/${top_design_name} $scriptDir/build.tcl +::pct::set_encap_build_script $block/sysc::tgfs::${top_design_name} $scriptDir/build.tcl ::pct::set_background_color_rgb $block 255 255 255 255 -::pct::create_instance SYSTEM_LIBRARY:${top_design_name} ${hardware} ${model_prefix}${top_design_name}${model_postfix} ${top_design_name} +::pct::create_instance SYSTEM_LIBRARY:${top_design_name} ${hardware} ${model_prefix}${top_design_name}${model_postfix} sysc::tgfs::${top_design_name} sysc::tgfs::${top_design_name}() # export the result as component ::pct::export_system_library ${top_design_name} ${top_design_name}.xml diff --git a/contrib/tgc_import_tb.pct b/contrib/tgc_import_tb.pct new file mode 100644 index 0000000..f1b3fb8 --- /dev/null +++ b/contrib/tgc_import_tb.pct @@ -0,0 +1,29 @@ +source tgc_import.tcl + +::paultra::add_hw_instance GenericIPlib:Memory_Generic -inst_name i_Memory_Generic +::paultra::add_hw_instance Bus:Bus -inst_name i_Bus +::BLWizard::generateFramework i_Bus SBLTLM2FT * {} \ + { common_configuration:BackBone:/advanced/num_resources_per_target:1 } +::pct::create_connection C i_core_complex/initiator i_Bus/i_core_complex_initiator +::pct::set_location_on_owner i_Bus/i_core_complex_initiator 10 +::pct::create_connection C_1 i_Bus/i_Memory_Generic_MEM i_Memory_Generic/MEM + +#::pct::set_main_configuration Default {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::INFO).coloredOutput(false).logAsync(false));} {} {} {}} +#::pct::set_main_configuration Debug {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::DEBUG).coloredOutput(false).logAsync(false));} {} {} {}} +::pct::create_simulation_build_config Debug +::pct::set_simulation_build_project_setting Debug "Main Configuration" Default +# add build settings and save design for next steps +#::pct::set_simulation_build_project_setting "Debug" "Linker Flags" "-Wl,-z,muldefs ${currentDir}/model/i_${Ncore_top_name}/Vgen_wrapper__ALL.a $::env(VERILATOR_ROOT)/include/verilated.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_sc.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_c.cpp" +#::pct::set_simulation_build_project_setting "Debug" "Include Paths" $::env(VERILATOR_ROOT)/include/ + +#::simulation::set_simulation_property Simulation [list run_for_duration:200ns results_dir:results/test_0 "TLM Port Trace:true"] +#::simulation::run_simulation Simulation + +#::pct::set_simulation_build_project_setting Debug {Export Type} {STATIC NETLIST} +#::pct::set_simulation_build_project_setting Debug {Encapsulated Netlist} false +#::pct::export_system "export" +#::cd "export" +#::scsh::open-project +#::scsh::build +#::scsh::elab sim +::pct::save_system testbench.xml From 54f75f92ea08cca648427c4077b3be72fbfbe213 Mon Sep 17 00:00:00 2001 From: Rocco Jonack Date: Mon, 24 Apr 2023 08:44:12 -0700 Subject: [PATCH 076/184] improved testbench import; added prebuild FW for testing --- contrib/hello.elf | Bin 0 -> 29716 bytes contrib/tgc_import.tcl | 1 + contrib/tgc_import_tb.pct | 29 ------------------ contrib/tgc_import_tb.tcl | 61 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 29 deletions(-) create mode 100755 contrib/hello.elf delete mode 100644 contrib/tgc_import_tb.pct create mode 100644 contrib/tgc_import_tb.tcl diff --git a/contrib/hello.elf b/contrib/hello.elf new file mode 100755 index 0000000000000000000000000000000000000000..9b63df72a75d994b5d4fdb0d8ea230a51171fbb3 GIT binary patch literal 29716 zcmeHw4Rl<^m1e!aey#tO+qNWZaN8|evauzBJTXZ~(hdTf88$cxNtlh3cB|Ev6!aIV zWniMuKi0h z+H}H>N}|KpuU6pF6z6e@1nko`Y!6bsPCe_ zJKPZ2^hQHyQ#fEiuj75gp=Fznt%07mnxn&CGg~u}Ey7y8Uu0IF5Y`&Q$gJ67Ske7P zCVIlK>J2kfzs0l~_M4f86Q;G+urh16SXSeHE7N$wvYHG#)3n95*6p`5>rU9#dc(=A z-{M#o?{_j6pKz=VMj*3cOTgN=KakmYB49NeZl-yQYqjimGc6}v_$@drBCVdEW}|DX z;fMWZ*fy+a^8+(kHw3>;&B^E5sks3$YGxV_%w-xT&_Av?8;V_(b( zN2QJ7>1o+7*?V2%n7c|GoqkKSbxn(7u87I!mIq!!{v(?v*#Y z^94R<9q8cq%?$bt<3q-Y%{Yl}cyuPZeqtutbb2Pb_T?EZ*FrnTTtgh)GcA(0!*)j) zVJ9a0D7w~`F_Jw}V}!@ZXG%WC&Qa*jI6~~qChu}h;*Pnt(DmQh-zY#yrhY>#-#&K~_D45N%~*(q zOyk7NnGTPCJ#p>C%}So8shLc}fmy4;p2ax7h2t;N;N>ZC>faE~9zY&yv}ehu^4F+Q z$hUp3f<3wj$$Ce}rgWZ=e$3QwIj1kPW5#~=P4bXyhMf>&{g+{fd1=)z!_)zE#;oS^ z@=viZ3vwgLV;;do%Ozn87}mV@koof-T3qa<~im9lCq{Uz{@+ z=*;{S4r~`kFlS@Fe?$61#46Eea;}hlAjB%fP(fYz>Zf7MJ=wsd5f0#qIX%pIeKP*| zv6IM`2i*wb=^p{VM*Xw79Pj+{tk_hu6@0EkI?&Lh}D9Vuw=2D#_5%aU0FRg|N#HlEw{>cMwkogdKE5P>X?+pBY z<{1~`9_gB8UVTZ z5aaaMGA7hKwaA>EpMNNWYlCD^<-@ES5y|D#f;g-d@XXC&=bk^1BaW!NdOGtk{P^%z zVSN+1@|!1x^`L8H9^7hJ4~-eorlqsd_4aIZ1Lm7%%r_C_{xzpD2fjR)dG4eUUCwoi zJsS?3G8hkGCjwjUe-$>*+%6`@)=2FI{w zI#Q3h!ks^gbz1a4y!w{a2);)9&166N2>ez<`qGxw3l&)<%9>J--I z!u&=BpOf=kcgQE!9nm#de>B;$4&yYs=Hx+JaNb-mTbwAtsWeHvBg+d*&&Zu`?@WNq+hxM{+ zgRfofgD3C*PjdXN~KAC8wx7Ph+q zIpiGe!hShl$@Y;K5cg<*3~LImj}CB-oXrNP1N1_ydO94!+VfFa7yh>(17*2S34_Ns z_e!0z4(3#Rs1oK6Ho))8pzr*#nph;tbAz?j824kJ4BJ=-!d}{n@o=H_&Hba9#)Br- zhBCK>9UJSJYhRaj8&%!S^|45JZ0p@&yZ!Dq`{fwUp`^UKIKsG}rEIAa%!!H&x_33 zZK0#Dd>?bg^Py~@Muck`MfA^~lX*S*z%kk9UTk9h`bn%~6Y$}e4fGX#DbL$b#yR6^ zoVi_ML^o`~c;1h*q^}#{GQ`fE_?3r5=7AHV;k! z^A6E=;DAVev4nn>V*-9Q;b#-)f`+vo=ZWjL7}mvxfpbA&;mi%^g2LJ;`$3+^B}Yrm z+A z2;T-@VZ6ycEf1Jk^jq?#?}_B~$0dLEUex*0_vR=s`O1^x=)osrZK`#}A@MkG6 zAmwFmm3z&1sYlnSi8j9$OKy8a9CaRv!G_=Psd!fXhBWdJPCkv;yT;+ZV_MfG@0shJ zIr1TQz10So{8uHC>4Bl1L~o>LIMUEriY1%4vcEGjuq%?fF_j!i_YCwCmmW$Cl9(JA zN=0@JrM?_Vq$3TzBav-4$vV81ZXX)xO7um#6T_(7lTLL;_VlE?Bguiz)Q3QCy-|p! z{*m6^bwa#7JwIRn&is5ieti0Wr#u>Q-6+52!D&24-^b4{>tAZQ_3iojZNE`=$BOLF z=?orS9tZEk9zSu{d9*`5+$ofo!q2>{n?5CseTK23!o3j?nhgdK8*cDG&HbLn8K2pXkj zTd%m{Ly@MfpZLtW$R(FFU((zvroiP0TQuW|m$>g%R`9`j8b1_PnJCK3M7hc=W0^NY zI3UF$R>-i-lAtgw!*@4J>>`XIF&eL^#dq7QmB%mS*F364a{75xIj}&EuXWI1*jq5~ zcd?thd%4x8-G^v*d11?{h5ujfexEJW+4B5HAHO%}!n*%*Fn-M)TBLe@8Xd`=zmh?` zSj5{=P<|i3z4$$VpNxEG1xiBR{u>I$izK{)o8>G+NIY)DB6Us`+_h8~PMI1Ej%f)F z3MVW~+X4>Ie1DeOFp&xEy>*i2_ZSG>cLYBD1v8|SI1QH zai<0)cv2FFB~8a_+%PsF^lADI8nBq@0h%7f(4hG%@GNja@Rz`%B7Ss%`AL*4`oaD& zZ*+$9uYt224w4BIgQN`h`ZR$?)^ge)v9+Flcv_CM#m@_^;RW)p^1RyOd2=J4#D5G= zderjpD?OOD6JO?el;t+B%-*Q;==4o}t`!%p0CFyb6nZY;Np;i^aLO%P;=>*s0-c@? z04DzuJSm<0)NVztzAf>2I4Joq0-c&IvC1TU8MI-&C0@N{R=|_1^jYS$PdYsZvn4$* zSGDiKpi-NqmMg8&5n1l@NsZ4Z7y8O&Ufl{G@1EN$Jp5i*So{UDwP(7i> z#CpKg^fC`$>OH+N0?nwQizjOp_kYOKwi312YN=-lYeOSIlzjmpJ{e;wn$#%WfLhd> zv8r_-%-*6eF9N^z=}JhekX(*cDRrvwq&l7y1F@l`NnKT4+&Pk@|8Q5fs4TD?^{6v# zVk0xD|26BzJUVo)=0d;ueT(Y)a>Z`=$noi>>}WZEoAq9hLE zX6)uoCJyEdi`hda4(l{QCJsv`j-Lf%ks6sG*bQFiKwU?6OBjm5LFgtGJT!@>RV#Ba zER>0K8BMM9f`;Xbl~Jgx0%MKG%b`oU4u~r7(IFvUU7b+ty*drjaW_f6l^!4UD7Q)$ zga;id6Yvl$eeYF=cBEQu-3OUmHb?F(Haha z(z%|XwQcITxR;gzjo!}ZRfYj;S9sF7PM~zXmRlpOFGHGW0+t>Hx2K^Ch`dXzeNr>l zrAF&LnL#h_S3*^7 zFbUE#c$Xyc9Q>-D)Ys$ED_T-6L|^d9^i9pHtzfPNO5$wF7PSRzS-}eLX<`jaY^fD0 z;9d(oC|&DYn$urS5(AqCJ*Fk!_ug3KgYOCa0KTw*m??}-SW3oN9?*A*r%Va<$4C^au zq^VUNr>Rys?sW9&oCIdXqUvSIgDFi$25JC{GNTADPo-FnL?vFvH8_yZcO&7x_cVVw zk~4p5n!f=h!5jBY+m|Cp*L!n~QXXwmD|MIV6ksGC9BBDk%n`p!%W1aE8(U7Z<%wKF z+V%OS{c60YGM?HCRXrC*2FgOCQ~)g^P03j(O=-1I^M#y#jKA!&QMt6axus)xuqD;M zTMVZYL+R#Ei&TGlXfK}Ksovg!=A>xp9_UN8fI8eVlo}iuZnGa-3YqiAr9vGy--b8xWz);^p34J&>Rqe*RQ#US@Lb~>XPoI{-A-HfC_+d<9s0)IJ z(?GERpB4P8+_RC6f&@O21O2;tx)fgYjr4Z*v>~uMdv@c#TBZ>L1DoShUa`n`WGM)! zh3HYugv29^w{hd)Z>6CzAnC>qK+0HgR%+K<6ZQW-i%H73B(78fB+yowu?Z6u%@Fm4?10NxK77vrF zTdQ^H)kGP={dnMOUubFbFV;%_5(?N)Ijr{|@hct2txS}E5)WgEL^qkS2(iZa&vD1M zRYENPGD_y*UQuxy2|>w6lLjSUWe;#+iZl=JkQGW*h3=};V7eTHP!D*@$`lX(6FQGt z%2ibmUnyP1Q!lz|0`0F12=R~Lcpt8^&gm-aO~^KT>hQH2^pkF@Qf{+0lk(aHcaUPc z^q$4dxAkm|L@7^N^rWpkX-$J{U%oU+)(^7$sbzn}@)amM*&0qop0`8Xyaivtt@;D( z?UIULqg*0N>H5G^4q4gb&Px)#`?ZBu$j=B<9V!lc0ZCV;xzdqeL(UWO!*S zg})w{z&3s*u*UeZA>fU_3v2?0jK=t_K)8nhmIE~Lk9gT-NUIf}w_Vjs z#`xpF1@0wbH3?v}Q-et{(WanoQQi;YU$vvcqo5n(|AQ57B<>=%Ny%jw0DPc|4NV4O zk?SO10F9dyAUqiU1`v)lD8#5({sb__pR|(qZ6_Atz%s@k1FzjL{$!hyc#T;H#8;}7 z=AC8*p^FrBz4;fAaLA+eR;2p|Mb?A5%|8R}J`dVq{uIzxJ!pH)Ca6ZYj8ieX=Dvs$ zxl_2E9!=uE>fvEW?dPfPfrxsLse@ep{791RM( z-X0R0FHz;|>|J8>Wvaa0{<7HoF;%|CJcAmsa=HobbZ@s~k=IbJzzin#Rw{J25Oob` z#%QV7fyNJjZj6thaT_^Jw5(L3dhvHGNMK&$-Qt34sN{OtHJ77WL{?kDv}Hs~zYFMf z48H9WyYjyiTeh4|;gD>SSaA?orZ_Ck1^#LSDJ}_26a}6q&EVM(L_L+_%q>vSy14d( ztoz&2opo(pf_(NO=`Ntgtv6Q9D^zhQdtXG{GJfT4GIqV^)5=~7xCR|;|%nZJD)E!va8f}WH^$5KPbAQ}PEW{~W)-6TA^p3jnzM&rmiXE_rBuuv z6kn_*!RW9~gF9ZOxUO@P-C}2m78`$9CsX3irG(u6kv@^A{)&{CaQtvIsOZk zaIZ1`S-{d`P4)Dcb@;`brOTRPtZ5y7{$`tYu8Y!6>+tEDO&YrH5{9pJ_|(lNZCm$Y z>Tex>=4O)yth-8qPu*w&9XP8~1L)%=N9v$oM+v$jRoyeI_* zqq^cX3}LmjT4tjyba(YC#k0fwduUX>UPaIK);9r#OHZH`&Nr*@#!t8}%BW=;P%>D* zyjs;qCXaxbnd7gKBaF{f3&BI6`a`Jsr}(vin&0UCkUT#G507geHD(K#jA{|8sWz5W zS(Pg)8!Gu-Hr3^j$_!GGO`&=LMHoIa^L9Z$*0Tx?$Df;^wlv&h zz?&Reg759MM?8Y7TcowCZD}qIDlOJp*<9wKm2AH?^a#A5#jmbttkZ^)R3Q!Wt5mtL zE2{Ec5mJ3n?N>vou*8pQtQ#}x6h6#3XKAy@ca>`YraB>(`Rn-AS}rw~5mRhTjq(hY zuWio7m9C7vfxoJ5irg3Yb;wJl9xE0n?E`6LzKy~<1wCKb&sK5#*tt%07J4_3_pXj` zzgyU<@??n$mIWc8ZKsiCG6ub&#ttG$LZ64|vRvMx zGb;__>M-40wHo8LrL4$J3!*^UBYl7ow%TR-qZlVY=vI5EfNaV?4&8-L59XbIuH2_> zEu*ak*)KotG3s?t6!nMB5}s1NMD1Y~$zZwAMiQgFZr(VrQn1i3C8hafSB<%UK|HJ8 z#NT15WV!l)sU26&6o|x~(=%@rd!@2~l8gg8vDDhQX-i}@tw ze6TE^1NO;TWVy7q?86|bzO9iR=|j{ON2NdH>b&aS%y za3OsJHB|ixQyqI2(l=sdq3HT}rI7x;fTrtRex$V+;TI8uC{lh(7{rKZFvgLqecVbBF(tiyn*uWK+Z1z6bj%@5p z3?;iiB0uXU(9!dep5DQ>OHoet;m_N8Khl@#O!V&soF3^mI$fsu~hlt(6ZC^d|?MxrZ~jwc64;{2mK38Z`aQbY0GiQbWvXCTg; zU}1cCxaX!63ap`+WSx=WRPGg25--AT7#1UVqZa2ICee`?>5LC0(kVf#{=VeiBoyqUXr)cZ-oeE1u;@!AhDU}{c`X%7?|^_~(g|Hry>#&u z$Ge(7Px}vSqVjQ`)efb04X1i_H8!N%mSw8gy=!OyZ-nBzpuYU8#JGGf=*hYaqLL#+ zL%{Jh+eioSe7l7k-fU?=y|IGc!^4TL9G0)DgyiF!DEy^kXG)|8RK?DoE)WN~k@f_t z_fKNCdSWLWk9Ump^rn0IVPU)%@7P3dVmKY=COOfY-qoAv5}k>3LJT4{&~SWkD3$CP z=AT!hzu4b{BWW3gc!H6yvsy*3tQU`W^^YWTayt^}6Hkp{PY)eWaqI{?QbVlW&$CC! z<`BTUt*&9=F~?;~j4%9oCbmRU1b32qdOFhp6P?NYOR)t5Qocmp2!%GL2L^hfaZi5> zE$`$DwvGL%J$T2q5fRgsx^&U^l5z~S$kF4yj`Lo;iE`wFd0ZC%auLV+^? zTes~uZa3S@gTlP-MEg_aW@|e#isoxV&KyUb_R2_}Z&dO{$X6^s0^XhYO`u*Ap6!*P z_S+3gzYd~9tRgnxw-dkD!LuDt@NB0JcUxJToSjm9sQpLnKbHIv@a)7-pQq<#UXzol zd3NB;{Q!8Ouh*_Q2qvj3ZQ6<7&%ncX3GJ1!oK4olhHN#47B!!K2Z8o-d^dW!(GJ>2 zdHS^qjt=Go6bhLm^ zIY;tA-9@fggh=EjN#puX!RRDhP5AF<@M+;6UT@cG*p@K=e=#grIC1i>Q9dp8e~)2t zls8LYiH55;2V+Ub>oQHp63lm5qSObmK6haG%aT#(hp|NSU6x>W$X}MI$^$4_B2)z9 z49s^~Vu|Mwg|x-5=KUHHri2Moxgh%+KTe{Cq|1hxsQ8e)ulH`p_2NV~TqK z?+l7j>Jfr{4+7Ttn)IW95eD)KLEqzmbzUa@Z+-l00KW)$AC7Uip~e!^6t4i*a~=8L z0Ia`(AUqGa8~$OuRiphS81heq)mnq}dgf_Eef~l?4n94f5pD+k`lagCEn$8KvJ>@p zuzkSW08c=lkf+b5D9?NENBR!H%m=Fdp!{Z$e|yTehNSNUUBtA1N(5h901@GxqjMDS zKD5uZ5&7={+?kW-if;hc`!)LGJAhv|)q02gPXN|)7X9}Fz&eML{ybpn$M!<#h?fC3 zp}ubK9{}ro83F$kV7)$KeV)~8`GoPst2|~uKz*T4Enq$GlirE?A^2}8>45ox#ZI3+ zF9DBhl(!J_EB@xIK)nH~=gXIRw0Aiw5dH}0Z==6j z2}8fD0PA?8e{x?adf)KnwnM)Ci{5SVslN~OHfIaAQ+oG@KOD|)-1MhI9iU9J$9+Zbu?W6k4 zFW%KV(2?l%5Un636TKRgtP~kf3=JjrV&B#Y1|LFhGl8Pp3V5(pT7dH*biG10h1HuX zY@w8Dg99)#HB^sw3O0sdPu>vc4q8*ZU82XA+d+=tlbYe4Ho42zJyWo0)-5Tw#rZ)< z92>%pq|Y$lNrT?0c|3W4pwju$0ytgl%=)f~Qq@LZn#8?o`2twS4 z2Bi4rR5#8j5;#C;?oIUKyhk*5=ALN28KzJaIvsWRxBJcbigl=`VrTIPxh}HRH9_?jf^j%u?7T`1=ilgV^yV~PJTIDq=AP@6P?$YgE3rr9{^6B~K zo*Y-+4(@|ApI%2xgvYD(<2n+u2DJ$47tsKonvd&AmbIC8p|GTgk92;VrR$LVRq(CB zd9=PX?N%WC@{V62#7%U%cag^5-QLqfiw|8TM4NB} {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::INFO).coloredOutput(false).logAsync(false));} {} {} {}} -#::pct::set_main_configuration Debug {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::DEBUG).coloredOutput(false).logAsync(false));} {} {} {}} -::pct::create_simulation_build_config Debug -::pct::set_simulation_build_project_setting Debug "Main Configuration" Default -# add build settings and save design for next steps -#::pct::set_simulation_build_project_setting "Debug" "Linker Flags" "-Wl,-z,muldefs ${currentDir}/model/i_${Ncore_top_name}/Vgen_wrapper__ALL.a $::env(VERILATOR_ROOT)/include/verilated.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_sc.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_c.cpp" -#::pct::set_simulation_build_project_setting "Debug" "Include Paths" $::env(VERILATOR_ROOT)/include/ - -#::simulation::set_simulation_property Simulation [list run_for_duration:200ns results_dir:results/test_0 "TLM Port Trace:true"] -#::simulation::run_simulation Simulation - -#::pct::set_simulation_build_project_setting Debug {Export Type} {STATIC NETLIST} -#::pct::set_simulation_build_project_setting Debug {Encapsulated Netlist} false -#::pct::export_system "export" -#::cd "export" -#::scsh::open-project -#::scsh::build -#::scsh::elab sim -::pct::save_system testbench.xml diff --git a/contrib/tgc_import_tb.tcl b/contrib/tgc_import_tb.tcl new file mode 100644 index 0000000..9df24aa --- /dev/null +++ b/contrib/tgc_import_tb.tcl @@ -0,0 +1,61 @@ +source tgc_import.tcl +set hardware /HARDWARE/HW/HW +set FW_name ${scriptDir}/hello.elf + +puts "instantiate testbench elements" +::paultra::add_hw_instance GenericIPlib:Memory_Generic -inst_name i_Memory_Generic +::pct::set_bounds i_Memory_Generic 1000 300 100 100 +::paultra::add_hw_instance Bus:Bus -inst_name i_Bus +::BLWizard::generateFramework i_Bus SBLTLM2FT * {} \ + { common_configuration:BackBone:/advanced/num_resources_per_target:1 } +::pct::set_bounds i_Bus 700 300 100 400 +::pct::create_connection C_init i_core_complex/initiator i_Bus/i_core_complex_initiator +::pct::set_location_on_owner i_Bus/i_core_complex_initiator 10 +::pct::create_connection C_targ i_Bus/i_Memory_Generic_MEM i_Memory_Generic/MEM + +puts "instantiating clock manager" +set clock "Clk" +::hw::create_hw_instance "" GenericIPlib:ClockGenerator ${clock}_clock +::pct::set_bounds ${clock}_clock 100 100 100 100 +::pct::set_param_value $hardware/${clock}_clock {Constructor Arguments} period 1000 +::pct::set_param_value $hardware/${clock}_clock {Constructor Arguments} period_unit sc_core::SC_PS + +puts "instantiating reset manager" +set reset "Rst" + ::hw::create_hw_instance "" GenericIPlib:ResetGenerator ${reset}_reset + ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} start_time 1000 + ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} start_time_unit sc_core::SC_PS + ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} duration 10000 + ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} duration_unit sc_core::SC_PS +# ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} active_level true +::pct::set_bounds ${reset}_reset 300 100 100 100 + +puts "connecting reset/clock" +::pct::create_connection C_clk . Clk_clock/CLK i_core_complex/clk_i +::pct::add_ports_to_connection C_clk i_Bus/Clk +::pct::create_connection C_rst . Rst_reset/RST i_core_complex/rst_i +::pct::add_ports_to_connection C_rst i_Bus/Rst + +puts "setting parameters for DBT-RISE-TGC/Bus and memory components" +::pct::set_param_value $hardware/i_core_complex {Scml Properties} elf_file ${FW_name} +::pct::set_address i_core_complex/initiator:i_Memory_Generic/MEM 0x0 + +#::pct::set_main_configuration Default {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::INFO).coloredOutput(false).logAsync(false));} {} {} {}} +#::pct::set_main_configuration Debug {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::DEBUG).coloredOutput(false).logAsync(false));} {} {} {}} +#::pct::create_simulation_build_config Debug +#::pct::set_simulation_build_project_setting Debug "Main Configuration" Default +# add build settings and save design for next steps +#::pct::set_simulation_build_project_setting "Debug" "Linker Flags" "-Wl,-z,muldefs $::env(VERILATOR_ROOT)/include/verilated.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_sc.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_c.cpp" +#::pct::set_simulation_build_project_setting "Debug" "Include Paths" $::env(VERILATOR_ROOT)/include/ + +#::simulation::set_simulation_property Simulation [list run_for_duration:200ns results_dir:results/test_0 "TLM Port Trace:true"] +#::simulation::run_simulation Simulation + +#::pct::set_simulation_build_project_setting Debug {Export Type} {STATIC NETLIST} +#::pct::set_simulation_build_project_setting Debug {Encapsulated Netlist} false +#::pct::export_system "export" +#::cd "export" +#::scsh::open-project +#::scsh::build +#::scsh::elab sim +::pct::save_system testbench.xml From 00b0f101ac92c3c125957ab94449efd4c742b94e Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 22 Apr 2023 17:04:41 +0200 Subject: [PATCH 077/184] adapts to changes of instrumentation interface in dbt-rise-core --- gen_input/templates/interp/CORENAME.cpp.gtl | 4 +- src/iss/arch/riscv_hart_m_p.h | 6 ++- src/iss/arch/riscv_hart_msu_vp.h | 6 ++- src/iss/arch/riscv_hart_mu_p.h | 6 ++- src/iss/plugin/cycle_estimate.cpp | 12 +++--- src/iss/plugin/cycle_estimate.h | 4 +- src/iss/plugin/instruction_count.cpp | 4 +- src/iss/plugin/instruction_count.h | 4 +- src/iss/plugin/pctrace.cpp | 44 ++++++++++++++++++--- src/iss/plugin/pctrace.h | 4 +- src/vm/interp/vm_tgc_c.cpp | 32 +++++++-------- 11 files changed, 83 insertions(+), 43 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 7a3f88f..7b26430 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -146,18 +146,17 @@ protected: inline void process_spawn_blocks() { if(spawn_blocks.size()==0) return; - std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken); for(auto it = std::begin(spawn_blocks); it!=std::end(spawn_blocks);) if(*it){ (*it)(); ++it; } else spawn_blocks.erase(it); - std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken); } <%functions.each{ it.eachLine { %> ${it}<%}%> <%}%> + private: /**************************************************************************** * start opcode definitions @@ -263,6 +262,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' auto inst_id = decode_inst_id(instr); // pre execution stuff + this->core.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> case arch::traits::opcode_e::${instr.name}: { diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 5967c29..74e20c0 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021 MINRES Technologies GmbH + * Copyright (C) 2019 - 2023 MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -316,7 +316,9 @@ protected: uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } - void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; + void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; + + bool is_branch_taken() override { return arch.last_branch; }; riscv_hart_m_p &arch; }; diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index 54e93fd..f09ea99 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017, 2018, 2021 MINRES Technologies GmbH + * Copyright (C) 2017 - 2023 MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -340,7 +340,9 @@ protected: uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } - virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; + void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; + + bool is_branch_taken() override { return arch.last_branch; }; riscv_hart_msu_vp &arch; }; diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index fc2f16e..040999d 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2021 MINRES Technologies GmbH + * Copyright (C) 2017 - 2023 MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -340,7 +340,9 @@ protected: uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } - void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; + void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; + + bool is_branch_taken() override { return arch.last_branch; }; riscv_hart_mu_p &arch; }; diff --git a/src/iss/plugin/cycle_estimate.cpp b/src/iss/plugin/cycle_estimate.cpp index 3174f30..77d4c5b 100644 --- a/src/iss/plugin/cycle_estimate.cpp +++ b/src/iss/plugin/cycle_estimate.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017, MINRES Technologies GmbH + * Copyright (C) 2017 - 2023, MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -107,12 +107,12 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& } -void iss::plugin::cycle_estimate::callback(instr_info_t instr_info, exec_info const& exc_info) { +void iss::plugin::cycle_estimate::callback(instr_info_t instr_info) { assert(instr_if && "No instrumentation interface available but callback executed"); auto entry = delays[instr_info.instr_id]; - bool taken = exc_info.branch_taken; - if (exc_info.branch_taken && (entry.taken > 1)) - instr_if->set_curr_instr_cycles(entry.taken); + bool taken = instr_if->is_branch_taken(); + if (taken && (entry.taken > 1)) + instr_if->update_last_instr_cycles(entry.taken); else if (entry.not_taken > 1) - instr_if->set_curr_instr_cycles(entry.not_taken); + instr_if->update_last_instr_cycles(entry.not_taken); } diff --git a/src/iss/plugin/cycle_estimate.h b/src/iss/plugin/cycle_estimate.h index f35f106..079a805 100644 --- a/src/iss/plugin/cycle_estimate.h +++ b/src/iss/plugin/cycle_estimate.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017, 2018, MINRES Technologies GmbH + * Copyright (C) 2017 - 2023, MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -78,7 +78,7 @@ public: sync_type get_sync() override { return POST_SYNC; }; - void callback(instr_info_t instr_info, exec_info const&) override; + void callback(instr_info_t instr_info) override; private: iss::instrumentation_if *instr_if; diff --git a/src/iss/plugin/instruction_count.cpp b/src/iss/plugin/instruction_count.cpp index 0b54e21..7613b27 100644 --- a/src/iss/plugin/instruction_count.cpp +++ b/src/iss/plugin/instruction_count.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017, MINRES Technologies GmbH + * Copyright (C) 2017 - 2023 MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -90,6 +90,6 @@ bool iss::plugin::instruction_count::registration(const char* const version, vm_ return true; } -void iss::plugin::instruction_count::callback(instr_info_t instr_info, exec_info const&) { +void iss::plugin::instruction_count::callback(instr_info_t instr_info) { rep_counts[instr_info.instr_id]++; } diff --git a/src/iss/plugin/instruction_count.h b/src/iss/plugin/instruction_count.h index 6e90cf6..94504cf 100644 --- a/src/iss/plugin/instruction_count.h +++ b/src/iss/plugin/instruction_count.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017, 2018, MINRES Technologies GmbH + * Copyright (C) 2017 - 2023, MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,7 +69,7 @@ public: sync_type get_sync() override { return POST_SYNC; }; - void callback(instr_info_t, exec_info const&) override; + void callback(instr_info_t) override; private: Json::Value root; diff --git a/src/iss/plugin/pctrace.cpp b/src/iss/plugin/pctrace.cpp index df2225a..ea20702 100644 --- a/src/iss/plugin/pctrace.cpp +++ b/src/iss/plugin/pctrace.cpp @@ -1,3 +1,37 @@ +/******************************************************************************* + * Copyright (C) 2017 - 2023, 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: + * alex.com - initial implementation + ******************************************************************************/ + #include #include #include @@ -152,22 +186,22 @@ bool pctrace::registration(const char *const version, vm_if& vm) { return true; } -void pctrace::callback(instr_info_t iinfo, const exec_info& einfo) { +void pctrace::callback(instr_info_t iinfo) { auto delay = 0; size_t id = iinfo.instr_id; auto entry = delays[id]; auto instr = instr_if->get_instr_word(); auto call = id==65 || id ==86 || ((id==2 || id==3) && bit_sub<7,5>(instr)!=0) ;//not taking care of tail calls (jalr with loading x6) - bool taken = einfo.branch_taken; + bool taken = instr_if->is_branch_taken(); bool compressed = (instr&0x3)!=0x3; - if (einfo.branch_taken) { + if (taken) { delay = entry.taken; if(entry.taken > 1) - instr_if->set_curr_instr_cycles(entry.taken); + instr_if->update_last_instr_cycles(entry.taken); } else { delay = entry.not_taken; if (entry.not_taken > 1) - instr_if->set_curr_instr_cycles(entry.not_taken); + instr_if->update_last_instr_cycles(entry.not_taken); } #ifndef WITH_LZ4 output<get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; diff --git a/src/iss/plugin/pctrace.h b/src/iss/plugin/pctrace.h index ff3153c..092719d 100644 --- a/src/iss/plugin/pctrace.h +++ b/src/iss/plugin/pctrace.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017, 2018, MINRES Technologies GmbH + * Copyright (C) 2017 - 2023, MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -83,7 +83,7 @@ public: sync_type get_sync() override { return POST_SYNC; }; - void callback(instr_info_t, exec_info const&) override; + void callback(instr_info_t) override; private: iss::instrumentation_if *instr_if {nullptr}; diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index eaef390..3e54a25 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -140,16 +140,15 @@ protected: inline void process_spawn_blocks() { if(spawn_blocks.size()==0) return; - std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken); for(auto it = std::begin(spawn_blocks); it!=std::end(spawn_blocks);) if(*it){ (*it)(); ++it; } else spawn_blocks.erase(it); - std::swap(super::ex_info.branch_taken, super::ex_info.hw_branch_taken); } + private: /**************************************************************************** * start opcode definitions @@ -341,6 +340,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' auto inst_id = decode_inst_id(instr); // pre execution stuff + this->core.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); switch(inst_id){ case arch::traits::opcode_e::LUI: { @@ -422,7 +422,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *(X+rd) = *PC + 4; } *NEXT_PC = *PC + (int32_t)sext<21>(imm); - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } } } @@ -457,7 +457,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *(X+rd) = *PC + 4; } *NEXT_PC = new_pc & ~ 0x1; - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } } } @@ -489,7 +489,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } } } @@ -522,7 +522,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } } } @@ -555,7 +555,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } } } @@ -588,7 +588,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } } } @@ -621,7 +621,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } } } @@ -654,7 +654,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } } } @@ -2097,7 +2097,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { *(X+1) = *PC + 2; *NEXT_PC = *PC + (int16_t)sext<12>(imm); - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } TRAP_CJAL:break; }// @suppress("No break at end of case") @@ -2342,7 +2342,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { *NEXT_PC = *PC + (int16_t)sext<12>(imm); - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } TRAP_CJ:break; }// @suppress("No break at end of case") @@ -2363,7 +2363,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { if(*(X+rs1 + 8) == 0) { *NEXT_PC = *PC + (int16_t)sext<9>(imm); - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } } TRAP_CBEQZ:break; @@ -2385,7 +2385,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { if(*(X+rs1 + 8) != 0) { *NEXT_PC = *PC + (int16_t)sext<9>(imm); - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } } TRAP_CBNEZ:break; @@ -2485,7 +2485,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { if(rs1 && rs1 < traits::RFS) { *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } else { raise(0, 2); @@ -2553,7 +2553,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t new_pc = *(X+rs1); *(X+1) = *PC + 2; *NEXT_PC = new_pc & ~ 0x1; - super::ex_info.branch_taken=true; + this->core.last_branch = 1; } } TRAP_CJALR:break; From 1672b01e62d6ba23fb51409e1f545f20563f3506 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 27 Apr 2023 12:20:30 +0200 Subject: [PATCH 078/184] adds WT cache functionality as mixin --- src/iss/arch/riscv_hart_m_p.h | 19 +++- src/iss/arch/riscv_hart_msu_vp.h | 12 +-- src/iss/arch/riscv_hart_mu_p.h | 24 ++++- src/iss/arch/wt_cache.h | 172 +++++++++++++++++++++++++++++++ 4 files changed, 215 insertions(+), 12 deletions(-) create mode 100644 src/iss/arch/wt_cache.h diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 74e20c0..2a39f83 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -422,6 +422,15 @@ protected: feature_config cfg; unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; inline bool debug_mode_active() {return this->reg.PRIV&0x4;} + std::pair, std::function> + replace_mem_access(std::function rd, std::function wr){ + std::pair, std::function> ret{hart_mem_rd_delegate, hart_mem_wr_delegate}; + hart_mem_rd_delegate = rd; + hart_mem_wr_delegate = wr; + return ret; + } + std::function hart_mem_rd_delegate; + std::function hart_mem_wr_delegate; }; template @@ -543,6 +552,12 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; } + hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { + return this->read_mem(a, l, d); + }; + hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { + return this->write_mem(a, l, d); + }; } template std::pair riscv_hart_m_p::load_file(std::string name, int type) { @@ -663,9 +678,9 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce auto idx = std::distance(std::begin(memfn_range), it); res = memfn_read[idx](phys_addr, length, data); } else - res = read_mem( phys_addr, length, data); + res = hart_mem_rd_delegate( phys_addr, length, data); } else { - res = read_mem( phys_addr, length, data); + res = hart_mem_rd_delegate( phys_addr, length, data); } if (unlikely(res != iss::Ok)){ this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index f09ea99..5936329 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -845,7 +845,7 @@ template iss::status riscv_hart_msu_vp::write_reg(unsigned return iss::Ok; } -template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_cycle(unsigned addr, reg_t &val) { auto cycle_val = this->icount + cycle_offset; if (addr == mcycle) { val = static_cast(cycle_val); @@ -856,7 +856,7 @@ template iss::status riscv_hart_m_p::read_cycle(unsigned a return iss::Ok; } -template iss::status riscv_hart_m_p::write_cycle(unsigned addr, reg_t val) { +template iss::status riscv_hart_msu_vp::write_cycle(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { if (addr == mcycleh) return iss::Err; @@ -872,7 +872,7 @@ template iss::status riscv_hart_m_p::write_cycle(unsigned return iss::Ok; } -template iss::status riscv_hart_m_p::read_instret(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_instret(unsigned addr, reg_t &val) { if ((addr&0xff) == (minstret&0xff)) { val = static_cast(this->reg.instret); } else if ((addr&0xff) == (minstreth&0xff)) { @@ -882,7 +882,7 @@ template iss::status riscv_hart_m_p::read_instret(unsigned return iss::Ok; } -template iss::status riscv_hart_m_p::write_instret(unsigned addr, reg_t val) { +template iss::status riscv_hart_msu_vp::write_instret(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { if ((addr&0xff) == (minstreth&0xff)) return iss::Err; @@ -898,7 +898,7 @@ template iss::status riscv_hart_m_p::write_instret(unsigne return iss::Ok; } -template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_time(unsigned addr, reg_t &val) { uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052; if (addr == time) { val = static_cast(time_val); @@ -909,7 +909,7 @@ template iss::status riscv_hart_m_p::read_time(unsigned ad return iss::Ok; } -template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_tvec(unsigned addr, reg_t &val) { val = csr[addr] & ~2; return iss::Ok; } diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 040999d..06c8830 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -449,6 +449,16 @@ protected: feature_config cfg; unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; inline bool debug_mode_active() {return this->reg.PRIV&0x4;} + + std::pair, std::function> + replace_mem_access(std::function rd, std::function wr){ + std::pair, std::function> ret{hart_mem_rd_delegate, hart_mem_wr_delegate}; + hart_mem_rd_delegate = rd; + hart_mem_wr_delegate = wr; + return ret; + } + std::function hart_mem_rd_delegate; + std::function hart_mem_wr_delegate; }; template @@ -612,6 +622,12 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; } + hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { + return this->read_mem(a, l, d); + }; + hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { + return this->write_mem(a, l, d); + }; } template std::pair riscv_hart_mu_p::load_file(std::string name, int type) { @@ -829,9 +845,9 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc auto idx = std::distance(std::begin(memfn_range), it); res = memfn_read[idx](phys_addr, length, data); } else - res = read_mem( phys_addr, length, data); + res = hart_mem_rd_delegate( phys_addr, length, data); } else { - res = read_mem( phys_addr, length, data); + res = hart_mem_rd_delegate( phys_addr, length, data); } if (unlikely(res != iss::Ok)){ this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault @@ -930,9 +946,9 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac auto idx = std::distance(std::begin(memfn_range), it); res = memfn_write[idx]( phys_addr, length, data); } else - res = write_mem( phys_addr, length, data); + res = hart_mem_wr_delegate( phys_addr, length, data); } else { - res = write_mem( phys_addr, length, data); + res = hart_mem_wr_delegate( phys_addr, length, data); } if (unlikely(res != iss::Ok)) { this->trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) diff --git a/src/iss/arch/wt_cache.h b/src/iss/arch/wt_cache.h new file mode 100644 index 0000000..d5acf3c --- /dev/null +++ b/src/iss/arch/wt_cache.h @@ -0,0 +1,172 @@ +/******************************************************************************* + * Copyright (C) 2023 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 implementation + ******************************************************************************/ + +#ifndef _RISCV_HART_M_P_WT_CACHE_H +#define _RISCV_HART_M_P_WT_CACHE_H + +#include +#include +#include +#include +#include + +namespace iss { +namespace arch { +namespace cache { + +enum class state { INVALID, VALID}; +struct line { + uint64_t tag_addr{0}; + state st{state::INVALID}; + std::vector data; + line(unsigned line_sz): data(line_sz) {} +}; +struct set { + std::vector ways; + set(unsigned ways_count, line const& l): ways(ways_count, l) {} +}; +struct cache { + std::vector sets; + + cache(unsigned size, unsigned line_sz, unsigned ways) { + line const ref_line{line_sz}; + set const ref_set{ways, ref_line}; + sets.resize(size/(ways*line_sz), ref_set); + } +}; + +struct wt_policy { + bool is_cacheline_hit(cache& c ); +}; +} + +// write thru, allocate on read, direct mapped or set-associative with round-robin replacement policy +template class wt_cache : public BASE { +public: + using base_class = BASE; + using this_class = wt_cache; + using reg_t = typename BASE::reg_t; + using mem_read_f = typename BASE::mem_read_f; + using mem_write_f = typename BASE::mem_write_f; + using phys_addr_t = typename BASE::phys_addr_t; + + wt_cache(); + virtual ~wt_cache() = default; + + unsigned size{4096}; + unsigned line_sz{32}; + unsigned ways{1}; + uint64_t io_address{0xf0000000}; + uint64_t io_addr_mask{0xf0000000}; +protected: + iss::status read_cache(phys_addr_t addr, unsigned, uint8_t *const); + iss::status write_cache(phys_addr_t addr, unsigned, uint8_t const *const); + std::function cache_mem_rd_delegate; + std::function cache_mem_wr_delegate; + std::unique_ptr dcache_ptr; + std::unique_ptr icache_ptr; + size_t get_way_select() { + return 0; + } +}; + + +template +inline wt_cache::wt_cache() { + auto cb = base_class::replace_mem_access( + [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return read_cache(a, l,d);}, + [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return write_cache(a, l,d);}); + cache_mem_rd_delegate = cb.first; + cache_mem_wr_delegate = cb.second; +} + +template +iss::status iss::arch::wt_cache::read_cache(phys_addr_t a, unsigned l, uint8_t* const d) { + if(!icache_ptr) { + icache_ptr.reset(new cache::cache(size, line_sz, ways)); + dcache_ptr.reset(new cache::cache(size, line_sz, ways)); + } + if((a.val&io_addr_mask) != io_address) { + auto set_addr=(a.val&(size-1))>>util::ilog2(line_sz*ways); + auto tag_addr=a.val>>util::ilog2(line_sz); + auto& set = (a.access==access_type::FETCH?icache_ptr:dcache_ptr)->sets[set_addr]; + for(auto& cl: set.ways) { + if(cl.st==cache::state::VALID && cl.tag_addr==tag_addr) { + auto start_addr = a.val&(line_sz-1); + for(auto i = 0U; i +iss::status iss::arch::wt_cache::write_cache(phys_addr_t a, unsigned l, const uint8_t* const d) { + if(!dcache_ptr) + dcache_ptr.reset(new cache::cache(size, line_sz, ways)); + auto res = cache_mem_wr_delegate(a, l, d); + if(res == iss::Ok && ((a.val&io_addr_mask) != io_address)) { + auto set_addr=(a.val&(size-1))>>util::ilog2(line_sz*ways); + auto tag_addr=a.val>>util::ilog2(line_sz); + auto& set = dcache_ptr->sets[set_addr]; + for(auto& cl: set.ways) { + if(cl.st==cache::state::VALID && cl.tag_addr==tag_addr) { + auto start_addr = a.val&(line_sz-1); + for(auto i = 0U; i Date: Mon, 1 May 2023 22:23:35 +0200 Subject: [PATCH 079/184] fixes reading of 64bit CSR register --- src/iss/arch/riscv_hart_m_p.h | 8 ++++---- src/iss/arch/riscv_hart_mu_p.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 2a39f83..bf1e32a 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -256,7 +256,7 @@ public: return traits::MISA_VAL&0b0100; } constexpr reg_t get_pc_mask() { - return has_compressed()?~1:~3; + return has_compressed()?(reg_t)~1:(reg_t)~3; } riscv_hart_m_p(feature_config cfg = feature_config{}); @@ -477,11 +477,11 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) } // special handling & overrides csr_rd_cb[time] = &this_class::read_time; - csr_rd_cb[timeh] = &this_class::read_time; + if(traits::XLEN==32) csr_rd_cb[timeh] = &this_class::read_time; csr_rd_cb[cycle] = &this_class::read_cycle; - csr_rd_cb[cycleh] = &this_class::read_cycle; + if(traits::XLEN==32) csr_rd_cb[cycleh] = &this_class::read_cycle; csr_rd_cb[instret] = &this_class::read_instret; - csr_rd_cb[instreth] = &this_class::read_instret; + if(traits::XLEN==32) csr_rd_cb[instreth] = &this_class::read_instret; csr_rd_cb[mcycle] = &this_class::read_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle; diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 06c8830..94f7e08 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -508,11 +508,11 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) } // special handling & overrides csr_rd_cb[time] = &this_class::read_time; - csr_rd_cb[timeh] = &this_class::read_time; + if(traits::XLEN==32) csr_rd_cb[timeh] = &this_class::read_time; csr_rd_cb[cycle] = &this_class::read_cycle; - csr_rd_cb[cycleh] = &this_class::read_cycle; + if(traits::XLEN==32) csr_rd_cb[cycleh] = &this_class::read_cycle; csr_rd_cb[instret] = &this_class::read_instret; - csr_rd_cb[instreth] = &this_class::read_instret; + if(traits::XLEN==32) csr_rd_cb[instreth] = &this_class::read_instret; csr_rd_cb[mcycle] = &this_class::read_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle; From d70489cbb825fca85751c5f331a5fa1914d91efc Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 2 May 2023 07:58:48 +0200 Subject: [PATCH 080/184] update import script to initialize broker --- CMakeLists.txt | 2 +- contrib/.gitignore | 2 ++ contrib/README.md | 62 +++++++++++++++++++++++++++------------ contrib/build.tcl | 2 +- contrib/tgc_import.tcl | 9 +++--- contrib/tgc_import_tb.tcl | 8 ++--- 6 files changed, 56 insertions(+), 29 deletions(-) create mode 100644 contrib/.gitignore diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e59c6d..cf7a3b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,7 +173,7 @@ if(SystemC_FOUND) string(TOUPPER ${CORE_NAME_LC} CORE_NAME) target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) endforeach() - target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc) + target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc) if(WITH_LLVM) target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) endif() diff --git a/contrib/.gitignore b/contrib/.gitignore new file mode 100644 index 0000000..72f2821 --- /dev/null +++ b/contrib/.gitignore @@ -0,0 +1,2 @@ +/results +/cwr diff --git a/contrib/README.md b/contrib/README.md index ea9a647..c65d9f6 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -1,19 +1,43 @@ - # requires conan version 1.59 - # requires decent cmake version 3.23 for instance - git clone --recursive -b develop https://git.minres.com/TGFS/TGC-ISS.git - cd TGC-ISS/ - setenv COWAREHOME /scratch/rocco/workarea/tools/synopsys/T-2022.06-3 - setenv SNPSLMD_LICENSE_FILE 27001@lic02.arteris.com:5285@lic-node0:5285@lic03:5285@lic-node1 - source $COWAREHOME/SLS/linux/setup.csh pae - setenv SNPS_ENABLE_MEM_ON_DEMAND_IN_GENERIC_MEM 1 - setenv PATH $COWAREHOME/common/bin/:${PATH} - setenv LD_LIBRARY_PATH /scratch/rocco/workarea/tools/gcc-9.3.0-install/lib64/ - setenv CC /scratch/rocco/workarea/tools/synopsys/T-2022.06-3/SLS/linux/common/bin//gcc - setenv CXX /scratch/rocco/workarea/tools/synopsys/T-2022.06-3/SLS/linux/common/bin//g++ - cmake -S . -B build/Debug-PA -DCMAKE_BUILD_TYPE=Debug -DUSE_CWR_SYSTEMC=ON -DBUILD_SHARED_LIBS=ON -DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=/scratch/rocco/partners/minres/TGC-ISS/install - cd build/Debug-PA/ - make -j 16 install - cd ../../dbt-rise-tgc/contrib - setenv TGFS_INSTALL_ROOT /scratch/rocco/partners/minres/TGC-ISS/install/ - # import the TGC core itself - pct tgc_import.tcl +# Notes + +* requires conan version 1.59 +* requires decent cmake version 3.23 + +Setup for tcsh: + +``` +git clone --recursive -b develop https://git.minres.com/TGFS/TGC-ISS.git +cd TGC-ISS/ +setenv TGFS_INSTALL_ROOT `pwd`/install +setenv COWAREHOME +setenv SNPSLMD_LICENSE_FILE +source $COWAREHOME/SLS/linux/setup.csh pae +setenv SNPS_ENABLE_MEM_ON_DEMAND_IN_GENERIC_MEM 1 +setenv PATH $COWAREHOME/common/bin/:${PATH} +setenv CC $COWAREHOME/SLS/linux/common/bin/gcc +setenv CXX $COWAREHOME/SLS/linux/common/bin/g++ +cmake -S . -B build/PA -DCMAKE_BUILD_TYPE=Debug -DUSE_CWR_SYSTEMC=ON -DBUILD_SHARED_LIBS=ON \ + -DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=${TGFS_INSTALL_ROOT} +cmake --build build/PA --target install -j16 +cd dbt-rise-tgc/contrib +# import the TGC core itself +pct tgc_import_tb.tcl +``` + +Setup for bash: + +``` +git clone --recursive -b develop https://git.minres.com/TGFS/TGC-ISS.git +cd TGC-ISS/ +export TGFS_INSTALL_ROOT `pwd`/install +module load tools/pa/T-2022.06 +export SNPS_ENABLE_MEM_ON_DEMAND_IN_GENERIC_MEM=1 +export CC=$COWAREHOME/SLS/linux/common/bin/gcc +export CXX=$COWAREHOME/SLS/linux/common/bin/g++ +cmake -S . -B build/PA -DCMAKE_BUILD_TYPE=Debug -DUSE_CWR_SYSTEMC=ON -DBUILD_SHARED_LIBS=ON \ + -DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=${TGFS_INSTALL_ROOT} +cmake --build build/PA --target install -j16 +cd dbt-rise-tgc/contrib +# import the TGC core itself +pct tgc_import_tb.tcl +``` \ No newline at end of file diff --git a/contrib/build.tcl b/contrib/build.tcl index 023815b..e4da561 100644 --- a/contrib/build.tcl +++ b/contrib/build.tcl @@ -16,7 +16,7 @@ namespace eval Specification { set libdir "${install_dir}/lib64" set preprocessorOptions [concat $preprocessorOptions "-I${incldir}"] # Set the Linker paths. - set linkerOptions [concat $linkerOptions "-Wl,-rpath,${libdir} -L${libdir} -ldbt-rise-tgc_sc"] + set linkerOptions [concat $linkerOptions "-Wl,-rpath,${libdir} -L${libdir} -ldbt-rise-tgc_sc -lscc-sysc"] } default { puts stderr "ERROR: \"$target\" is not supported, [::scsh::version]" diff --git a/contrib/tgc_import.tcl b/contrib/tgc_import.tcl index 549f1b6..99a5026 100644 --- a/contrib/tgc_import.tcl +++ b/contrib/tgc_import.tcl @@ -9,8 +9,8 @@ proc getScriptDirectory {} { set hardware /HARDWARE/HW/HW set scriptDir [getScriptDirectory] -#set top_design_name sysc::tgfs::core_complex set top_design_name core_complex +set encap_name sysc::tgfs::${top_design_name} set clocks clk_i set resets rst_i set model_prefix "i_" @@ -25,7 +25,8 @@ set model_postfix "" ::pct::set_update_existing_encaps_flag true ::pct::set_dynamic_port_arrays_flag true ::pct::set_import_scml_properties_flag true -::pct::load_modules --set-category modules tgc_import.cc +::pct::set_import_encap_prop_as_extra_prop_flag true +::pct::load_modules --set-category modules ${scriptDir}/tgc_import.cc # Set Port Protocols correctly set block ${top_design_name} @@ -39,9 +40,9 @@ foreach reset ${resets} { # Set compile settings and look set block SYSTEM_LIBRARY:${top_design_name} -::pct::set_encap_build_script $block/sysc::tgfs::${top_design_name} $scriptDir/build.tcl +::pct::set_encap_build_script $block/${encap_name} $scriptDir/build.tcl ::pct::set_background_color_rgb $block 255 255 255 255 -::pct::create_instance SYSTEM_LIBRARY:${top_design_name} ${hardware} ${model_prefix}${top_design_name}${model_postfix} sysc::tgfs::${top_design_name} sysc::tgfs::${top_design_name}() +::pct::create_instance SYSTEM_LIBRARY:${top_design_name} ${hardware} ${model_prefix}${top_design_name}${model_postfix} ${encap_name} ${encap_name}() ::pct::set_bounds i_${top_design_name} 200 300 100 400 # export the result as component diff --git a/contrib/tgc_import_tb.tcl b/contrib/tgc_import_tb.tcl index 9df24aa..8d3a899 100644 --- a/contrib/tgc_import_tb.tcl +++ b/contrib/tgc_import_tb.tcl @@ -40,10 +40,10 @@ puts "setting parameters for DBT-RISE-TGC/Bus and memory components" ::pct::set_param_value $hardware/i_core_complex {Scml Properties} elf_file ${FW_name} ::pct::set_address i_core_complex/initiator:i_Memory_Generic/MEM 0x0 -#::pct::set_main_configuration Default {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::INFO).coloredOutput(false).logAsync(false));} {} {} {}} -#::pct::set_main_configuration Debug {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::DEBUG).coloredOutput(false).logAsync(false));} {} {} {}} -#::pct::create_simulation_build_config Debug -#::pct::set_simulation_build_project_setting Debug "Main Configuration" Default +::pct::set_main_configuration Default {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::INFO).coloredOutput(false).logAsync(false));} {} {} {}} +::pct::set_main_configuration Debug {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::DEBUG).coloredOutput(false).logAsync(false));} {} {} {}} +::pct::create_simulation_build_config Debug +::pct::set_simulation_build_project_setting Debug "Main Configuration" Default # add build settings and save design for next steps #::pct::set_simulation_build_project_setting "Debug" "Linker Flags" "-Wl,-z,muldefs $::env(VERILATOR_ROOT)/include/verilated.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_sc.cpp $::env(VERILATOR_ROOT)/include/verilated_vcd_c.cpp" #::pct::set_simulation_build_project_setting "Debug" "Include Paths" $::env(VERILATOR_ROOT)/include/ From 974d64a627d53eae0da4c47a99f5c7eb8ef88d6d Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 2 May 2023 08:17:17 +0200 Subject: [PATCH 081/184] adds logo to imported instance --- contrib/.gitignore | 1 + contrib/minres.png | Bin 0 -> 25551 bytes contrib/tgc_import.tcl | 1 + contrib/tgc_import_tb.tcl | 4 ++-- 4 files changed, 4 insertions(+), 2 deletions(-) create mode 100755 contrib/minres.png diff --git a/contrib/.gitignore b/contrib/.gitignore index 72f2821..d534727 100644 --- a/contrib/.gitignore +++ b/contrib/.gitignore @@ -1,2 +1,3 @@ /results /cwr +/*.xml diff --git a/contrib/minres.png b/contrib/minres.png new file mode 100755 index 0000000000000000000000000000000000000000..babf0e15ea344db93d1b4f287e039b096d9c4fbb GIT binary patch literal 25551 zcmeEu^;gte)c(*SrJ{7Gbcb{eTm&4tJB6Ve>9$ZrkQllYkdhj@22cSR1f)BpM!LJ+ z!}Y$uegA>)TJPtsyIgB#&gY!7&pCTP``ORot){vX$xWJ@5D0_>_T;fP1cHZvK(Ll? z;Db+yge*tEKlo2olpaH_uK&w!&W{J55V}7x@`6BknXdoG^2>wzfDZ|t!PFE8rm;xK z_-~UB;ek)?Ltu~Pbp0mQr(0YnN6tETG+O?+UX`}4>Swr-8H33T!IgOd;}#lgoEh2NNV z(<8{Tn6N-c|M&c#1^)lF0Qle2T=cv4rk^jv!-W;)%!TrA<%U0gfEe!`_j*~)=8*X~y z{{1*?`F?>ZIcxb;+%qTt!6AeHdZl@p?fL#?cnc}cZ2Z3R;qz`MV}`#C>`5tBi!0dG zrC`CZGNOs^FPQsmU^xGM2YHSr0fQ<;3f`k%qO?RM4L!&v{`;K}k=zo#Aob78+?o^d z$sL0&mb^F$t2sV<*x&E7{cmu}$K7p*sf_;Tt{oeA7Gtsn4{a$<<8!^Kj#b`GZYZy+NX+gSxFYaUbtowQoB6Js zCiSch#n#%B-2^y(mh|3kAdCwxH>Gyp7qNiKjpL0DN~49n6nf-n596v5%hmSQ` zD(;#8qRF(1@sm`>_>3<-EUlnG~l z+sSI(;FSDoLr{CLkNu1`?bV+|G)0cdauZoTTG=rD?y(kQ0$x&nBYqMQDW_Z0q+J&G z(fb3e&P8)0k;8NaqQ6__1KV>ni=a_kFkJXuA8AmU34FXzDGB;!J{OEHFXrlgVWWy- zN&7`Z(vU|<)Z@EsUi1c$-%p&K|BgYIKyK+yvgNMsiQO!N>C><4qfbsocxT$Hb1%Kl zoH$+tOwuM%>^(AC@1~Q1w!!~4qT7H9g_~)mKV!Kle2NxN=ji@prr;qc*k(9trmUPb zX+ZA2X*iW1vn(dwh8r#^UVQ*vUjA=~yWe__rbv-pQX)!|&`R`Zik!E}va~URGxi>M zT8bm~JLYAArz$sYBK9yX;5!Gw{~CrhYhHehyQ3`T99Z%F`$z~c0?)tOog6;|^Xg&^ zt!`uYYsl?~O` zhc?)=vD9|zWQB4R<~fIVNCgQIVPXHBrR0MGXN~bZ{9cwGi-1@{V-$x6v{7=?+GK!$ z=xorVgz43P2T9#XhWxGf+w?T$?-{h|K@sB0^a)^NQ%!=$- zz7B_KQ<(NG>{&GE%G3PqYV%=%bKgMh1=Ysx!)`b$DFy!JfXxOf?wL+2D@AnZ38`6DKr7 zC$JVV{P>XBY`vaQN5}kAQE-orepW-y1;v}7d-x&f+IxRrHT#d|_(L7z`+7C@<|!d0 zIH4YMcJ>@Zyj!$ig1WAKh!W-SWhOGUhXeO{|Br#Fa^IK5*Ux|uwkVqLyG zc@2dikZWh_oWc~o#Q3$Rppk49Au~XkPf!WH7j_hudCWt;O|evmi+|^oUyyi z_Pi3miMTQMkd>^Mh$d3B#v=pj%>;k^x3lRM(&XSoZM}hTx!#0t+x5+7=vDHprQ?wy z?owL|;L(QTtO@?U(cqk`zGa&GMWfSWWn^DgP{p zsEGakkHM!YG!+MT{`zUR`mURq5#cQo?pfOR0-2W7wU6>p&W^TMwP733C#xT-|HiAZ zrVAw_YV4#caqa^v!RKY3A(P~LnOBcJ1ck$mM$=W4d(_h01joPo;yGVE9$+K?_1}Vd z?ltF*MsMi6`xZx5d26~ByR=xoGU#XwmH$*()j5!>khUErN__sxI%4keKqtHUgw@

=KE@j378jlVWt{N2c|eu){AX`YY0_?CR%(;zONTgQjeSMc3$j$(tR zUXRe_I9?u+w)e<5@-_Oy65z+%gBwG5%bh;bbqa_7=Ytp9+Ov1BDq6=vRNuae&8?)H z;q7bR9zi3$T^iySn};Gmyn>x}?xLEBa6Si*Wh7Uh*Dj8Px&aZ2Rl?{DgJk}Mqmx9+JbfM+}dc8VEg20U{M)m^a0&? z^|Q6UZa1?jE}0(=DObTk#Asx_H6JWht;69PipcC<<4k*y2z8mG-;7_;)yV0Y3N-X` zYC6{|;@jx2BI6WBnDJJeIR2@4>Z40BPv_^W;`XXmr(d5$u;|M?q3K~=2yMq}F`)4F zc~Edpi?uYJOuVG)gI&WGH~ zY$s;-O!lC|NtUo-R)@*pl((4ZoWV2`la$mlNeI3 z3yk8u3p!!O(Diy6KN9i=S4y`tCffCs2X2)l5f(&jwg!Nx}2fB5(LWUxtUG zMF~kVsj7Y|48%)ntS$zZnm;lA$-3}Lej~(jqFHCqr$zLIaQ=jJ#De~Q@`9coc46Y_ z_P5WBDX7OE3K%ZVr=0~Eh6|b{OlDt^2Yh(sTH8y{mC97R*Q^9B%QMhxiB*BRd};2u z`#I|i!$Hh!CR*aMV@v(OyXn|fggUg>Zx$Dk6=^)VJNY2*UMd=w7K)(zGR9Hvd^%jT z7(Z!7b-Y1;Se?UNIX;5AESK-WBt{meT%zpT-Z?=-p=05tj0wCQDVY=jM%~;$T*XZrCY6B5z;fze2zng%4fQ+U+LEioHhO9 zdC(_y6^A68d@%-g=Xt3 z-8sA)Zb2SyAcaU#`Vd)QVlpuAsiEfSL&6Q+41yo~cLuwpb)~(h=`QoxIMYgx+W!-4 zlr~AgDI+eXr@x!mm#tEZey&s4?z4qELPyo8>f zw~3kNI`bCZX@M`SEC$X>T28%1sQFNV=V`1r#CY6yFZ>T=4Je5owY8(7TlT#2xzD^a zN9}kj_S)`%W64ONU+bI z?shnO-lC!qBblByL|^~m?IUtRvEe>0-zimof6nL5-aG!J>h34SAv5>d7C#qhpYWUl z!|Nn3z6q_lTrG~HY;M~QmHcTYF=^Bj)1h(%tbLHx*>Vs6($pyTG{Zl>X$p3#rVTu4 z>^rO_5H858E_96a(G}$LUhvrSD@6}M(eSngvBAxE&E7pbeBHeVFTS-}fGr-o@6>y7 zRV+7+!kXsaHn5rtj5A+R(LZksC&5PBx8hpmt(S6#_vH7@wjAMq8{+;GYtVS);Cr?a zJ=MoZKNvGB(eTcoxy>EM_)qvOR-Y4{~X_Tgim3p(DTL6(cV z1QRl&vrrxR6FH+OhrPXWVPBYx`|e044HmdKgWLab@PoI9t!9oDub# zS4iz!>Z5n7H1+4T2jF+v7@6tGb$vOgu0$f^DWNJ<$4)v#5_$>@!#8k3tz7x<#(IcC zpSEbjW^Rw~lP&v(Nsu;8ppou=k9|cc<1W`pUNa^j+6@`|H@$Y)GlzYY9$;=!Do1V1 zPZ94ndK=%plXn!F^k_deiyXEkx~8hzym=LV5mahhvIjZkNOh3hd=#+k-92uzF1;FB zNbQ!He3YU*;4ElcgnZ@1_qa-0++RhK)VEh(W_4~WkP z`L~+^`s5`@$Pp8N4=}t33qN+RWSryANQ(up0WIE7g(RCnvU>vkphZ zTbM%^YWxroMs@arn?}0F=R_weC`2^d+6-pX841}Leawtg8;s9t&Yp}9O5-Mwx%mpJ z(ZPU)}%x-Pbbrobsijw`t0K{rp~{aQ#29 zyF!8Lj}Wx)aB@zKO+rzUb6r0+W<$>#Ct;Cnv!YEOF)SKypo$)!g0Z^+3-L*8TwRoJ zas}0L3;%M6dq&h?$LLl4$kq($T>ASFkANv)UWXx8&d5nWu}1Zjkh9aFZL z!h3?)k}^|FOI!LkUA)Y5Ts=`6GukyD7?=3hGvrqXk_fpMenC1+rxFxIqKyynzp3j{ z@J?1{@qLeXwp4#%J05apH?O{ZWrVyqA6<0YxdY!fKo@oGSpr}D#$34pS7npl!2jly zs=aFhm&({@)&pLa>cAHtl`O|6a7)!Ox3Ig%@~`%)2pJ@`4!;kiHKZ&3!C0!}tS_1l zaaur2=)~^b0RQ;aB#NNK3D<9Bk{OK@P zp0UjIo|sb!P)8;)t?Bli4c}=$+jLapoMo!GxR9G}DxX4OZVA)({KxiOHW54pqnv{B z)Ut(Oa%i72H3v6-XL8M&RST@(MOX6$SsYQ8?J3~|Sy~^DVOnC$zE}3IkOpd#NBMFO z7TQXnEeWjwl4(&bX=)v_uu~%=Zr4X_DIwM}mqt2|5N34F7Mt-U+%VP~XCJ=@hiLW^ ziM+l}Nkc&*$OcZ)U}2~p1@~q47xkTGOvm{JEes0WAxQ6RihTqiYu7_M%t#ht%XV&= z#@IfM3hHBG8g6{O{?@TPS>)!*8SX^+=+qFms}hu8cPrnlV}yOoajg&2$Vvw=K^`&{ zorc?&PZ2#u$~h}q{TW$24xK@f11<^#IBvwWTsgh{3MGB(bdkwVTtfT9xndS+v1K6nQv$Zj{)==Mpj z;lOT7i*bgRMas=l(_gQa>@G;fx&4k5ja+^|Y_`5F1yQ{N;W8h!>Srck^_<4fRAT># zopJ}CvI;j^DyfQo3j<78b-O5(mlcLzqjr!N)jpoN_ZC3d4W+%^_l@9Gh#=1usE!@( zvUy)Pd%^bD)f>>8ii_gm4G1B?k1d^@2 zF<7#x-77`qT&v@aA!%#e*iu-H( zmchcJkNyb5`Dp@4T;A@A|LCjFjeT(u6n{Zj7bLU!X9ce>?0Pw4QPFt3A`4$Zj7iD5 z6b-4Z^nZ^G+dV4@y(}kG51pMmq!&MK@4a|Vg@1_-8j0;ncj4+zpFTg~;M$A7^LWPM zF54c?*~r_I=5BWNA2$h-iE(1eZhOUg2fX>rXDGTw@|uSt$azsXq4P^@el6HwzsGbQ z?R$y!OdSK?CFp;Oe6#X4cNUm}0G5-~@p>8mK-U5)9@I?##?@I;S+;RW)7K!^p zM*5S$1&VK#J%`E*#-nuVuaxjaUKsUg>R8r6m6}+?0=rwAf?xw|##hM2ktGmYQ@os1 zjIdXAs1L7UX5$5=TCc7?)$s+uIrX>eEVDziOD5Xs2T%G?I|C*u#LjS|v105)rY)rd zz63;vA0__fo1FKrRbQKYTF09^e~Eh7AS5T^|A*xD-nh+AwbfG#d5tB@6zri6BR77! z6s4l>O^gmH0UeYvaK3|p&QdULlGVfMQQzfxZqrIxUvv8l{M4BwV~{}yFDzHVVS z=^-WHaL*6|_59GJ<)f{ii$Si)IgOOhs(mt^TB{MIfEE7AKn#vbD>LANEetB#F z2vGM(tL1jwenLn=Qi#Pa(Ys zM(b4E^b+Nxcln+yA0xyb!Qs^p;E8)+PqhmdoJGJqJwCSZOJDVCX&tiBWu{R8ZY;6U zj9wv=J=p$R%xYvmOzUSd4YFX#psSPe$ugI)lzzILF4Kwr%r1@^5vgH4ihHg{iI>d} zk=2L5ck>Ws3Gn!-?iUr%-n@qV6nzh-gU^s%q%b&CYxBc zVd$k~$-|g`q60fkBhWwIob!WVkqF%?%)J`u`+aIY0f(-ytx z(>U?ta>T}m49B@|c>|i`?F6@Sxi*Ea8AbJ<>~YF8-`}%}9-f?qE!N^ux;~Y-8VPvg z(x{38iFhlxU%baFVg1 zd^){*{ISfFu}1+l`b%e=ud|ZS@|F$P6%8N-=hWb$lDpr3#=4kCGywM)B6DbS)fG+) z*HG=(u%ee+qD;1&5Av!I3hzlw`I0Up;9$f_gydx@DKgA##no<{aM7Dq`!)acQ8M6< z3uFVRi8f7@9n)w!)+kSv9c3DO!oDg18k~RIKkA;I-Pu{NbXruSxATv2n-ki$Qb~fBKj0G| z(QL5!&$-t2tr~w8;qH1Li{E~nXToYqTIoN%>@Bi6aLOmhP;?~RErn;#AD9^B7p_lR zP7Mvdyb$=t-iaC%oi#F<9VM^43U0VL`b+w@z1Nw9jbwSy2rcnsr&L7+<{&zRbaZ?@ zUlcb%OT>{=UOO>^t{uj?65LDvn;b4T0>VkoP0{|P=rbtdV&V;(>P;>9=lxeDvS>3M zd<)x$iz#ol#!J(X*a!Lt#vjZ>Qxk*XFX}SE}1CzA1?*}uNL49-KTY;vtgApSLCa1 zv3f5#ImCE6^Rv{U@-&HeEL$CBgGhE&%M($RG)cSuYPNf3I^sOpv$^QihZ91dirq=3 zal&g>O(T{m`q*9_$?Y*mRI`Qs!HDhCIe4hclfcEovjs)SnM|ljF>#kdaFN5Me}Y#j z83jbVb6qrU_5l*IAJGO`H_Blh$rQ%w^<~-or}iWHX<_bUYH&nR?w>h%E$cgz;G3l^-PFPSi^H``twPj2oSY8DrP-ScE1m@p0HdYoNrk+XFRRm1tGu_5l6 z%SmOFSh}gag*%^Pt-;PjOKHFN4@GF`T+kc&l>827Zszen;v`e@n$+--`Q|CMa%T!y zQ`tXhDS}j)V9OD5W=G-oHWIn&|@t5lPL>{vCPudnZ=Akx~;%A+HitvD0|pO?Vtyc;AE}75U5Y{rjRR zN}d_12WRA++uY6ziM!nHByw>4PrP*#6}jJ+pIQXe?3SK2-ZQMxGKg==A>N1JlzzM-x9b z6Ns5#Z10L99BBBUR=KCZM0^fvv6+!(>}ztkV4b6|#=4#1&a;(aZw_R}KBcVXymVe7 zk1hFWnCZkmdc}0N&M?a$XXkeE;4cj=E?mU#$VxM|N1$A66M8!>hmXc;E{3^TTOeh` zi`<=nDlB*-`e!_!YW8TyAOmqgOX7%)AWq{C{SK8#8S|<8ixP|4q1>K9-|O%?IZs(< zdAw-q-ee1!BE4R#QXQL(o8j^$g&P5+O?AuzH|q9RySw%Mp^a=xd_j@Xz~%^BvC2J0 zI_Lg@>NQatt_2naf*r9WuZ>xy#;0429x6w&>VQ5DjRTKUu9OGEi@VP%2L2JZ$ncf;D+UawSv!xEfD+U*#A!P9Yut1HHpa&IiKZ;1+df1*X`=KRvX+z6|+EgA3(pq_gQ#76Mdq_b) z#t3SR%U3qH``+*t83dBhI>gaZQwMY8!hw{h-BSzu{IGzSqdTPD*T%xL%Y71k_*T_-y7^Wkg&K;Cz03^;vphEo|1y<~-O7AugqDsT@G zz{cm@0iKK-xI;i!Ya83}5NhWr!vulI4o5KuBkP(&-1yVAO(+X$W-R|0jS)L>LfUui zvFqNb!h>wF8#2+|h72BeK@}xaBrQq@4AL?*^OcMH9-*54es#*Ou=|~V)dh(riEP|) z`_Y2er8+(uqZx*3MEL5O;TV1j+8+7IttfpTY&c1VN^Z@FrXpr%!GTRF>0(_D{~CMyAn-NNUaa&WPTY(W$U@p&Qg%hK8>e8#w$ zm*KN{)u5q|2(n2UiNNZm?0cX>t!B3%>F(fq2dnpfL6lv}m!;BNM&@A6kd*GxI8gNJ za{%S3uxXIv)&J1P-^L~nL&i=g4@}sLnTYCt77{l7N0VBT5GNGWkfDH~fVFTE@o!0{ z)a&SLF91U~UQ26?z#EiRxq+RF>~hyXYxe)pRm=fzM66G(2dlZj>lOo3A!mTbc;N7$ zknviUf_O3+mziq+rRTmiHNK2@4Y1IzfI*^kkgY>tn)A|aHL|)s+)Q2`7v8*fth_{& z*WQff*r#Z5Q&~-FC4unys%V_IS(nF+CF>pn8b&TFo$)n5G_p6I6ne3{@SFh{!8!R~ z)*7a&-<|DWw|a7FHgFP7UZMia3OQZaV!4)MShoGxJuE087DES#4&q=0BT@%< zWe;&_HF6ifScz#dsp1D6+uxC-97oG8q{LAc zuHz@Tu?J%X!Cn0Wui0+p${g+?U3@_Wl2%^ki@ia{(5u5yKBy-WR74f1-cF!ptq<_! zHGEXeoqsz03IcTJgNy=ybFfZATcR0i9q)h(;0t{BM|r@+OQ*2go4O{pFskDW^sU5s z8GRY3^Tx3P0o?4iVJ%~BPP$lMd>^>?5;sgql`v9J#loDO zh!^mfR>PofxGs(%A{8MbXYigNZz&gu5Jp1UMK^`~dZq-H;WC>w3KpE5SL@$+~PM=wn8W)NiBx$Z~X_}-qjD;r(L2rIFTuB9ZD zI8+QIWd~2>T0UCh3)^kFUQ_8*uu&I<-y$xQT$QS%ez7yRLmJKEF>$UAZzm*md~)_n zkZCurz|I16S~_s_>eEmuIe50IPAWJsi&8b&HG*LegTPK#NyQp7GFalCi15sSH6-i@ zy78N)LA)BH856PvHB0~9xo@c;kRN#CXvj^^PG9=5v(%>fz(GGYH1^L>z-v^wiq3-y z(aI+M7y+*!u$hJp7tRlp(Wxrz@`!O8se5q#5A`4R`x80~+UwqC3#RgVTQc@u?`n|< zAir4@3TH8)mdy;wS;uovh@N_4|AMv`h@l373)MS$aZ6WmFfV#tDG3A$i05N4Y$?+; zRTT(^vqHL}%noL3CUbMD)Lk&6vwFvr+Jb|0lhVd7?fffoPL zM^<^6#Nc>+&;v#FRdIhXLXz3GRBjWWH+^L~XbL)9L5Y;mg5=W-MCH>wpJO z1lAV59(3?6P5hgRmehP=NmZa~)0+fiDIg9?ai8u7Vufs5as%LX*M<2WW)mCM%k(K& zQqTIZa(GLZt7=mJ!c3se5ViJ_*9rOXX(oWoMUb|?tIgudydlV1O{<{WHCBE;SebovN5qt3OU z@UEB@4`{5>je}S^w;q+9E*%7{7T=127Aelv^&DLCZ*byh@Q1@S2BgV(!3@Z2DiI+6 z`>0fjgYbUnu=&)7PSXH%_@IylnYiPI0S;+%fHb&I04wv_3-N}6ol*lzNNz+EKWTNk zse!%zyj^V&rBY}4_h62{4}c6mEB&HtVb(o91vB;Ul9l(nq?tp`p zNlqinV=5q)S}3y!F;!W;cFRPMIM91GmmM~b!J>`{>K!Hwz0KP&+sBvh<9>{rooWsa z&ZVygIAK1=gwz3g?uxWxJsO-{50MDiGzV-T3XA4n|+He%g; z*;eeZ(O{%62_31c5#Wew`sZ8+BI+>h(&-gv!ObV9az;kPj=Z9iZ;`}@1HkzomfthI zlpBzQW6hgQKRG=B<8;>91t%oo%>){9xTJau$G!;U(?ASyF>Vu7saJ2Wh>V8Zbl%#r1firo(FRlx`Z(BJ*`NrI{$aA0ICra169~^ zP;kHq;c1>$2Y~>5s(_l2-TlHLt&F zP*0ftK;vNp$?vQFIr|PO8o1mvrR6UQQR1u+x-EVm~JLD2|uK%=w~8 zIP}WyE?Y5x#jFr8@1nlL=fO$b`*`baplAgMlqv3^gV4B{f+>lj3lO`|u~@&hy}TS9 zO=}Z|>rgyaqP-ws)P51UUqCFRdzVcImX&}P<11mrQQUm2ahGk7U7hL)Hbiry>zDHQ zL#W7md;htDt&IuXWRtj%_-O@EQ4!!Q!`7#ofJriuX(2Uz-Ffdzz&Rkf+umi`DZP2B z|F0Cdgb*T|H=g^{0?}T_Wwi&qP-{zHw-=m6!6h@PPnCmo?Yb>F;FXM0 z-dSfnIi1EW0P$3q4azkhYU=g48|NfA!YQOuw zl*wZDz&aF11sLBh*BQ&ggcq#wkAzvshxl=usST3X+A>RLYQN3Hw?D!{pE`=8MsU_&=Zuf%al#&bW83)mI4G%CfLY z6#`7Lx*NQSo_VM>q=z3i-HRZ@b6cq1AXCt!X4kySme2a*GzRG$ZlPR7qr!M57)g$w1cB)GP5le4?sh6dWQ}Z&;GErr#vt;uq|!1$C>LDjO?!c>aNXf>#i#bCW&=OBte=SgQo^`Uem&<1%O!7)nSW z>QR+nNpAxXf<+|3cU9nfb95Pow==?0g~ufahAGX|Jqh?5_TH(lBE1f_5cm0}Alp3Lxx`2vd-0vQ&$M(v0HZZ?~3$d4{iZvhbH zlc+qv1nazrXIj4k1Ca@uPd*EB0z+!uW#fXis00*GQ$*B#c*e5Q$F8mqYG7WyPhAmX z%ytu2T21`hI^%s34cVRGz)Q2hxilR7vu_;!-rX`k6rT;M<3C6exFc9ZA+)(IBo#n1ITU@E?vga@x zKidS4i9fF(5Zktr0+64*Yz+FKdkud3ATqulxxV-*9d?>vJ>qF}Dv2spDf|0snFdgn z_|gSweNCYTfkXg=f&p$eskwcrR26b|ONAhH?K`*mF}IG%N$Lz91Y-V=3mhUm@`(_V zko}`wZL~%P7bJu{z>dg?P7yN(DnoPe0q2?MvNe^4%5tdhK9JCIx&d!-9W4MtcyI7* zo>W5t!Y&_+VQ?ah0lZEF5~+Jg$_)gW&vJVvBsaH=ji{p{o*%L0(Sj}K0^AHcte@H! z#P#h2TYO6+9#{L@y00r$sUzOq@%_CUM$;`yDm2~eVvGGdGm?ax?@tc|GV~RsI@eA( z$(De|1#U$vbq}jG6(B;GMB%Z&4oH*hdS1c41G067p{&dlQa#tYTT(a+Tw9Ub$N4Px z0O!YGtTo7TlILiMGv|IfKywB)GB?0n!LsYX%IL>4G8mhQ0j2TPX3ZX4p3uKMh&kK0 z1>nvK2n^vZ%mDAoR*tg^90R0LWA6x2c(mjbNjGX}HW&$rrzP#+6yTo@PX-K-mljmV zTyW}cM$Z5+mEja1nLSBHhqx@=?jaS5uTOz5q<{0r45_O2^o&^W zbCG2YGJ$7?5H75t*={kxFZj2C97h`7wv;Aad+`Vhq>QUhBGi3ws7bvW z12vCLdZ!j%dZO_JsTURGm4N7vcMM*+B2aQUxTUWor4AWR=*Nra75?ar-ULEkU*?Of zTv4>L^_0wMee8Z(E|6*;vHJs8#WZFv`aAcH%OSozEzz@*KfJA4+A5Rcpc1Q-N-K-C z@V+Lu__^pFsNIxwSfen%uq7vb2l|C^vc0;`#QV-j)D92Q0S<&PJAhyes(U55MDNm? zfs@@!HxOnkAg&8V83Fx~q{?2=bv@T1^9Lj>CxxxVIbDaM21=WPZrxM|YMA=o5q)an zv;)Le*Ii)o#33*A&mmPx@?0j)1L{_{?A%HJxnS`<}eL z3)KD#b7SJnp*wM2FgKP9@DcD@I;f|>5qyd|&Do0Sd03@8`D;mlN0VcDIjSekkS#8x zZ--vKBv&{s=ggqVkef8?I z=@u0j06jmXAdtBy*NA!r^-_&b^(0cBHGpS4@Uc){5~MyQsl4Y1oW;34lCWja1HdO} zkx4()OAR zjzFpAYRuy@7uEo_#6vH+Bgn25MIYA!>xdJK3z>-3#NQz%yu>S$;t|Q?`i9-_Aw~>jtz7jHZ=e)${J~}vP5EjsAW4cwQYt3`C&eLp+>40Za1DJj}oHZa6 zZ7zEP&ZW*J_K(qm+>K23ZsTi>noLSJgyFq_B6?mSiDmsChlx${&*@M*Q_cL%NFhqIA_WP@R4+cW43TQ}BpOeY=RLx6G8LF*H*?WnXCl zRW>!qDV0A#SYM79wFih`Vn0C$hMmf)JbB1O!ftGF!W%*g(UT%e1YR`V4rwgOLPoP$ zSbru|`DJ66VF$G{-E(JZ( zYh$^I)hg#(*){gI0%YpCid4r$FgF{h^~r=Yt%>UWV{1}3Z&nVTY{lJ=09QihZhS^r z=-@~nvHrqqjV|?*z?SurDwulNT?UwmyksD~TgOY>dR)^}`_n6^>|a6Qir99&dIG`( z5Ec<@MJWgB)S}oFDfvuPjX3r{#lGde3Io)Grz%HOV(#Q~QE#@cN5UBu?Fr3dd~+q3 zz=W^tyLJ5hc%WwzlKrWK=9`kge(m*WkCT@`H0?%9OU41ufdEn^3F4qWVunb+sTFyu zV;5}n>=4hNU=3y-A8x4D;&lBe9dI$xAnxhF7-@DrG6LxC+0UKW@~(&)W6P?U^|4xG zI;a7HarjK9XfhzVL~e>g>~j(aF_@j>lW#Y(yOY~ZlvH&f=lWJWz$F~9UXZkM1)dgf zO2uc8WH;^g=ne?;U}f8;^K_p|cjD{WA>S&+DSl?%TE^IP*7|*@`XEGx11&*gqUUqr zGIl0L;vYJ-VGdYXU6tEA=1Ly((zRQF0?rYu*Aak=*-Qv8(c(j7d95R=TAh5xXX{cF_TXoe1$0sAT41Q zbrhU;r6_wNFz6j%ojUa`{Yy`6xGmCl86Z=Vm}emE(H;mi#*tO%q%s@zjY~z#;w67s z%Zo09pBoPdM#fvS%JRHpycmx!AdH?JkcU9rvp8=5E@Ti+;NgLSTAmZ&eBocpSQV3Kz{f0Qy_06KlMZ(bw5bA3h?)Cr!@ij9_q z_lkQBV{9qH0s=qm1DQii5%L=@0xKdV%(3X{Dj6y%jqC7lIFo~y?qoH0%&9UB+A7z zis$IC91w^99Mhm10lU;RGmQ4s@#AZ5wc)~K_?Lg81i1SPpglBe%)eECYditB2Wr)7 zn8F;hyavGbh}%~mGRD`;B=BNzOsmjj0Yu7_FtV;>6jX{Eq$kOX;^`k1Dxqujjg={J zA=!ScFUpI#U;N68)31#SDbRM2he&4mDxv`T;EvFW9<&-U5ehEqLP^aS2lHHtN-AMvJCJQIkOqq%mJ= zpLe&sMN&Z`y~=3t;zd!II&AgTgsSO6pJJ<~56@PNa{zLSn*Tny^Ntn?0mUvBfp z*YU37vDtY2cnFV!d9{Kkgf6((C~fDeN|Y*KIek#8!f6sx&_V#Oh*vmq3~^Lz?BnOYj1%%^SW1?h9gqKy8UV zsq4-RZh$fRxs-pY_>N@z*3*EK=zUv$k9+NJ6Qon?+3(*N=dBP|40upLj~_zQ-qoD@h%yFqeHJbR(-;!q zAnk!fNZsVmO09^qy9{&;$!uJ9a}>@;-@#4fZX%d_wWnTG;;paxp&lOMBYgxZ$RY?f za&oMvHb|~e$Z^#SRkDzczvho9{G<+h!38ZX^EPlX;L^Zz@O)ca?Kcos#>p5@WM!%G zVB{w}bJt(Db&+AgRV@BU%&N7Wi(JEJ@Ps9S8qfP{+NOO7S0-s6@Jd^%{FOx#6D}1Es9X)a zt?vGCfR~_rD68leyGsX$OMu_6AIVSWcr^K~VY}8q`|L|L)rsu308nGgXKFMyw;0=Z zsTK(5g;xT3f{k#If7-80PvE%;?lix@1DKwHz;|gp#sUNnZem` z2TDj(_TOfZbP(dJuhoc4wj6Hhfc%+WIM^$ysWS&%C@YDN@0chpukJreo=Hg5K-at&>msSgtO188bJztN@sQ2%Ag;ZE)VCG>~ z1GiO{n*w<{Q;V%-)_6~s57-iq1bF7v)V9TzX!kzFgZ(Vbi33u6@HoEQr4%#1%feFQrh93d;DJzv;oXYGheoNY4xw>eGk*-Ad(vXdng36UoT< zyj-rOG+5w+6&=7{rc-cB`hHmfNtDCZ=~Erfg^Bsg=}|y6={4K7{k=*(_wYGd?8#j= zGdP?$l6VY-sG4GfoRN@`idZ>iQKsQ-ZE|mzBr$9f$6TLm@RU9%h-yv=+f^Db+zb5t zg<0|F&5@zRSX2ZqTKXQNA?ksOxM*?Q={4aCs^uSnj)~6%3qC2sKy6qmrDHK3|IFkU z>*nJ`&rE&srU<1+f2V$3;Omt0z2g+r&UuP|}E^b=PG{(Nuj1nU~n ztJ@)5twCj9=ze@{v)p}R@&-pk#JWv>^ zCypC5&Vc5Q-|zZ(!6&6j1x|#Cu>T(EQ%qf!3w#`NW@`*C(3+Y{o=-cdobLUoJrU2> z2IS!NQxB^5lnNfm5Bn2sW`TB&L|dog+VxtIb0GB+kzVuqB|QAwXuFq>A2>y2r6EO9 zoUA>ee_OiWBs#F7ETf+;+srIu6i3c_H6#E}SQt&ju43e~w;I+?>tgH~pK@4uN1&QAOH<&f*eRWaoo{58IJ zzyxO@NAHF!jOGI64Z8MjS3OCOE85DE+&%rl5AASL@5_4gP`zyv=?xe2LTuokfX}nZo2r`KdQ0m(>cVPuJ_1~_U|#Wwv8WfmxR!1J zXT|{vyM`v=OP`#$TY$hp{axttz4J@@2+EDM_5NAKXMZou&wbi*z;3eC!;k^VHsF~x zj38Ssy>8&IG;9UPibuvLB4ypW&-I+v>hkey46`WDW5K;9c@6q?H>bhb0m_NrI4K){ z`_r54$MuUQ3=8)3XZ+TB#hc$Zp-=Iq>BsL4*95!-gJ_0P9eDUC%BR>Zh{++qIeYMF zXaf;W%f|N6>QL3iF!|MaZvrSrL9S+JE*4qi^4?)ztrlT?%I>e+8>`0F!BHe0;Gy`i zm;kG1e*FXnBaV$s=U4N@`lAKDp()GWxrsJ!t2Wr4xlcMBQmDGudHYs)D732~n9Jk) zTQBvOZ~0Kiq`HRrlaeu2_&@!`3>mDhk`{hj>g~vUQTV>#C*~Jq?Uhf#F>WVCH%0s6 zpT54%qD;07*Rsq@%xXyn(>-VzV{wR!Ik~QF&PvcusLE7RzJ8@g=H8CEBE@!N^t6*m z==(RYluFh7Jq1bR+=gI>%A$1u z6-N||qo4vo!{7)~MpQaMG!O;pO==W~C|x=P5(Y~r>7?<()w3tQ7ZZYboYxSM|eT`0z*WTC_3*j#DP=9}Az z5uwlSs!zHLn+NCcr_kH6VFVLa$zEG{8yWIWo_o=YXg(=*T-Qmd<7y3GuHBLmPypGcIr{AfE9k84vJdx zvr$u{E|DV5#5w`ZKhR8quGGGFY1>0;bM*K$;zKfik=ESyA*w3Mvt}`e4`~ZF-s5OD zKnD6XJt}}t(0f>Kj}4Y?tUs?T?G8*j1gXb$ijt`FtFAqA@}p(65W6MbfpScg`ZJ4N zc_^mePCheX~EQ&Ll~Y?g=&5pRWx26VZ`&cS^8+|0Gnz zaJ+l8g>Cl36qptxMf>uy^}M zQdz zIp)Wf=;864>%Iu#$G&wwl{F@SSkP^K>61Ts zI7N85T3SjSQ+^{X?}hu|P$SQWHH`&`K;@>md(8Mu_J-DE zX&p>`Z&{$hwuHLP=O)|2%1Ql6NPq1{7$`BZyzA}Rwx0aW=>E9#aQNuOJSR!FYtiY) zc_0vzud~d8cOUy_2kGW<)u(MGdYOKqa%6z43Szq4l=DA_t!4g$ePFlxe=14$Qpi*pGf7twWgN7I_@b<^#!EOW&&6 zgO_Qy`C8aFdyg*I-$rX4`B;0})282c)4naC^Vgb#o#~fu(5+|weXnz=k>=c08AE(| z@(G@G7oVT)tGTm*25vV5+fI;Do&#RIJ~uM-83wsq%IH{;#ia(jE5mr_P%5Q%OZZXL zg0Snlo2acUjQ5hVa~;gQXj$pdzs!y7o`wA82KB*3zTx7aqGdU_=CIK1*7i{`u1eC7 zhle5BIR&}#YTH&0#tV~orV_X3AGKX|Zh@Kqc%mla^Z4MhwH?g&Cu!rx%wLOjEe)Ua z$bL5D6(zi!O}|0Rg^~=}oh%eHZu%@ba8Y+7+Logrx~L21+-aKL^w7q@uny3|Z|n5b zG>}+Q#-o7CMG*wtv45<|SYeKt(R)gxW0)_p9@Hddz9);4zKPdz36IH2^jN8x*0Qy0 z+rToE-WH*gJv~mFU+^^=-?UD~=W-5-Kv#AUNnf*7a|vfNgQvH*J*Hn96s##l_S@MP zzcxpXsI-Midk35AV0?(Jy5B{4mSNr2$nWtr1CsHz3eC?M5)0U#T~}!-<8`5Kfo**>${A&*7L%~YA(>t?mC-{i?TwLj=2 z_}g0To2(QBPKb|tfw1+lsl^F9|F&FX2mj?=wYC!RZUEO5SnA*gMn*s*y`RoXalZ!R zb%d^T5w=PqgyBX>HSg=kr@d;=Ha+Ao$g;ZWuY~?SS-0`D*1FNvn(N7+qg)s*t43ww z4Z3A!$TaqHt=wjJ(lN+Q^>p||C1HNRVK9qP>F*=}p!s!3FveHFylCxeXhpZ~xk$C+ zw!W1$0WkG~V>wGPs=GCa^!J`C(I+~G`uxpZ^Ti~HRr2{xHeV9{J};h`LkIUj&X61<9u0iWOZ#E zQ7H>tLF{2o$c14yX5M5x009ybnHMHa)knHdGzJ0OYqOrS5cwj>D7Jp_`UqVazgjI~ zCH!WujcdN)#)oQ#w^*|_i^oPvD%tlOv<_8Us6V3F*ky9`vK}LR$g4IH*@%w8j4!Sx zf2*QVY7UY+1!93(Y>=N1aZw^JsCqK4_M(qT&SSx z5F<6hD8v1pE%&rldTDZG8|_#0(rXE<>n9O;eRDTPV4Gmj>XCv{QdN8=2641R9e#v z;(Y{t`z80?;h0{ID%wL!UvYhq7D!ERA!MN%>*PnZy(?>a{S;1G9pU|9L>_iR@ekkE zXq07Cj%EG@P6qyyCZlQKeA9mc?t|7SH#DrTh812(Iu&C&E~m@^8TZP(+2LjxxX!l` z|1Vd7fO+cAXu_5+c^EtIg)Pyg_AddmZKU!bskI0=R8NHmKL><*+(?tTl>g{mO~aC; z=!B8U_VvR=8KWW`skSDZ;L{q#4apdC1U?yQlKIH(qMb9(0w<^7hMf@2PvLB)oqyev zdF9cuX+H&hSaj_7S*Bx5&0baE&Wig#*|g#rmhVH-Bra@Jiqu06rolL_^E$S zT2G~1SOE|hl&3ZRo`wzkQ#swIa><|iP`YE{&L_9ah7#1}>G+h2$hkPly*ST(~cAJ38>+S)Of#ItG)junjw7n7L0%jLFqkjOyUow4P4=aTL`*%Z!R& z_R*4tYd;<~#fSguK)7t39Bcrsh(^bPfNcaf_BlUk2-p~@%;3ciXo`FJ%0d77p?KQ{#Zk%|>+Vbp2pXK9@29B{X^ngI1zuoG72UMa^ zmgo-nNU8Vp?Zc;-5hZ*>yea z>PHbi?sou^&q49g1iWTB)5zdUP-b`;U}$|>*O5PMLl1){Hv6~NOw#PYdZxsKL<)X| z^$_RM%BfpF3xSO0wk#(WVy{ioilAdGo5$h<}UG?@m0FzKp@LnRPa~@f*uK$5KMm0!UoU{ zb6$5a57<%$VavM#g#t(%Pf>kC0rnQ(6XZu8w$$_=tHyN{?;960rA2L7&O*|n;nR5s zOI50JmN^zfA+7p43B?%wie6_GfK9&$TV|hJwk5Se>7v31@Z_=lWtDzE>>Qw1#eYqh z)!(&AF{u1}vDaCWyw=o0*fP||F5V)7x>kMO4I2NW zz*(1$aN1n<7$6V78h%OtvV8z_o)Htj%z7u$lJP;-*vO?H{rHApEMe>ZP0Mun+c8Hu z*a_fNxjT39FAh&N5J_ALjo!J2V*Y@ZJ#qKnX}l)x`R>xKn_!WblZ?C8H>D5(Z>SI- zz{tDZ11^<@X$gZFpR#?85=?250*TS?yWxqWbAJTy{=wcjeuW^DNA5s*0D5i^wlL8$ z=DyGsZ7@K5a~x7H=v}}gF{uQHX?;&muDD-qOe&`YrF!nHP%}Z3z@oHX@p3YFSR;29 zgJyGL#~_#`2S=b9yMT&Nz_<>u=wn6Uzz-95oJ@0FqR#OeJf!ujydpd#iO1Z5l^LQs=#ra3A#8%1^juc?!c0j0k61t?- z{obUrg&G!i=09#ou;>o(IpJ_u!|_!U!;A?f_z?7I{Jy89eBBs`YXN4{;SLppT$e&+~CtG#UWEQ?;Y4M8X@KXL5GqPa$!Ngh4>X{%NOkGTixaI0A{R z0dfg^H2Z#G6`sG)s79={O)5ZME%ncQ+{wx*%ryX&)+naFZAC+BHVTOkuQ>N~XyZL~ zb~2an5y*vnRVqpR>?r+V!MrEFwqwZ(*_hL_5DDjbfLMGQnT^^PGaIWcxh{_YuPT&g zs}UQ-*{~?d;!I}5NF~?oSNt==?d_R?BQ^S{zYQmB^_SFtmxY^lT{ANJn#~X0purGU z^8-;isU)XO%Ok-KG4YuLafANE&aQ9rLDd0$EnQu00rSjY#xKODG4Qc_=%WA=6;|l064O_dFM_k}Kq{ z3?~AFAp+y$sDvJA_R;$>tLz6>q%a^hqHq#I6~A?F;G2oOZF;AJGmDv9r#xM@Opo|H-&3H zCvA})mU-xxgwYZtbSum-=ZZ$^0W0{t1L)J<2j?18I`6zhI&}G;1^7E0xvp& zR@-9HfvzPYu)zOx3~(=r6Az3qdpSgj1FSNH4i5B7F0WyQE`6F3UkJCg7En#^;%p=F zAc$(BZ_6ib7&b^HFGG>w`d*acR8vj^wZ1 zsz4$K{>cjv8BWajk?`0aL&%IQXx|1^kFTO}+Lf6d!nVprGdrpSXE!e?Ml*u!-QLaw z9j7lcfWa9-Hmbo7BEA>K9Of=G>RYr#sG(wNOqQ`zf~hs(l6LD98U+qw9%6w^oyOHq z(`2uOZGRP^?`RfeBGVJ^|8~vk28j0nRw^xpZ3()k%vjVM6La35aZ)b>VQheXILd0e z^b62r;3DtQWbG0HSUW(9L1d3~uCw?xhCT)U%CcW8;2$*F^Fdk#GU)vR4d%#u_MrSB zZgIvBppCTXL<5zsO7G5H!!k#M?7j8f0PZMLB)UKu}YldQa;OZAOiBp39IC=NforuU@Q*rQYE zfi6OmUvw5kD2$-$Uo4RAac~GdzL?33{tb9@T|@ZdmYMY0irOiEAvGmEyxN8{%PX*r zK)BvAmo3ALY#aTspp)Z+IGB2EWDP{2Uq525**Ga^5iGNWK3^B(W;;ezh+_4O?z z)oid>^HyWmbu-hPsz3wgjMD>_%{aXrCa@m;`Hvbz3PqytN>S=pO`?Kqa_+4Ng)n?) z6Wc{WzBTyRpT-4=#)UrTn(Uiur^MlNoFRfOWSF_>V$+rF3NQ1TY@t?i>ddz?iUd2; z+bfo3bx~Z<=S(Qy<-$KC-PBAsXmcmfZi+U(F&K`7f_--mjOqW*Oc0H$-ijd;K04nJ z+|wxrv_S&wSCXej__MXd$Etc(PU+VV~Tq$+sYcuu|7))> zJ1-u@UY5R8NNevuVXM6s4r(Cah($ literal 0 HcmV?d00001 diff --git a/contrib/tgc_import.tcl b/contrib/tgc_import.tcl index 99a5026..4372e3b 100644 --- a/contrib/tgc_import.tcl +++ b/contrib/tgc_import.tcl @@ -44,6 +44,7 @@ set block SYSTEM_LIBRARY:${top_design_name} ::pct::set_background_color_rgb $block 255 255 255 255 ::pct::create_instance SYSTEM_LIBRARY:${top_design_name} ${hardware} ${model_prefix}${top_design_name}${model_postfix} ${encap_name} ${encap_name}() ::pct::set_bounds i_${top_design_name} 200 300 100 400 +::pct::set_image i_${top_design_name} "$scriptDir/minres.png" center center false true # export the result as component ::pct::export_system_library ${top_design_name} ${top_design_name}.xml diff --git a/contrib/tgc_import_tb.tcl b/contrib/tgc_import_tb.tcl index 8d3a899..f2c87b7 100644 --- a/contrib/tgc_import_tb.tcl +++ b/contrib/tgc_import_tb.tcl @@ -37,8 +37,8 @@ puts "connecting reset/clock" ::pct::add_ports_to_connection C_rst i_Bus/Rst puts "setting parameters for DBT-RISE-TGC/Bus and memory components" -::pct::set_param_value $hardware/i_core_complex {Scml Properties} elf_file ${FW_name} -::pct::set_address i_core_complex/initiator:i_Memory_Generic/MEM 0x0 +::pct::set_param_value $hardware/i_${top_design_name} {Scml Properties} elf_file ${FW_name} +::pct::set_address $hardware/i_${top_design_name}/initiator:i_Memory_Generic/MEM 0x0 ::pct::set_main_configuration Default {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::INFO).coloredOutput(false).logAsync(false));} {} {} {}} ::pct::set_main_configuration Debug {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::DEBUG).coloredOutput(false).logAsync(false));} {} {} {}} From f9e8e1d857684784a5e0f3b18da0018a14994798 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 2 May 2023 11:13:25 +0200 Subject: [PATCH 082/184] fixes core_complex wrt. tlm quantum and DMI --- contrib/hello.dis | 2092 +++++++++++++++++++++++++++++++++++++ contrib/hello.elf | Bin 29716 -> 51556 bytes contrib/tgc_import_tb.tcl | 11 +- src/sysc/core_complex.cpp | 67 +- 4 files changed, 2123 insertions(+), 47 deletions(-) create mode 100644 contrib/hello.dis diff --git a/contrib/hello.dis b/contrib/hello.dis new file mode 100644 index 0000000..ff86ca8 --- /dev/null +++ b/contrib/hello.dis @@ -0,0 +1,2092 @@ + +hello: file format elf32-littleriscv + + +Disassembly of section .init: + +00000020 <_start>: + .section .init + .globl _start + .type _start,@function + +_start: + la gp, _gp + 20: 10000197 auipc gp,0x10000 + 24: 7e018193 addi gp,gp,2016 # 10000800 <_gp> + la sp, _sp + 28: 10004117 auipc sp,0x10004 + 2c: fd810113 addi sp,sp,-40 # 10004000 <_sp> + + /* Load data section */ + la a0, _data_lma + 30: 00001517 auipc a0,0x1 + 34: 72850513 addi a0,a0,1832 # 1758 <_data_lma> + la a1, _data + 38: 10000597 auipc a1,0x10000 + 3c: fc858593 addi a1,a1,-56 # 10000000 <_data> + la a2, _edata + 40: 10000617 auipc a2,0x10000 + 44: fc860613 addi a2,a2,-56 # 10000008 <__bss_start> + bgeu a1, a2, 2f + 48: 00c5fc63 bgeu a1,a2,60 <_start+0x40> +1: + lw t0, (a0) + 4c: 00052283 lw t0,0(a0) + sw t0, (a1) + 50: 0055a023 sw t0,0(a1) + addi a0, a0, 4 + 54: 00450513 addi a0,a0,4 + addi a1, a1, 4 + 58: 00458593 addi a1,a1,4 + bltu a1, a2, 1b + 5c: fec5e8e3 bltu a1,a2,4c <_start+0x2c> +2: + + /* Clear bss section */ + la a0, __bss_start + 60: 10000517 auipc a0,0x10000 + 64: fa850513 addi a0,a0,-88 # 10000008 <__bss_start> + la a1, _end + 68: 10000597 auipc a1,0x10000 + 6c: fa058593 addi a1,a1,-96 # 10000008 <__bss_start> + bgeu a0, a1, 2f + 70: 00b57863 bgeu a0,a1,80 <_start+0x60> +1: + sw zero, (a0) + 74: 00052023 sw zero,0(a0) + addi a0, a0, 4 + 78: 00450513 addi a0,a0,4 + bltu a0, a1, 1b + 7c: feb56ce3 bltu a0,a1,74 <_start+0x54> + fssr x0 +1: +#endif + + /* argc = argv = 0 */ + li a0, 0 + 80: 00000513 li a0,0 + li a1, 0 + 84: 00000593 li a1,0 + call main + 88: 008000ef jal ra,90

+ tail _exit + 8c: 3300006f j 3bc <__wrap__exit> + +Disassembly of section .text: + +00000090
: + return result; + +} + +int main() +{ + 90: fe010113 addi sp,sp,-32 + volatile int result = 1; + 94: 00100793 li a5,1 +{ + 98: 00812c23 sw s0,24(sp) + 9c: 00912a23 sw s1,20(sp) + a0: 00112e23 sw ra,28(sp) + volatile int result = 1; + a4: 00f12623 sw a5,12(sp) + for (int ii = 1; ii <= i; ii++) { + a8: 00100413 li s0,1 + ac: 00b00493 li s1,11 + result = result * ii; + b0: 00c12503 lw a0,12(sp) + b4: 00040593 mv a1,s0 + for (int ii = 1; ii <= i; ii++) { + b8: 00140413 addi s0,s0,1 + result = result * ii; + bc: 2b0010ef jal ra,136c <__mulsi3> + c0: 00a12623 sw a0,12(sp) + for (int ii = 1; ii <= i; ii++) { + c4: fe9416e3 bne s0,s1,b0 + return result; + c8: 00c12783 lw a5,12(sp) +// *(uint32_t*)(GPIO_CTRL_ADDR+GPIO_IOF_SEL) &= ~IOF0_UART0_MASK; +// *(uint32_t*)(GPIO_CTRL_ADDR+GPIO_IOF_EN) |= IOF0_UART0_MASK; + volatile int result = factorial (10); + printf("Factorial is %d\n", result); + cc: 00001517 auipc a0,0x1 + d0: 3c450513 addi a0,a0,964 # 1490 <__clzsi2+0x4c> + volatile int result = factorial (10); + d4: 00f12423 sw a5,8(sp) + printf("Factorial is %d\n", result); + d8: 00812583 lw a1,8(sp) + dc: 285000ef jal ra,b60 <__wrap_printf> + printf("End of execution"); + e0: 00001517 auipc a0,0x1 + e4: 3c450513 addi a0,a0,964 # 14a4 <__clzsi2+0x60> + e8: 279000ef jal ra,b60 <__wrap_printf> + return 0; +} + ec: 01c12083 lw ra,28(sp) + f0: 01812403 lw s0,24(sp) + f4: 01412483 lw s1,20(sp) + f8: 00000513 li a0,0 + fc: 02010113 addi sp,sp,32 + 100: 00008067 ret + +00000104 : + + .section .text.entry + .align 2 + .global trap_entry +trap_entry: + addi sp, sp, -32*REGBYTES + 104: f8010113 addi sp,sp,-128 + + STORE x1, 1*REGBYTES(sp) + 108: 00112223 sw ra,4(sp) + STORE x2, 2*REGBYTES(sp) + 10c: 00212423 sw sp,8(sp) + STORE x3, 3*REGBYTES(sp) + 110: 00312623 sw gp,12(sp) + STORE x4, 4*REGBYTES(sp) + 114: 00412823 sw tp,16(sp) + STORE x5, 5*REGBYTES(sp) + 118: 00512a23 sw t0,20(sp) + STORE x6, 6*REGBYTES(sp) + 11c: 00612c23 sw t1,24(sp) + STORE x7, 7*REGBYTES(sp) + 120: 00712e23 sw t2,28(sp) + STORE x8, 8*REGBYTES(sp) + 124: 02812023 sw s0,32(sp) + STORE x9, 9*REGBYTES(sp) + 128: 02912223 sw s1,36(sp) + STORE x10, 10*REGBYTES(sp) + 12c: 02a12423 sw a0,40(sp) + STORE x11, 11*REGBYTES(sp) + 130: 02b12623 sw a1,44(sp) + STORE x12, 12*REGBYTES(sp) + 134: 02c12823 sw a2,48(sp) + STORE x13, 13*REGBYTES(sp) + 138: 02d12a23 sw a3,52(sp) + STORE x14, 14*REGBYTES(sp) + 13c: 02e12c23 sw a4,56(sp) + STORE x15, 15*REGBYTES(sp) + 140: 02f12e23 sw a5,60(sp) +#ifndef __riscv_abi_rve + STORE x16, 16*REGBYTES(sp) + 144: 05012023 sw a6,64(sp) + STORE x17, 17*REGBYTES(sp) + 148: 05112223 sw a7,68(sp) + STORE x18, 18*REGBYTES(sp) + 14c: 05212423 sw s2,72(sp) + STORE x19, 19*REGBYTES(sp) + 150: 05312623 sw s3,76(sp) + STORE x20, 20*REGBYTES(sp) + 154: 05412823 sw s4,80(sp) + STORE x21, 21*REGBYTES(sp) + 158: 05512a23 sw s5,84(sp) + STORE x22, 22*REGBYTES(sp) + 15c: 05612c23 sw s6,88(sp) + STORE x23, 23*REGBYTES(sp) + 160: 05712e23 sw s7,92(sp) + STORE x24, 24*REGBYTES(sp) + 164: 07812023 sw s8,96(sp) + STORE x25, 25*REGBYTES(sp) + 168: 07912223 sw s9,100(sp) + STORE x26, 26*REGBYTES(sp) + 16c: 07a12423 sw s10,104(sp) + STORE x27, 27*REGBYTES(sp) + 170: 07b12623 sw s11,108(sp) + STORE x28, 28*REGBYTES(sp) + 174: 07c12823 sw t3,112(sp) + STORE x29, 29*REGBYTES(sp) + 178: 07d12a23 sw t4,116(sp) + STORE x30, 30*REGBYTES(sp) + 17c: 07e12c23 sw t5,120(sp) + STORE x31, 31*REGBYTES(sp) + 180: 07f12e23 sw t6,124(sp) +#endif + csrr a0, mcause + 184: 34202573 csrr a0,mcause + csrr a1, mepc + 188: 341025f3 csrr a1,mepc + mv a2, sp + 18c: 00010613 mv a2,sp + call handle_trap + 190: 11c000ef jal ra,2ac + csrw mepc, a0 + 194: 34151073 csrw mepc,a0 + + # Remain in M-mode after mret + li t0, MSTATUS_MPP + 198: 000022b7 lui t0,0x2 + 19c: 80028293 addi t0,t0,-2048 # 1800 <_data_lma+0xa8> + csrs mstatus, t0 + 1a0: 3002a073 csrs mstatus,t0 + + LOAD x1, 1*REGBYTES(sp) + 1a4: 00412083 lw ra,4(sp) + LOAD x2, 2*REGBYTES(sp) + 1a8: 00812103 lw sp,8(sp) + LOAD x3, 3*REGBYTES(sp) + 1ac: 00c12183 lw gp,12(sp) + LOAD x4, 4*REGBYTES(sp) + 1b0: 01012203 lw tp,16(sp) + LOAD x5, 5*REGBYTES(sp) + 1b4: 01412283 lw t0,20(sp) + LOAD x6, 6*REGBYTES(sp) + 1b8: 01812303 lw t1,24(sp) + LOAD x7, 7*REGBYTES(sp) + 1bc: 01c12383 lw t2,28(sp) + LOAD x8, 8*REGBYTES(sp) + 1c0: 02012403 lw s0,32(sp) + LOAD x9, 9*REGBYTES(sp) + 1c4: 02412483 lw s1,36(sp) + LOAD x10, 10*REGBYTES(sp) + 1c8: 02812503 lw a0,40(sp) + LOAD x11, 11*REGBYTES(sp) + 1cc: 02c12583 lw a1,44(sp) + LOAD x12, 12*REGBYTES(sp) + 1d0: 03012603 lw a2,48(sp) + LOAD x13, 13*REGBYTES(sp) + 1d4: 03412683 lw a3,52(sp) + LOAD x14, 14*REGBYTES(sp) + 1d8: 03812703 lw a4,56(sp) + LOAD x15, 15*REGBYTES(sp) + 1dc: 03c12783 lw a5,60(sp) +#ifndef __riscv_abi_rve + LOAD x16, 16*REGBYTES(sp) + 1e0: 04012803 lw a6,64(sp) + LOAD x17, 17*REGBYTES(sp) + 1e4: 04412883 lw a7,68(sp) + LOAD x18, 18*REGBYTES(sp) + 1e8: 04812903 lw s2,72(sp) + LOAD x19, 19*REGBYTES(sp) + 1ec: 04c12983 lw s3,76(sp) + LOAD x20, 20*REGBYTES(sp) + 1f0: 05012a03 lw s4,80(sp) + LOAD x21, 21*REGBYTES(sp) + 1f4: 05412a83 lw s5,84(sp) + LOAD x22, 22*REGBYTES(sp) + 1f8: 05812b03 lw s6,88(sp) + LOAD x23, 23*REGBYTES(sp) + 1fc: 05c12b83 lw s7,92(sp) + LOAD x24, 24*REGBYTES(sp) + 200: 06012c03 lw s8,96(sp) + LOAD x25, 25*REGBYTES(sp) + 204: 06412c83 lw s9,100(sp) + LOAD x26, 26*REGBYTES(sp) + 208: 06812d03 lw s10,104(sp) + LOAD x27, 27*REGBYTES(sp) + 20c: 06c12d83 lw s11,108(sp) + LOAD x28, 28*REGBYTES(sp) + 210: 07012e03 lw t3,112(sp) + LOAD x29, 29*REGBYTES(sp) + 214: 07412e83 lw t4,116(sp) + LOAD x30, 30*REGBYTES(sp) + 218: 07812f03 lw t5,120(sp) + LOAD x31, 31*REGBYTES(sp) + 21c: 07c12f83 lw t6,124(sp) +#endif + addi sp, sp, 32*REGBYTES + 220: 08010113 addi sp,sp,128 + mret + 224: 30200073 mret + +.weak handle_trap +handle_trap: +1: + j 1b + 228: 0000006f j 228 + +0000022c : +int factorial(int i){ + 22c: fe010113 addi sp,sp,-32 + volatile int result = 1; + 230: 00100793 li a5,1 +int factorial(int i){ + 234: 00112e23 sw ra,28(sp) + 238: 00812c23 sw s0,24(sp) + 23c: 00912a23 sw s1,20(sp) + volatile int result = 1; + 240: 00f12623 sw a5,12(sp) + for (int ii = 1; ii <= i; ii++) { + 244: 02a05263 blez a0,268 + 248: 00150493 addi s1,a0,1 + 24c: 00100413 li s0,1 + result = result * ii; + 250: 00c12503 lw a0,12(sp) + 254: 00040593 mv a1,s0 + for (int ii = 1; ii <= i; ii++) { + 258: 00140413 addi s0,s0,1 + result = result * ii; + 25c: 110010ef jal ra,136c <__mulsi3> + 260: 00a12623 sw a0,12(sp) + for (int ii = 1; ii <= i; ii++) { + 264: fe9416e3 bne s0,s1,250 +} + 268: 01c12083 lw ra,28(sp) + 26c: 01812403 lw s0,24(sp) + return result; + 270: 00c12503 lw a0,12(sp) +} + 274: 01412483 lw s1,20(sp) + 278: 02010113 addi sp,sp,32 + 27c: 00008067 ret + +00000280 : +#if __riscv_xlen==32 + +static uint32_t mtime_hi(void) +{ + unsigned long ret; + __asm volatile("rdtimeh %0":"=r"(ret)); + 280: c81027f3 rdtimeh a5 + __asm volatile("rdtime %0":"=r"(ret)); + 284: c0102573 rdtime a0 + __asm volatile("rdtimeh %0":"=r"(ret)); + 288: c81025f3 rdtimeh a1 +uint64_t get_timer_value() +{ + while (1) { + uint32_t hi = mtime_hi(); + uint32_t lo = mtime_lo(); + if (hi == mtime_hi()) + 28c: fef59ae3 bne a1,a5,280 + return ((uint64_t)hi << 32) | lo; + } +} + 290: 00008067 ret + +00000294 : +#endif + +unsigned long get_timer_freq() +{ + return 32768; +} + 294: 00008537 lui a0,0x8 + 298: 00008067 ret + +0000029c : + +unsigned long get_cpu_freq() +{ + return 10000000; + 29c: 00989537 lui a0,0x989 +} + 2a0: 68050513 addi a0,a0,1664 # 989680 <_data_lma+0x987f28> + 2a4: 00008067 ret + +000002a8 : + +void init_pll(void){ + +} + 2a8: 00008067 ret + +000002ac : +#ifdef USE_M_TIME +extern void handle_m_time_interrupt(); +#endif + +uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) +{ + 2ac: ff010113 addi sp,sp,-16 + 2b0: 00812423 sw s0,8(sp) + } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){ + handle_m_time_interrupt(); +#endif + } + else { + write(1, "trap\n", 5); + 2b4: 00500613 li a2,5 +{ + 2b8: 00050413 mv s0,a0 + write(1, "trap\n", 5); + 2bc: 00001597 auipc a1,0x1 + 2c0: 1fc58593 addi a1,a1,508 # 14b8 <__clzsi2+0x74> + 2c4: 00100513 li a0,1 +{ + 2c8: 00112623 sw ra,12(sp) + write(1, "trap\n", 5); + 2cc: 05c000ef jal ra,328 <__wrap_write> + _exit(1 + mcause); + 2d0: 00140513 addi a0,s0,1 + 2d4: 0e8000ef jal ra,3bc <__wrap__exit> + +000002d8 <_init>: +void _init() +{ + +#ifndef NO_INIT + init_pll(); + printf("core freq at %d Hz\n", get_cpu_freq()); + 2d8: 009895b7 lui a1,0x989 +{ + 2dc: ff010113 addi sp,sp,-16 + printf("core freq at %d Hz\n", get_cpu_freq()); + 2e0: 68058593 addi a1,a1,1664 # 989680 <_data_lma+0x987f28> + 2e4: 00001517 auipc a0,0x1 + 2e8: 1dc50513 addi a0,a0,476 # 14c0 <__clzsi2+0x7c> +{ + 2ec: 00112623 sw ra,12(sp) + printf("core freq at %d Hz\n", get_cpu_freq()); + 2f0: 071000ef jal ra,b60 <__wrap_printf> + write_csr(mtvec, &trap_entry); + 2f4: 00000797 auipc a5,0x0 + 2f8: e1078793 addi a5,a5,-496 # 104 + 2fc: 30579073 csrw mtvec,a5 + if (read_csr(misa) & (1 << ('F' - 'A'))) { // if F extension is present + 300: 301027f3 csrr a5,misa + 304: 0207f793 andi a5,a5,32 + 308: 00078863 beqz a5,318 <_init+0x40> + write_csr(mstatus, MSTATUS_FS); // allow FPU instructions without trapping + 30c: 000067b7 lui a5,0x6 + 310: 30079073 csrw mstatus,a5 + write_csr(fcsr, 0); // initialize rounding mode, undefined at reset + 314: 00305073 csrwi fcsr,0 + } +#endif + +} + 318: 00c12083 lw ra,12(sp) + 31c: 01010113 addi sp,sp,16 + 320: 00008067 ret + +00000324 <_fini>: + +void _fini() +{ +} + 324: 00008067 ret + +00000328 <__wrap_write>: + +#include "platform.h" +#include "stub.h" + +ssize_t __wrap_write(int fd, const void* ptr, size_t len) +{ + 328: ff010113 addi sp,sp,-16 + 32c: 00812423 sw s0,8(sp) + 330: 00912223 sw s1,4(sp) + 334: 00112623 sw ra,12(sp) + 338: 00058413 mv s0,a1 + 33c: 00060493 mv s1,a2 + const uint8_t * current = (const char *)ptr; + + if (isatty(fd)) { + 340: 070000ef jal ra,3b0 <__wrap_isatty> + 344: 06050263 beqz a0,3a8 <__wrap_write+0x80> + for (size_t jj = 0; jj < len; jj++) { + 348: 02048c63 beqz s1,380 <__wrap_write+0x58> + 34c: 00040593 mv a1,s0 + 350: 00940833 add a6,s0,s1 + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + 354: ffff0737 lui a4,0xffff0 + UART0_REG(UART_REG_TXFIFO) = current[jj]; + + if (current[jj] == '\n') { + 358: 00a00693 li a3,10 + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + UART0_REG(UART_REG_TXFIFO) = '\r'; + 35c: 00d00613 li a2,13 + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + 360: 00072783 lw a5,0(a4) # ffff0000 + 364: fe07cee3 bltz a5,360 <__wrap_write+0x38> + UART0_REG(UART_REG_TXFIFO) = current[jj]; + 368: 0005c783 lbu a5,0(a1) + 36c: 00f72023 sw a5,0(a4) + if (current[jj] == '\n') { + 370: 0005c783 lbu a5,0(a1) + 374: 02d78263 beq a5,a3,398 <__wrap_write+0x70> + for (size_t jj = 0; jj < len; jj++) { + 378: 00158593 addi a1,a1,1 + 37c: ff0592e3 bne a1,a6,360 <__wrap_write+0x38> + } + } + return len; + 380: 00048513 mv a0,s1 + } + + return _stub(EBADF); +} + 384: 00c12083 lw ra,12(sp) + 388: 00812403 lw s0,8(sp) + 38c: 00412483 lw s1,4(sp) + 390: 01010113 addi sp,sp,16 + 394: 00008067 ret + while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; + 398: 00072783 lw a5,0(a4) + 39c: fe07cee3 bltz a5,398 <__wrap_write+0x70> + UART0_REG(UART_REG_TXFIFO) = '\r'; + 3a0: 00c72023 sw a2,0(a4) + 3a4: fd5ff06f j 378 <__wrap_write+0x50> + return _stub(EBADF); + 3a8: fff00513 li a0,-1 + 3ac: fd9ff06f j 384 <__wrap_write+0x5c> + +000003b0 <__wrap_isatty>: + +#include + +int __wrap_isatty(int fd) +{ + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) + 3b0: fff50513 addi a0,a0,-1 + return 1; + + return 0; +} + 3b4: 00253513 sltiu a0,a0,2 + 3b8: 00008067 ret + +000003bc <__wrap__exit>: +extern volatile uint32_t fromhost; + +void __wrap__exit(int code) +{ +//volatile uint32_t* leds = (uint32_t*) (GPIO_BASE_ADDR + GPIO_OUT_OFFSET); + const char message[] = "\nProgam has exited with code:"; + 3bc: 00001797 auipc a5,0x1 + 3c0: 11878793 addi a5,a5,280 # 14d4 <__clzsi2+0x90> + 3c4: 0007ae83 lw t4,0(a5) + 3c8: 0047ae03 lw t3,4(a5) + 3cc: 0087a303 lw t1,8(a5) + 3d0: 00c7a883 lw a7,12(a5) + 3d4: 0107a803 lw a6,16(a5) + 3d8: 0147a683 lw a3,20(a5) + 3dc: 0187a703 lw a4,24(a5) + 3e0: 01c7d783 lhu a5,28(a5) +{ + 3e4: fd010113 addi sp,sp,-48 +//*leds = (~(code)); + + write(STDERR_FILENO, message, sizeof(message) - 1); + 3e8: 01d00613 li a2,29 +{ + 3ec: 02812423 sw s0,40(sp) + write(STDERR_FILENO, message, sizeof(message) - 1); + 3f0: 00010593 mv a1,sp +{ + 3f4: 00050413 mv s0,a0 + write(STDERR_FILENO, message, sizeof(message) - 1); + 3f8: 00200513 li a0,2 + const char message[] = "\nProgam has exited with code:"; + 3fc: 00f11e23 sh a5,28(sp) +{ + 400: 02112623 sw ra,44(sp) + const char message[] = "\nProgam has exited with code:"; + 404: 01d12023 sw t4,0(sp) + 408: 01c12223 sw t3,4(sp) + 40c: 00612423 sw t1,8(sp) + 410: 01112623 sw a7,12(sp) + 414: 01012823 sw a6,16(sp) + 418: 00d12a23 sw a3,20(sp) + 41c: 00e12c23 sw a4,24(sp) + write(STDERR_FILENO, message, sizeof(message) - 1); + 420: f09ff0ef jal ra,328 <__wrap_write> + write_hex(STDERR_FILENO, code); + 424: 00040593 mv a1,s0 + 428: 00200513 li a0,2 + 42c: 028000ef jal ra,454 + write(STDERR_FILENO, "\n", 1); + 430: 00100613 li a2,1 + 434: 00001597 auipc a1,0x1 + 438: 08858593 addi a1,a1,136 # 14bc <__clzsi2+0x78> + 43c: 00200513 li a0,2 + tohost = code+1; + 440: 00140413 addi s0,s0,1 + write(STDERR_FILENO, "\n", 1); + 444: ee5ff0ef jal ra,328 <__wrap_write> + tohost = code+1; + 448: 00000797 auipc a5,0x0 + 44c: ba87a423 sw s0,-1112(a5) # fffffff0 + for (;;); + 450: 0000006f j 450 <__wrap__exit+0x94> + +00000454 : +#include +#include +#include "platform.h" + +void write_hex(int fd, uint32_t hex) +{ + 454: fd010113 addi sp,sp,-48 + 458: 02912223 sw s1,36(sp) + uint8_t ii; + uint8_t jj; + char towrite; + write(fd , "0x", 2); + 45c: 00200613 li a2,2 +{ + 460: 00058493 mv s1,a1 + write(fd , "0x", 2); + 464: 00001597 auipc a1,0x1 + 468: 09058593 addi a1,a1,144 # 14f4 <__clzsi2+0xb0> +{ + 46c: 02812423 sw s0,40(sp) + 470: 03212023 sw s2,32(sp) + 474: 01312e23 sw s3,28(sp) + 478: 01412c23 sw s4,24(sp) + 47c: 01512a23 sw s5,20(sp) + 480: 02112623 sw ra,44(sp) + 484: 00050913 mv s2,a0 + write(fd , "0x", 2); + 488: 01c00413 li s0,28 + 48c: e9dff0ef jal ra,328 <__wrap_write> + for (ii = 8 ; ii > 0; ii--) { + jj = ii - 1; + uint8_t digit = ((hex & (0xF << (jj*4))) >> (jj*4)); + 490: 00f00a93 li s5,15 + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + 494: 00900a13 li s4,9 + for (ii = 8 ; ii > 0; ii--) { + 498: ffc00993 li s3,-4 + 49c: 0240006f j 4c0 + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + 4a0: 0ff6f793 zext.b a5,a3 + for (ii = 8 ; ii > 0; ii--) { + 4a4: ffc40413 addi s0,s0,-4 + write(fd, &towrite, 1); + 4a8: 00100613 li a2,1 + 4ac: 00f10593 addi a1,sp,15 + 4b0: 00090513 mv a0,s2 + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + 4b4: 00f107a3 sb a5,15(sp) + write(fd, &towrite, 1); + 4b8: e71ff0ef jal ra,328 <__wrap_write> + for (ii = 8 ; ii > 0; ii--) { + 4bc: 05340063 beq s0,s3,4fc + uint8_t digit = ((hex & (0xF << (jj*4))) >> (jj*4)); + 4c0: 008a97b3 sll a5,s5,s0 + 4c4: 0097f7b3 and a5,a5,s1 + 4c8: 0087d7b3 srl a5,a5,s0 + 4cc: 0ff7f793 zext.b a5,a5 + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + 4d0: 03078693 addi a3,a5,48 + 4d4: 03778713 addi a4,a5,55 + 4d8: fcfa74e3 bgeu s4,a5,4a0 + 4dc: 0ff77793 zext.b a5,a4 + for (ii = 8 ; ii > 0; ii--) { + 4e0: ffc40413 addi s0,s0,-4 + write(fd, &towrite, 1); + 4e4: 00100613 li a2,1 + 4e8: 00f10593 addi a1,sp,15 + 4ec: 00090513 mv a0,s2 + towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA)); + 4f0: 00f107a3 sb a5,15(sp) + write(fd, &towrite, 1); + 4f4: e35ff0ef jal ra,328 <__wrap_write> + for (ii = 8 ; ii > 0; ii--) { + 4f8: fd3414e3 bne s0,s3,4c0 + } +} + 4fc: 02c12083 lw ra,44(sp) + 500: 02812403 lw s0,40(sp) + 504: 02412483 lw s1,36(sp) + 508: 02012903 lw s2,32(sp) + 50c: 01c12983 lw s3,28(sp) + 510: 01812a03 lw s4,24(sp) + 514: 01412a83 lw s5,20(sp) + 518: 03010113 addi sp,sp,48 + 51c: 00008067 ret + +00000520 : +} + +static void sprintf_putch(int ch, void** data) +{ + char** pstr = (char**)data; + **pstr = ch; + 520: 0005a783 lw a5,0(a1) + 524: 00a78023 sb a0,0(a5) + (*pstr)++; + 528: 0005a783 lw a5,0(a1) + 52c: 00178793 addi a5,a5,1 + 530: 00f5a023 sw a5,0(a1) +} + 534: 00008067 ret + +00000538 : +{ + 538: fe010113 addi sp,sp,-32 + 53c: 00a12623 sw a0,12(sp) + return write(STDOUT_FILENO, &ch, 1) == 1 ? ch : -1; + 540: 00100613 li a2,1 + 544: 00c10593 addi a1,sp,12 + 548: 00100513 li a0,1 +{ + 54c: 00112e23 sw ra,28(sp) + return write(STDOUT_FILENO, &ch, 1) == 1 ? ch : -1; + 550: dd9ff0ef jal ra,328 <__wrap_write> + 554: 00100793 li a5,1 + 558: 00f51a63 bne a0,a5,56c + 55c: 00c12503 lw a0,12(sp) +} + 560: 01c12083 lw ra,28(sp) + 564: 02010113 addi sp,sp,32 + 568: 00008067 ret + return write(STDOUT_FILENO, &ch, 1) == 1 ? ch : -1; + 56c: fff00513 li a0,-1 + 570: ff1ff06f j 560 + +00000574 : + for (char* p = buf; p < pbuf; p++) + putch(*p, putdat); +} + +static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap) +{ + 574: f1010113 addi sp,sp,-240 + 578: 0d512a23 sw s5,212(sp) + 57c: 40000ab7 lui s5,0x40000 + 580: fffa8793 addi a5,s5,-1 # 3fffffff <_sp+0x2fffbfff> + 584: 0d912223 sw s9,196(sp) + u.u &= ~(1ULL << 63); + 588: 80000cb7 lui s9,0x80000 + 58c: 00f12223 sw a5,4(sp) + 590: fffcc793 not a5,s9 +{ + 594: 0e812423 sw s0,232(sp) + 598: 0e912223 sw s1,228(sp) + 59c: 0f212023 sw s2,224(sp) + 5a0: 0d312e23 sw s3,220(sp) + 5a4: 0e112623 sw ra,236(sp) + 5a8: 0d412c23 sw s4,216(sp) + 5ac: 0d612823 sw s6,208(sp) + 5b0: 0d712623 sw s7,204(sp) + 5b4: 0d812423 sw s8,200(sp) + 5b8: 0da12023 sw s10,192(sp) + 5bc: 0bb12e23 sw s11,188(sp) + 5c0: 00050913 mv s2,a0 + 5c4: 00058493 mv s1,a1 + 5c8: 00060413 mv s0,a2 + 5cc: 00d12023 sw a3,0(sp) + unsigned long num; + int base, lflag, width, precision, altflag; + char padc; + + while (1) { + while ((ch = *(unsigned char *) fmt) != '%') { + 5d0: 02500993 li s3,37 + u.u &= ~(1ULL << 63); + 5d4: 00f12423 sw a5,8(sp) + while ((ch = *(unsigned char *) fmt) != '%') { + 5d8: 0140006f j 5ec + if (ch == '\0') + 5dc: 06050263 beqz a0,640 + return; + fmt++; + putch(ch, putdat); + 5e0: 00048593 mv a1,s1 + fmt++; + 5e4: 00140413 addi s0,s0,1 + putch(ch, putdat); + 5e8: 000900e7 jalr s2 + while ((ch = *(unsigned char *) fmt) != '%') { + 5ec: 00044503 lbu a0,0(s0) + 5f0: ff3516e3 bne a0,s3,5dc + width = -1; + precision = -1; + lflag = 0; + altflag = 0; + reswitch: + switch (ch = *(unsigned char *) fmt++) { + 5f4: 00144683 lbu a3,1(s0) + fmt++; + 5f8: 00140d93 addi s11,s0,1 + 5fc: 000d8713 mv a4,s11 + padc = ' '; + 600: 02000b93 li s7,32 + precision = -1; + 604: fff00d13 li s10,-1 + width = -1; + 608: fff00b13 li s6,-1 + switch (ch = *(unsigned char *) fmt++) { + 60c: 05500593 li a1,85 + case '8': + case '9': + for (precision = 0; ; ++fmt) { + precision = precision * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + 610: 00900513 li a0,9 + switch (ch = *(unsigned char *) fmt++) { + 614: fdd68793 addi a5,a3,-35 + 618: 0ff7f793 zext.b a5,a5 + 61c: 00170413 addi s0,a4,1 + 620: 06f5ec63 bltu a1,a5,698 + 624: 00001617 auipc a2,0x1 + 628: edc60613 addi a2,a2,-292 # 1500 <__clzsi2+0xbc> + 62c: 00279793 slli a5,a5,0x2 + 630: 00c787b3 add a5,a5,a2 + 634: 0007a783 lw a5,0(a5) + 638: 00c787b3 add a5,a5,a2 + 63c: 00078067 jr a5 + putch('%', putdat); + fmt = last_fmt; + break; + } + } +} + 640: 0ec12083 lw ra,236(sp) + 644: 0e812403 lw s0,232(sp) + 648: 0e412483 lw s1,228(sp) + 64c: 0e012903 lw s2,224(sp) + 650: 0dc12983 lw s3,220(sp) + 654: 0d812a03 lw s4,216(sp) + 658: 0d412a83 lw s5,212(sp) + 65c: 0d012b03 lw s6,208(sp) + 660: 0cc12b83 lw s7,204(sp) + 664: 0c812c03 lw s8,200(sp) + 668: 0c412c83 lw s9,196(sp) + 66c: 0c012d03 lw s10,192(sp) + 670: 0bc12d83 lw s11,188(sp) + 674: 0f010113 addi sp,sp,240 + 678: 00008067 ret + padc = '0'; + 67c: 00068b93 mv s7,a3 + goto reswitch; + 680: 00174683 lbu a3,1(a4) + switch (ch = *(unsigned char *) fmt++) { + 684: 00040713 mv a4,s0 + 688: 00170413 addi s0,a4,1 + 68c: fdd68793 addi a5,a3,-35 + 690: 0ff7f793 zext.b a5,a5 + 694: f8f5f8e3 bgeu a1,a5,624 + putch('%', putdat); + 698: 00048593 mv a1,s1 + 69c: 02500513 li a0,37 + 6a0: 000900e7 jalr s2 + fmt = last_fmt; + 6a4: 000d8413 mv s0,s11 + break; + 6a8: f45ff06f j 5ec + ch = *fmt; + 6ac: 00174683 lbu a3,1(a4) + switch (ch = *(unsigned char *) fmt++) { + 6b0: 00040713 mv a4,s0 + goto reswitch; + 6b4: f61ff06f j 614 + ch = *fmt; + 6b8: 00174603 lbu a2,1(a4) + precision = precision * 10 + ch - '0'; + 6bc: fd068d13 addi s10,a3,-48 + switch (ch = *(unsigned char *) fmt++) { + 6c0: 00040713 mv a4,s0 + if (ch < '0' || ch > '9') + 6c4: fd060793 addi a5,a2,-48 + ch = *fmt; + 6c8: 00060693 mv a3,a2 + if (ch < '0' || ch > '9') + 6cc: 02f56663 bltu a0,a5,6f8 + precision = precision * 10 + ch - '0'; + 6d0: 002d1793 slli a5,s10,0x2 + 6d4: 01a787b3 add a5,a5,s10 + for (precision = 0; ; ++fmt) { + 6d8: 00170713 addi a4,a4,1 + precision = precision * 10 + ch - '0'; + 6dc: 00179793 slli a5,a5,0x1 + 6e0: 00c787b3 add a5,a5,a2 + ch = *fmt; + 6e4: 00074603 lbu a2,0(a4) + precision = precision * 10 + ch - '0'; + 6e8: fd078d13 addi s10,a5,-48 + if (ch < '0' || ch > '9') + 6ec: fd060793 addi a5,a2,-48 + ch = *fmt; + 6f0: 00060693 mv a3,a2 + if (ch < '0' || ch > '9') + 6f4: fcf57ee3 bgeu a0,a5,6d0 + if (width < 0) + 6f8: f00b5ee3 bgez s6,614 + width = precision, precision = -1; + 6fc: 000d0b13 mv s6,s10 + 700: fff00d13 li s10,-1 + 704: f11ff06f j 614 + putch(ch, putdat); + 708: 00048593 mv a1,s1 + 70c: 02500513 li a0,37 + 710: 000900e7 jalr s2 + break; + 714: ed9ff06f j 5ec + precision = va_arg(ap, int); + 718: 00012783 lw a5,0(sp) + ch = *fmt; + 71c: 00174683 lbu a3,1(a4) + switch (ch = *(unsigned char *) fmt++) { + 720: 00040713 mv a4,s0 + precision = va_arg(ap, int); + 724: 0007ad03 lw s10,0(a5) + 728: 00478793 addi a5,a5,4 + 72c: 00f12023 sw a5,0(sp) + goto process_precision; + 730: fc9ff06f j 6f8 + switch (ch = *(unsigned char *) fmt++) { + 734: 01000a93 li s5,16 + return va_arg(*ap, unsigned int); + 738: 00012783 lw a5,0(sp) + 73c: 0007ac03 lw s8,0(a5) + 740: 00478793 addi a5,a5,4 + 744: 00f12023 sw a5,0(sp) + digs[pos++] = num % base; + 748: 000a8593 mv a1,s5 + 74c: 000c0513 mv a0,s8 + 750: 491000ef jal ra,13e0 <__umodsi3> + 754: 02a12823 sw a0,48(sp) + 758: 00050d13 mv s10,a0 + 75c: 03410a13 addi s4,sp,52 + 760: 00100c93 li s9,1 + if (num < base) + 764: 355c6e63 bltu s8,s5,ac0 <__stack_size+0x2c0> + num /= base; + 768: 000a8593 mv a1,s5 + 76c: 000c0513 mv a0,s8 + 770: 429000ef jal ra,1398 <__udivsi3> + digs[pos++] = num % base; + 774: 000a8593 mv a1,s5 + num /= base; + 778: 00050c13 mv s8,a0 + digs[pos++] = num % base; + 77c: 465000ef jal ra,13e0 <__umodsi3> + 780: 00aa2023 sw a0,0(s4) + 784: 000c8d93 mv s11,s9 + 788: 00050d13 mv s10,a0 + if (num < base) + 78c: 004a0a13 addi s4,s4,4 + digs[pos++] = num % base; + 790: 001c8c93 addi s9,s9,1 # 80000001 + if (num < base) + 794: fd5c7ae3 bgeu s8,s5,768 + while (width-- > pos) + 798: 016cdc63 bge s9,s6,7b0 + 79c: fffb0b13 addi s6,s6,-1 + putch(padc, putdat); + 7a0: 00048593 mv a1,s1 + 7a4: 000b8513 mv a0,s7 + 7a8: 000900e7 jalr s2 + while (width-- > pos) + 7ac: ff6cc8e3 blt s9,s6,79c + 7b0: 00412783 lw a5,4(sp) + 7b4: 02c10b93 addi s7,sp,44 + putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat); + 7b8: 00900b13 li s6,9 + 7bc: 00fd8db3 add s11,s11,a5 + 7c0: 002d9d93 slli s11,s11,0x2 + 7c4: 03010793 addi a5,sp,48 + 7c8: 01b78db3 add s11,a5,s11 + 7cc: 00c0006f j 7d8 + 7d0: 000dad03 lw s10,0(s11) + 7d4: ffcd8d93 addi s11,s11,-4 + 7d8: 01ab37b3 sltu a5,s6,s10 + 7dc: 40f007b3 neg a5,a5 + 7e0: 0277f793 andi a5,a5,39 + 7e4: 03078793 addi a5,a5,48 + 7e8: 00048593 mv a1,s1 + 7ec: 01a78533 add a0,a5,s10 + 7f0: 000900e7 jalr s2 + while (pos-- > 0) + 7f4: fdbb9ee3 bne s7,s11,7d0 + 7f8: df5ff06f j 5ec + if ((p = va_arg(ap, char *)) == NULL) + 7fc: 00012783 lw a5,0(sp) + 800: 0007ad83 lw s11,0(a5) + 804: 00478a13 addi s4,a5,4 + 808: 2e0d8c63 beqz s11,b00 <__stack_size+0x300> + if (width > 0 && padc != '-') + 80c: 0b605263 blez s6,8b0 <__stack_size+0xb0> + 810: 02d00793 li a5,45 + 814: 04fb9e63 bne s7,a5,870 <__stack_size+0x70> + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + 818: 000dc503 lbu a0,0(s11) + 81c: 02050863 beqz a0,84c <__stack_size+0x4c> + 820: fff00b93 li s7,-1 + 824: 000d4663 bltz s10,830 <__stack_size+0x30> + 828: fffd0d13 addi s10,s10,-1 + 82c: 017d0e63 beq s10,s7,848 <__stack_size+0x48> + putch(ch, putdat); + 830: 00048593 mv a1,s1 + p++; + 834: 001d8d93 addi s11,s11,1 + putch(ch, putdat); + 838: 000900e7 jalr s2 + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + 83c: 000dc503 lbu a0,0(s11) + 840: fffb0b13 addi s6,s6,-1 + 844: fe0510e3 bnez a0,824 <__stack_size+0x24> + for (; width > 0; width--) + 848: 01605c63 blez s6,860 <__stack_size+0x60> + 84c: fffb0b13 addi s6,s6,-1 + putch(' ', putdat); + 850: 00048593 mv a1,s1 + 854: 02000513 li a0,32 + 858: 000900e7 jalr s2 + for (; width > 0; width--) + 85c: fe0b18e3 bnez s6,84c <__stack_size+0x4c> + if ((p = va_arg(ap, char *)) == NULL) + 860: 01412023 sw s4,0(sp) + 864: d89ff06f j 5ec + p = "(null)"; + 868: 00001d97 auipc s11,0x1 + 86c: c90d8d93 addi s11,s11,-880 # 14f8 <__clzsi2+0xb4> + while (n-- > 0 && *str) str++; + 870: 000d8793 mv a5,s11 + 874: 01ad86b3 add a3,s11,s10 + 878: 000d1863 bnez s10,888 <__stack_size+0x88> + 87c: 0200006f j 89c <__stack_size+0x9c> + 880: 00178793 addi a5,a5,1 + 884: 00d78663 beq a5,a3,890 <__stack_size+0x90> + 888: 0007c703 lbu a4,0(a5) + 88c: fe071ae3 bnez a4,880 <__stack_size+0x80> + return str - start; + 890: 41b787b3 sub a5,a5,s11 + for (width -= strnlen(p, precision); width > 0; width--) + 894: 40fb0b33 sub s6,s6,a5 + 898: 01605c63 blez s6,8b0 <__stack_size+0xb0> + 89c: fffb0b13 addi s6,s6,-1 + putch(padc, putdat); + 8a0: 00048593 mv a1,s1 + 8a4: 000b8513 mv a0,s7 + 8a8: 000900e7 jalr s2 + for (width -= strnlen(p, precision); width > 0; width--) + 8ac: fe0b18e3 bnez s6,89c <__stack_size+0x9c> + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + 8b0: 000dc503 lbu a0,0(s11) + 8b4: fa0506e3 beqz a0,860 <__stack_size+0x60> + 8b8: fff00b93 li s7,-1 + 8bc: f69ff06f j 824 <__stack_size+0x24> + putch(va_arg(ap, int), putdat); + 8c0: 00012783 lw a5,0(sp) + 8c4: 00048593 mv a1,s1 + 8c8: 0007a503 lw a0,0(a5) + 8cc: 00478a13 addi s4,a5,4 + 8d0: 000900e7 jalr s2 + 8d4: 01412023 sw s4,0(sp) + break; + 8d8: d15ff06f j 5ec + return va_arg(*ap, int); + 8dc: 00012783 lw a5,0(sp) + 8e0: 0007ac03 lw s8,0(a5) + 8e4: 00478a13 addi s4,a5,4 + if ((long) num < 0) { + 8e8: 000c5a63 bgez s8,8fc <__stack_size+0xfc> + putch('-', putdat); + 8ec: 00048593 mv a1,s1 + 8f0: 02d00513 li a0,45 + 8f4: 000900e7 jalr s2 + num = -(long) num; + 8f8: 41800c33 neg s8,s8 + return va_arg(*ap, int); + 8fc: 01412023 sw s4,0(sp) + num = -(long) num; + 900: 00a00a93 li s5,10 + 904: e45ff06f j 748 + print_double(putch, putdat, va_arg(ap, double), width, precision); + 908: 00012783 lw a5,0(sp) + 90c: 00778a13 addi s4,a5,7 + 910: ff8a7a13 andi s4,s4,-8 + 914: 004a2d83 lw s11,4(s4) + 918: 000a2a83 lw s5,0(s4) + 91c: 008a0793 addi a5,s4,8 + 920: 00f12023 sw a5,0(sp) + u.d = num; + 924: 000d8713 mv a4,s11 + 928: 000a8693 mv a3,s5 + if (u.u & (1ULL << 63)) { + 92c: 1a0dc063 bltz s11,acc <__stack_size+0x2cc> + for (int i = 0; i < prec; i++) + 930: 05a05263 blez s10,974 <__stack_size+0x174> + 934: 0ffff797 auipc a5,0xffff + 938: 6cc78793 addi a5,a5,1740 # 10000000 <_data> + u.d *= 10; + 93c: 0007ab03 lw s6,0(a5) + 940: 0047ab83 lw s7,4(a5) + for (int i = 0; i < prec; i++) + 944: 00000a13 li s4,0 + u.d *= 10; + 948: 00068513 mv a0,a3 + 94c: 00070593 mv a1,a4 + 950: 000b8693 mv a3,s7 + 954: 000b0613 mv a2,s6 + 958: 2cc000ef jal ra,c24 <__muldf3> + for (int i = 0; i < prec; i++) + 95c: 001a0a13 addi s4,s4,1 + u.d *= 10; + 960: 00050a93 mv s5,a0 + 964: 00058d93 mv s11,a1 + 968: 00050693 mv a3,a0 + 96c: 00058713 mv a4,a1 + for (int i = 0; i < prec; i++) + 970: fd4d1ce3 bne s10,s4,948 <__stack_size+0x148> + printnum(sprintf_putch, (void**)&pbuf, (unsigned long)u.d, 10, 0, 0); + 974: 000d8593 mv a1,s11 + 978: 000a8513 mv a0,s5 + 97c: 175000ef jal ra,12f0 <__fixunsdfsi> + digs[pos++] = num % base; + 980: 00a00593 li a1,10 + printnum(sprintf_putch, (void**)&pbuf, (unsigned long)u.d, 10, 0, 0); + 984: 00050b13 mv s6,a0 + digs[pos++] = num % base; + 988: 259000ef jal ra,13e0 <__umodsi3> + 98c: 02a12823 sw a0,48(sp) + if (num < base) + 990: 00900793 li a5,9 + 994: 1967f663 bgeu a5,s6,b20 <__stack_size+0x320> + 998: 03410a13 addi s4,sp,52 + digs[pos++] = num % base; + 99c: 00100d93 li s11,1 + if (num < base) + 9a0: 06300b93 li s7,99 + num /= base; + 9a4: 00a00593 li a1,10 + 9a8: 000b0513 mv a0,s6 + 9ac: 1ed000ef jal ra,1398 <__udivsi3> + digs[pos++] = num % base; + 9b0: 00a00593 li a1,10 + 9b4: 000b0a93 mv s5,s6 + num /= base; + 9b8: 00050b13 mv s6,a0 + digs[pos++] = num % base; + 9bc: 225000ef jal ra,13e0 <__umodsi3> + 9c0: 00aa2023 sw a0,0(s4) + 9c4: 000d8613 mv a2,s11 + if (num < base) + 9c8: 004a0a13 addi s4,s4,4 + digs[pos++] = num % base; + 9cc: 001d8d93 addi s11,s11,1 + if (num < base) + 9d0: fd5beae3 bltu s7,s5,9a4 <__stack_size+0x1a4> + 9d4: 03010813 addi a6,sp,48 + 9d8: 00261713 slli a4,a2,0x2 + 9dc: 00e80733 add a4,a6,a4 + putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat); + 9e0: 01010693 addi a3,sp,16 + 9e4: 00900893 li a7,9 + 9e8: 00c0006f j 9f4 <__stack_size+0x1f4> + 9ec: ffc72503 lw a0,-4(a4) + 9f0: 00058713 mv a4,a1 + 9f4: 00a8b7b3 sltu a5,a7,a0 + 9f8: 40f007b3 neg a5,a5 + 9fc: 0277f793 andi a5,a5,39 + a00: 03078793 addi a5,a5,48 + a04: 00a787b3 add a5,a5,a0 + **pstr = ch; + a08: 0ff7f793 zext.b a5,a5 + a0c: 00f68023 sb a5,0(a3) + while (pos-- > 0) + a10: ffc70593 addi a1,a4,-4 + (*pstr)++; + a14: 00168693 addi a3,a3,1 + while (pos-- > 0) + a18: fce81ae3 bne a6,a4,9ec <__stack_size+0x1ec> + (*pstr)++; + a1c: 01160713 addi a4,a2,17 + a20: 00270bb3 add s7,a4,sp + if (prec > 0) { + a24: 03a05a63 blez s10,a58 <__stack_size+0x258> + a28: 000b8713 mv a4,s7 + a2c: 41ab86b3 sub a3,s7,s10 + a30: 0080006f j a38 <__stack_size+0x238> + pbuf[-i] = pbuf[-i-1]; + a34: fff74783 lbu a5,-1(a4) + a38: 00f70023 sb a5,0(a4) + for (int i = 0; i < prec; i++) { + a3c: fff70713 addi a4,a4,-1 + a40: fed71ae3 bne a4,a3,a34 <__stack_size+0x234> + pbuf[-prec] = '.'; + a44: 41ab8bb3 sub s7,s7,s10 + a48: 02e00793 li a5,46 + a4c: 00fb8023 sb a5,0(s7) + pbuf++; + a50: 01260793 addi a5,a2,18 + a54: 00278bb3 add s7,a5,sp + for (char* p = buf; p < pbuf; p++) + a58: 01010b13 addi s6,sp,16 + a5c: b97b78e3 bgeu s6,s7,5ec + putch(*p, putdat); + a60: 000b4503 lbu a0,0(s6) + a64: 00048593 mv a1,s1 + for (char* p = buf; p < pbuf; p++) + a68: 001b0b13 addi s6,s6,1 + putch(*p, putdat); + a6c: 000900e7 jalr s2 + for (char* p = buf; p < pbuf; p++) + a70: ff7b18e3 bne s6,s7,a60 <__stack_size+0x260> + a74: b79ff06f j 5ec + putch('0', putdat); + a78: 03000513 li a0,48 + a7c: 00048593 mv a1,s1 + a80: 000900e7 jalr s2 + putch('x', putdat); + a84: 00048593 mv a1,s1 + a88: 07800513 li a0,120 + a8c: 000900e7 jalr s2 + return va_arg(*ap, unsigned long); + a90: 00012783 lw a5,0(sp) + a94: 01000a93 li s5,16 + a98: 00478793 addi a5,a5,4 + a9c: 00f12023 sw a5,0(sp) + aa0: ffc7ac03 lw s8,-4(a5) + aa4: ca5ff06f j 748 + if (width < 0) + aa8: fffb4793 not a5,s6 + aac: 41f7d793 srai a5,a5,0x1f + ch = *fmt; + ab0: 00174683 lbu a3,1(a4) + ab4: 00fb7b33 and s6,s6,a5 + switch (ch = *(unsigned char *) fmt++) { + ab8: 00040713 mv a4,s0 + goto reswitch; + abc: b59ff06f j 614 + while (width-- > pos) + ac0: 00000d93 li s11,0 + ac4: cd6ccce3 blt s9,s6,79c + ac8: ce9ff06f j 7b0 + putch('-', putdat); + acc: 00048593 mv a1,s1 + ad0: 02d00513 li a0,45 + ad4: 01512623 sw s5,12(sp) + ad8: 000900e7 jalr s2 + u.u &= ~(1ULL << 63); + adc: 00812783 lw a5,8(sp) + printnum(sprintf_putch, (void**)&pbuf, (unsigned long)u.d, 10, 0, 0); + ae0: 00c12683 lw a3,12(sp) + u.u &= ~(1ULL << 63); + ae4: 01b7f733 and a4,a5,s11 + printnum(sprintf_putch, (void**)&pbuf, (unsigned long)u.d, 10, 0, 0); + ae8: 00070d93 mv s11,a4 + aec: e45ff06f j 930 <__stack_size+0x130> + switch (ch = *(unsigned char *) fmt++) { + af0: 00800a93 li s5,8 + af4: c45ff06f j 738 + af8: 00a00a93 li s5,10 + afc: c3dff06f j 738 + if (width > 0 && padc != '-') + b00: 01605663 blez s6,b0c <__stack_size+0x30c> + b04: 02d00793 li a5,45 + b08: d6fb90e3 bne s7,a5,868 <__stack_size+0x68> + b0c: 00001d97 auipc s11,0x1 + b10: 9ecd8d93 addi s11,s11,-1556 # 14f8 <__clzsi2+0xb4> + for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { + b14: 02800513 li a0,40 + b18: fff00b93 li s7,-1 + b1c: d09ff06f j 824 <__stack_size+0x24> + while (pos-- > 0) + b20: 00000613 li a2,0 + b24: eb1ff06f j 9d4 <__stack_size+0x1d4> + +00000b28 : + while (n-- > 0 && *str) str++; + b28: 00b506b3 add a3,a0,a1 + b2c: 00050793 mv a5,a0 + b30: 00059863 bnez a1,b40 + b34: 0240006f j b58 + b38: 00178793 addi a5,a5,1 + b3c: 00f68a63 beq a3,a5,b50 + b40: 0007c703 lbu a4,0(a5) + b44: fe071ae3 bnez a4,b38 + return str - start; + b48: 40a78533 sub a0,a5,a0 +} + b4c: 00008067 ret + return str - start; + b50: 40a68533 sub a0,a3,a0 + b54: 00008067 ret + while (n-- > 0 && *str) str++; + b58: 00000513 li a0,0 + b5c: 00008067 ret + +00000b60 <__wrap_printf>: + +int __wrap_printf(const char* fmt, ...) +{ + b60: fc010113 addi sp,sp,-64 + va_list ap; + va_start(ap, fmt); + b64: 02410313 addi t1,sp,36 +{ + b68: 00050e13 mv t3,a0 + b6c: 02b12223 sw a1,36(sp) + b70: 02c12423 sw a2,40(sp) + b74: 02d12623 sw a3,44(sp) + + vprintfmt((void*)putchar, 0, fmt, ap); + b78: 00000517 auipc a0,0x0 + b7c: 9c050513 addi a0,a0,-1600 # 538 + b80: 00030693 mv a3,t1 + b84: 000e0613 mv a2,t3 + b88: 00000593 li a1,0 +{ + b8c: 00112e23 sw ra,28(sp) + b90: 02e12823 sw a4,48(sp) + b94: 02f12a23 sw a5,52(sp) + b98: 03012c23 sw a6,56(sp) + b9c: 03112e23 sw a7,60(sp) + va_start(ap, fmt); + ba0: 00612623 sw t1,12(sp) + vprintfmt((void*)putchar, 0, fmt, ap); + ba4: 9d1ff0ef jal ra,574 + + va_end(ap); + return 0; // incorrect return value, but who cares, anyway? +} + ba8: 01c12083 lw ra,28(sp) + bac: 00000513 li a0,0 + bb0: 04010113 addi sp,sp,64 + bb4: 00008067 ret + +00000bb8 <__wrap_sprintf>: + +int __wrap_sprintf(char* str, const char* fmt, ...) +{ + bb8: fb010113 addi sp,sp,-80 + va_list ap; + char* str0 = str; + va_start(ap, fmt); + bbc: 03810313 addi t1,sp,56 +{ + bc0: 02812423 sw s0,40(sp) + bc4: 00a12623 sw a0,12(sp) + bc8: 02c12c23 sw a2,56(sp) + bcc: 02d12e23 sw a3,60(sp) + char* str0 = str; + bd0: 00050413 mv s0,a0 + + vprintfmt(sprintf_putch, (void**)&str, fmt, ap); + bd4: 00058613 mv a2,a1 + bd8: 00000517 auipc a0,0x0 + bdc: 94850513 addi a0,a0,-1720 # 520 + be0: 00c10593 addi a1,sp,12 + be4: 00030693 mv a3,t1 +{ + be8: 02112623 sw ra,44(sp) + bec: 04f12223 sw a5,68(sp) + bf0: 04e12023 sw a4,64(sp) + bf4: 05012423 sw a6,72(sp) + bf8: 05112623 sw a7,76(sp) + va_start(ap, fmt); + bfc: 00612e23 sw t1,28(sp) + vprintfmt(sprintf_putch, (void**)&str, fmt, ap); + c00: 975ff0ef jal ra,574 + *str = 0; + c04: 00c12783 lw a5,12(sp) + c08: 00078023 sb zero,0(a5) + + va_end(ap); + return str - str0; + c0c: 00c12503 lw a0,12(sp) +} + c10: 02c12083 lw ra,44(sp) + c14: 40850533 sub a0,a0,s0 + c18: 02812403 lw s0,40(sp) + c1c: 05010113 addi sp,sp,80 + c20: 00008067 ret + +00000c24 <__muldf3>: +#include "soft-fp.h" +#include "double.h" + +DFtype +__muldf3 (DFtype a, DFtype b) +{ + c24: fd010113 addi sp,sp,-48 + c28: 01312e23 sw s3,28(sp) + FP_DECL_D (B); + FP_DECL_D (R); + DFtype r; + + FP_INIT_ROUNDMODE; + FP_UNPACK_D (A, a); + c2c: 0145d993 srli s3,a1,0x14 +{ + c30: 02812423 sw s0,40(sp) + c34: 02912223 sw s1,36(sp) + c38: 01412c23 sw s4,24(sp) + c3c: 01512a23 sw s5,20(sp) + c40: 01712623 sw s7,12(sp) + FP_UNPACK_D (A, a); + c44: 00c59493 slli s1,a1,0xc +{ + c48: 02112623 sw ra,44(sp) + c4c: 03212023 sw s2,32(sp) + c50: 01612823 sw s6,16(sp) + FP_UNPACK_D (A, a); + c54: 7ff9f993 andi s3,s3,2047 +{ + c58: 00050413 mv s0,a0 + c5c: 00060b93 mv s7,a2 + c60: 00068a13 mv s4,a3 + FP_UNPACK_D (A, a); + c64: 00c4d493 srli s1,s1,0xc + c68: 01f5da93 srli s5,a1,0x1f + c6c: 3c098863 beqz s3,103c <__muldf3+0x418> + c70: 7ff00793 li a5,2047 + c74: 42f98663 beq s3,a5,10a0 <__muldf3+0x47c> + c78: 00349493 slli s1,s1,0x3 + c7c: 01d55793 srli a5,a0,0x1d + c80: 0097e7b3 or a5,a5,s1 + c84: 008004b7 lui s1,0x800 + c88: 0097e4b3 or s1,a5,s1 + c8c: 00351913 slli s2,a0,0x3 + c90: c0198993 addi s3,s3,-1023 + c94: 00000b13 li s6,0 + FP_UNPACK_D (B, b); + c98: 014a5713 srli a4,s4,0x14 + c9c: 00ca1413 slli s0,s4,0xc + ca0: 7ff77713 andi a4,a4,2047 + ca4: 00c45413 srli s0,s0,0xc + ca8: 01fa5a13 srli s4,s4,0x1f + cac: 42070663 beqz a4,10d8 <__muldf3+0x4b4> + cb0: 7ff00793 li a5,2047 + cb4: 48f70663 beq a4,a5,1140 <__muldf3+0x51c> + cb8: 00341413 slli s0,s0,0x3 + cbc: 01dbd793 srli a5,s7,0x1d + cc0: 0087e7b3 or a5,a5,s0 + cc4: 00800437 lui s0,0x800 + cc8: 0087e433 or s0,a5,s0 + ccc: c0170713 addi a4,a4,-1023 + cd0: 003b9793 slli a5,s7,0x3 + cd4: 00000613 li a2,0 + FP_MUL_D (R, A, B); + cd8: 00e989b3 add s3,s3,a4 + cdc: 002b1713 slli a4,s6,0x2 + ce0: 00c76733 or a4,a4,a2 + ce4: 00a00693 li a3,10 + ce8: 014ac833 xor a6,s5,s4 + cec: 00198893 addi a7,s3,1 + cf0: 4ce6c863 blt a3,a4,11c0 <__muldf3+0x59c> + cf4: 00200693 li a3,2 + cf8: 48e6c063 blt a3,a4,1178 <__muldf3+0x554> + cfc: fff70713 addi a4,a4,-1 + d00: 00100693 li a3,1 + d04: 48e6fc63 bgeu a3,a4,119c <__muldf3+0x578> + d08: 00010a37 lui s4,0x10 + d0c: fffa0393 addi t2,s4,-1 # ffff <_data_lma+0xe8a7> + d10: 0107d293 srli t0,a5,0x10 + d14: 00797e33 and t3,s2,t2 + d18: 0077f7b3 and a5,a5,t2 + d1c: 01095f93 srli t6,s2,0x10 + d20: 000e0513 mv a0,t3 + d24: 00078593 mv a1,a5 + d28: 644000ef jal ra,136c <__mulsi3> + d2c: 00050e93 mv t4,a0 + d30: 00028593 mv a1,t0 + d34: 000e0513 mv a0,t3 + d38: 634000ef jal ra,136c <__mulsi3> + d3c: 00050713 mv a4,a0 + d40: 00078593 mv a1,a5 + d44: 000f8513 mv a0,t6 + d48: 624000ef jal ra,136c <__mulsi3> + d4c: 00050913 mv s2,a0 + d50: 00028593 mv a1,t0 + d54: 000f8513 mv a0,t6 + d58: 614000ef jal ra,136c <__mulsi3> + d5c: 010ed313 srli t1,t4,0x10 + d60: 01270733 add a4,a4,s2 + d64: 00e30333 add t1,t1,a4 + d68: 00050f13 mv t5,a0 + d6c: 01237463 bgeu t1,s2,d74 <__muldf3+0x150> + d70: 01450f33 add t5,a0,s4 + d74: 01035913 srli s2,t1,0x10 + d78: 00737333 and t1,t1,t2 + d7c: 007efeb3 and t4,t4,t2 + d80: 01031313 slli t1,t1,0x10 + d84: 007473b3 and t2,s0,t2 + d88: 01d30333 add t1,t1,t4 + d8c: 01045a13 srli s4,s0,0x10 + d90: 000e0513 mv a0,t3 + d94: 00038593 mv a1,t2 + d98: 5d4000ef jal ra,136c <__mulsi3> + d9c: 00050e93 mv t4,a0 + da0: 000a0593 mv a1,s4 + da4: 000e0513 mv a0,t3 + da8: 5c4000ef jal ra,136c <__mulsi3> + dac: 00050e13 mv t3,a0 + db0: 00038593 mv a1,t2 + db4: 000f8513 mv a0,t6 + db8: 5b4000ef jal ra,136c <__mulsi3> + dbc: 00050413 mv s0,a0 + dc0: 000a0593 mv a1,s4 + dc4: 000f8513 mv a0,t6 + dc8: 5a4000ef jal ra,136c <__mulsi3> + dcc: 010ed713 srli a4,t4,0x10 + dd0: 008e0e33 add t3,t3,s0 + dd4: 01c70733 add a4,a4,t3 + dd8: 00050693 mv a3,a0 + ddc: 00877663 bgeu a4,s0,de8 <__muldf3+0x1c4> + de0: 00010637 lui a2,0x10 + de4: 00c506b3 add a3,a0,a2 + de8: 00010b37 lui s6,0x10 + dec: fffb0e13 addi t3,s6,-1 # ffff <_data_lma+0xe8a7> + df0: 01075f93 srli t6,a4,0x10 + df4: 01c77733 and a4,a4,t3 + df8: 01071713 slli a4,a4,0x10 + dfc: 01cefeb3 and t4,t4,t3 + e00: 01d70eb3 add t4,a4,t4 + e04: 01c4fe33 and t3,s1,t3 + e08: 00df8fb3 add t6,t6,a3 + e0c: 01d90933 add s2,s2,t4 + e10: 0104da93 srli s5,s1,0x10 + e14: 000e0513 mv a0,t3 + e18: 00078593 mv a1,a5 + e1c: 550000ef jal ra,136c <__mulsi3> + e20: 00050413 mv s0,a0 + e24: 00028593 mv a1,t0 + e28: 000e0513 mv a0,t3 + e2c: 540000ef jal ra,136c <__mulsi3> + e30: 00050493 mv s1,a0 + e34: 00078593 mv a1,a5 + e38: 000a8513 mv a0,s5 + e3c: 530000ef jal ra,136c <__mulsi3> + e40: 00050b93 mv s7,a0 + e44: 00028593 mv a1,t0 + e48: 000a8513 mv a0,s5 + e4c: 520000ef jal ra,136c <__mulsi3> + e50: 01045793 srli a5,s0,0x10 + e54: 017484b3 add s1,s1,s7 + e58: 009787b3 add a5,a5,s1 + e5c: 00050713 mv a4,a0 + e60: 0177f463 bgeu a5,s7,e68 <__muldf3+0x244> + e64: 01650733 add a4,a0,s6 + e68: 000104b7 lui s1,0x10 + e6c: fff48693 addi a3,s1,-1 # ffff <_data_lma+0xe8a7> + e70: 0107d293 srli t0,a5,0x10 + e74: 00e282b3 add t0,t0,a4 + e78: 00d7f733 and a4,a5,a3 + e7c: 00d47433 and s0,s0,a3 + e80: 01071713 slli a4,a4,0x10 + e84: 00870733 add a4,a4,s0 + e88: 000e0513 mv a0,t3 + e8c: 00038593 mv a1,t2 + e90: 4dc000ef jal ra,136c <__mulsi3> + e94: 00050413 mv s0,a0 + e98: 000a0593 mv a1,s4 + e9c: 000e0513 mv a0,t3 + ea0: 4cc000ef jal ra,136c <__mulsi3> + ea4: 00050e13 mv t3,a0 + ea8: 00038593 mv a1,t2 + eac: 000a8513 mv a0,s5 + eb0: 4bc000ef jal ra,136c <__mulsi3> + eb4: 00050393 mv t2,a0 + eb8: 000a0593 mv a1,s4 + ebc: 000a8513 mv a0,s5 + ec0: 4ac000ef jal ra,136c <__mulsi3> + ec4: 01045793 srli a5,s0,0x10 + ec8: 007e0e33 add t3,t3,t2 + ecc: 01c78e33 add t3,a5,t3 + ed0: 00050593 mv a1,a0 + ed4: 007e7463 bgeu t3,t2,edc <__muldf3+0x2b8> + ed8: 009505b3 add a1,a0,s1 + edc: 000106b7 lui a3,0x10 + ee0: fff68693 addi a3,a3,-1 # ffff <_data_lma+0xe8a7> + ee4: 00de77b3 and a5,t3,a3 + ee8: 00d47433 and s0,s0,a3 + eec: 01079793 slli a5,a5,0x10 + ef0: 012f0f33 add t5,t5,s2 + ef4: 008787b3 add a5,a5,s0 + ef8: 01df3eb3 sltu t4,t5,t4 + efc: 01f787b3 add a5,a5,t6 + f00: 01d78533 add a0,a5,t4 + f04: 00ef0f33 add t5,t5,a4 + f08: 00ef3733 sltu a4,t5,a4 + f0c: 005506b3 add a3,a0,t0 + f10: 00e68633 add a2,a3,a4 + f14: 01f7b433 sltu s0,a5,t6 + f18: 01d53533 sltu a0,a0,t4 + f1c: 010e5793 srli a5,t3,0x10 + f20: 00e63733 sltu a4,a2,a4 + f24: 00a46433 or s0,s0,a0 + f28: 0056b6b3 sltu a3,a3,t0 + f2c: 00f40433 add s0,s0,a5 + f30: 00e6e6b3 or a3,a3,a4 + f34: 00d40433 add s0,s0,a3 + f38: 00b40433 add s0,s0,a1 + f3c: 01765793 srli a5,a2,0x17 + f40: 00941413 slli s0,s0,0x9 + f44: 00f46433 or s0,s0,a5 + f48: 009f1793 slli a5,t5,0x9 + f4c: 0067e7b3 or a5,a5,t1 + f50: 00f037b3 snez a5,a5 + f54: 017f5f13 srli t5,t5,0x17 + f58: 00961713 slli a4,a2,0x9 + f5c: 01e7e7b3 or a5,a5,t5 + f60: 00e7e7b3 or a5,a5,a4 + f64: 01000737 lui a4,0x1000 + f68: 00e47733 and a4,s0,a4 + f6c: 28070663 beqz a4,11f8 <__muldf3+0x5d4> + f70: 0017d713 srli a4,a5,0x1 + f74: 0017f793 andi a5,a5,1 + f78: 00f76733 or a4,a4,a5 + f7c: 01f41793 slli a5,s0,0x1f + f80: 00f767b3 or a5,a4,a5 + f84: 00145413 srli s0,s0,0x1 + FP_PACK_D (r, R); + f88: 3ff88693 addi a3,a7,1023 + f8c: 26d05a63 blez a3,1200 <__muldf3+0x5dc> + f90: 0077f713 andi a4,a5,7 + f94: 02070063 beqz a4,fb4 <__muldf3+0x390> + f98: 00f7f713 andi a4,a5,15 + f9c: 00400613 li a2,4 + fa0: 00c70a63 beq a4,a2,fb4 <__muldf3+0x390> + fa4: 00478713 addi a4,a5,4 + fa8: 00f737b3 sltu a5,a4,a5 + fac: 00f40433 add s0,s0,a5 + fb0: 00070793 mv a5,a4 + fb4: 01000737 lui a4,0x1000 + fb8: 00e47733 and a4,s0,a4 + fbc: 00070a63 beqz a4,fd0 <__muldf3+0x3ac> + fc0: ff000737 lui a4,0xff000 + fc4: fff70713 addi a4,a4,-1 # feffffff + fc8: 00e47433 and s0,s0,a4 + fcc: 40088693 addi a3,a7,1024 + fd0: 7fe00713 li a4,2046 + fd4: 2ed74e63 blt a4,a3,12d0 <__muldf3+0x6ac> + fd8: 01d41713 slli a4,s0,0x1d + fdc: 0037d793 srli a5,a5,0x3 + fe0: 00f76733 or a4,a4,a5 + fe4: 00345413 srli s0,s0,0x3 + fe8: 7ff007b7 lui a5,0x7ff00 + fec: 01469693 slli a3,a3,0x14 + ff0: 00c41413 slli s0,s0,0xc + ff4: 00f6f6b3 and a3,a3,a5 + ff8: 00c45413 srli s0,s0,0xc + FP_HANDLE_EXCEPTIONS; + + return r; +} + ffc: 02c12083 lw ra,44(sp) + FP_PACK_D (r, R); + 1000: 0086e6b3 or a3,a3,s0 +} + 1004: 02812403 lw s0,40(sp) + FP_PACK_D (r, R); + 1008: 01f81813 slli a6,a6,0x1f + 100c: 0106e7b3 or a5,a3,a6 +} + 1010: 02412483 lw s1,36(sp) + 1014: 02012903 lw s2,32(sp) + 1018: 01c12983 lw s3,28(sp) + 101c: 01812a03 lw s4,24(sp) + 1020: 01412a83 lw s5,20(sp) + 1024: 01012b03 lw s6,16(sp) + 1028: 00c12b83 lw s7,12(sp) + 102c: 00070513 mv a0,a4 + 1030: 00078593 mv a1,a5 + 1034: 03010113 addi sp,sp,48 + 1038: 00008067 ret + FP_UNPACK_D (A, a); + 103c: 00a4e933 or s2,s1,a0 + 1040: 06090c63 beqz s2,10b8 <__muldf3+0x494> + 1044: 04048063 beqz s1,1084 <__muldf3+0x460> + 1048: 00048513 mv a0,s1 + 104c: 3f8000ef jal ra,1444 <__clzsi2> + 1050: ff550713 addi a4,a0,-11 + 1054: 01c00793 li a5,28 + 1058: 02e7cc63 blt a5,a4,1090 <__muldf3+0x46c> + 105c: 01d00793 li a5,29 + 1060: ff850913 addi s2,a0,-8 + 1064: 40e787b3 sub a5,a5,a4 + 1068: 012494b3 sll s1,s1,s2 + 106c: 00f457b3 srl a5,s0,a5 + 1070: 0097e4b3 or s1,a5,s1 + 1074: 01241933 sll s2,s0,s2 + 1078: c0d00993 li s3,-1011 + 107c: 40a989b3 sub s3,s3,a0 + 1080: c15ff06f j c94 <__muldf3+0x70> + 1084: 3c0000ef jal ra,1444 <__clzsi2> + 1088: 02050513 addi a0,a0,32 + 108c: fc5ff06f j 1050 <__muldf3+0x42c> + 1090: fd850493 addi s1,a0,-40 + 1094: 009414b3 sll s1,s0,s1 + 1098: 00000913 li s2,0 + 109c: fddff06f j 1078 <__muldf3+0x454> + 10a0: 00a4e933 or s2,s1,a0 + 10a4: 02090263 beqz s2,10c8 <__muldf3+0x4a4> + 10a8: 00050913 mv s2,a0 + 10ac: 7ff00993 li s3,2047 + 10b0: 00300b13 li s6,3 + 10b4: be5ff06f j c98 <__muldf3+0x74> + 10b8: 00000493 li s1,0 + 10bc: 00000993 li s3,0 + 10c0: 00100b13 li s6,1 + 10c4: bd5ff06f j c98 <__muldf3+0x74> + 10c8: 00000493 li s1,0 + 10cc: 7ff00993 li s3,2047 + 10d0: 00200b13 li s6,2 + 10d4: bc5ff06f j c98 <__muldf3+0x74> + FP_UNPACK_D (B, b); + 10d8: 017467b3 or a5,s0,s7 + 10dc: 06078e63 beqz a5,1158 <__muldf3+0x534> + 10e0: 04040063 beqz s0,1120 <__muldf3+0x4fc> + 10e4: 00040513 mv a0,s0 + 10e8: 35c000ef jal ra,1444 <__clzsi2> + 10ec: ff550693 addi a3,a0,-11 + 10f0: 01c00793 li a5,28 + 10f4: 02d7ce63 blt a5,a3,1130 <__muldf3+0x50c> + 10f8: 01d00713 li a4,29 + 10fc: ff850793 addi a5,a0,-8 + 1100: 40d70733 sub a4,a4,a3 + 1104: 00f41433 sll s0,s0,a5 + 1108: 00ebd733 srl a4,s7,a4 + 110c: 00876433 or s0,a4,s0 + 1110: 00fb97b3 sll a5,s7,a5 + 1114: c0d00713 li a4,-1011 + 1118: 40a70733 sub a4,a4,a0 + 111c: bb9ff06f j cd4 <__muldf3+0xb0> + 1120: 000b8513 mv a0,s7 + 1124: 320000ef jal ra,1444 <__clzsi2> + 1128: 02050513 addi a0,a0,32 + 112c: fc1ff06f j 10ec <__muldf3+0x4c8> + 1130: fd850413 addi s0,a0,-40 + 1134: 008b9433 sll s0,s7,s0 + 1138: 00000793 li a5,0 + 113c: fd9ff06f j 1114 <__muldf3+0x4f0> + 1140: 017467b3 or a5,s0,s7 + 1144: 02078263 beqz a5,1168 <__muldf3+0x544> + 1148: 000b8793 mv a5,s7 + 114c: 7ff00713 li a4,2047 + 1150: 00300613 li a2,3 + 1154: b85ff06f j cd8 <__muldf3+0xb4> + 1158: 00000413 li s0,0 + 115c: 00000713 li a4,0 + 1160: 00100613 li a2,1 + 1164: b75ff06f j cd8 <__muldf3+0xb4> + 1168: 00000413 li s0,0 + 116c: 7ff00713 li a4,2047 + 1170: 00200613 li a2,2 + 1174: b65ff06f j cd8 <__muldf3+0xb4> + 1178: 00100693 li a3,1 + 117c: 00e696b3 sll a3,a3,a4 + 1180: 5306f713 andi a4,a3,1328 + 1184: 04071863 bnez a4,11d4 <__muldf3+0x5b0> + 1188: 2406f593 andi a1,a3,576 + 118c: 12059463 bnez a1,12b4 <__muldf3+0x690> + 1190: 0886f693 andi a3,a3,136 + 1194: b6068ae3 beqz a3,d08 <__muldf3+0xe4> + 1198: 000a0813 mv a6,s4 + FP_PACK_D (r, R); + 119c: 00200713 li a4,2 + 11a0: 12e60863 beq a2,a4,12d0 <__muldf3+0x6ac> + 11a4: 00300713 li a4,3 + 11a8: 10e60e63 beq a2,a4,12c4 <__muldf3+0x6a0> + 11ac: 00100713 li a4,1 + 11b0: dce61ce3 bne a2,a4,f88 <__muldf3+0x364> + 11b4: 00000413 li s0,0 + 11b8: 00000713 li a4,0 + 11bc: 0bc0006f j 1278 <__muldf3+0x654> + FP_MUL_D (R, A, B); + 11c0: 00f00693 li a3,15 + 11c4: 02d70063 beq a4,a3,11e4 <__muldf3+0x5c0> + 11c8: 00b00693 li a3,11 + 11cc: fcd706e3 beq a4,a3,1198 <__muldf3+0x574> + FP_UNPACK_D (A, a); + 11d0: 000a8813 mv a6,s5 + FP_MUL_D (R, A, B); + 11d4: 00048413 mv s0,s1 + 11d8: 00090793 mv a5,s2 + 11dc: 000b0613 mv a2,s6 + 11e0: fbdff06f j 119c <__muldf3+0x578> + 11e4: 00080437 lui s0,0x80 + 11e8: 00000793 li a5,0 + 11ec: 00000813 li a6,0 + 11f0: 00300613 li a2,3 + 11f4: fb1ff06f j 11a4 <__muldf3+0x580> + 11f8: 00098893 mv a7,s3 + 11fc: d8dff06f j f88 <__muldf3+0x364> + FP_PACK_D (r, R); + 1200: 00100613 li a2,1 + 1204: 40d60633 sub a2,a2,a3 + 1208: 03800713 li a4,56 + 120c: fac744e3 blt a4,a2,11b4 <__muldf3+0x590> + 1210: 01f00713 li a4,31 + 1214: 06c74663 blt a4,a2,1280 <__muldf3+0x65c> + 1218: 41e88893 addi a7,a7,1054 + 121c: 01141733 sll a4,s0,a7 + 1220: 00c7d6b3 srl a3,a5,a2 + 1224: 011798b3 sll a7,a5,a7 + 1228: 00d76733 or a4,a4,a3 + 122c: 011038b3 snez a7,a7 + 1230: 011767b3 or a5,a4,a7 + 1234: 00c45433 srl s0,s0,a2 + 1238: 0077f713 andi a4,a5,7 + 123c: 02070063 beqz a4,125c <__muldf3+0x638> + 1240: 00f7f713 andi a4,a5,15 + 1244: 00400693 li a3,4 + 1248: 00d70a63 beq a4,a3,125c <__muldf3+0x638> + 124c: 00478713 addi a4,a5,4 # 7ff00004 <_sp+0x6fefc004> + 1250: 00f737b3 sltu a5,a4,a5 + 1254: 00f40433 add s0,s0,a5 + 1258: 00070793 mv a5,a4 + 125c: 00800737 lui a4,0x800 + 1260: 00e47733 and a4,s0,a4 + 1264: 06071e63 bnez a4,12e0 <__muldf3+0x6bc> + 1268: 01d41713 slli a4,s0,0x1d + 126c: 0037d793 srli a5,a5,0x3 + 1270: 00f76733 or a4,a4,a5 + 1274: 00345413 srli s0,s0,0x3 + 1278: 00000693 li a3,0 + 127c: d6dff06f j fe8 <__muldf3+0x3c4> + 1280: fe100713 li a4,-31 + 1284: 40d70733 sub a4,a4,a3 + 1288: 02000593 li a1,32 + 128c: 00e45733 srl a4,s0,a4 + 1290: 00000693 li a3,0 + 1294: 00b60663 beq a2,a1,12a0 <__muldf3+0x67c> + 1298: 43e88893 addi a7,a7,1086 + 129c: 011416b3 sll a3,s0,a7 + 12a0: 00f6e6b3 or a3,a3,a5 + 12a4: 00d036b3 snez a3,a3 + 12a8: 00d767b3 or a5,a4,a3 + 12ac: 00000413 li s0,0 + 12b0: f89ff06f j 1238 <__muldf3+0x614> + FP_MUL_D (R, A, B); + 12b4: 00080437 lui s0,0x80 + FP_PACK_D (r, R); + 12b8: 7ff00693 li a3,2047 + 12bc: 00000813 li a6,0 + 12c0: d29ff06f j fe8 <__muldf3+0x3c4> + 12c4: 00080437 lui s0,0x80 + 12c8: 00000713 li a4,0 + 12cc: fedff06f j 12b8 <__muldf3+0x694> + 12d0: 00000413 li s0,0 + 12d4: 00000713 li a4,0 + 12d8: 7ff00693 li a3,2047 + 12dc: d0dff06f j fe8 <__muldf3+0x3c4> + 12e0: 00000413 li s0,0 + 12e4: 00000713 li a4,0 + 12e8: 00100693 li a3,1 + 12ec: cfdff06f j fe8 <__muldf3+0x3c4> + +000012f0 <__fixunsdfsi>: + FP_DECL_EX; + FP_DECL_D (A); + USItype r; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_D (A, a); + 12f0: 0145d713 srli a4,a1,0x14 + 12f4: 00100637 lui a2,0x100 +{ + 12f8: 00050693 mv a3,a0 + FP_UNPACK_RAW_D (A, a); + 12fc: fff60793 addi a5,a2,-1 # fffff <_data_lma+0xfe8a7> + 1300: 7ff77713 andi a4,a4,2047 + FP_TO_INT_D (r, A, SI_BITS, 0); + 1304: 3fe00513 li a0,1022 + FP_UNPACK_RAW_D (A, a); + 1308: 00b7f7b3 and a5,a5,a1 + 130c: 01f5d593 srli a1,a1,0x1f + FP_TO_INT_D (r, A, SI_BITS, 0); + 1310: 04e55a63 bge a0,a4,1364 <__fixunsdfsi+0x74> + 1314: 00000513 li a0,0 + 1318: 00059863 bnez a1,1328 <__fixunsdfsi+0x38> + 131c: 41e00593 li a1,1054 + 1320: fff00513 li a0,-1 + 1324: 00e5d463 bge a1,a4,132c <__fixunsdfsi+0x3c> + FP_HANDLE_EXCEPTIONS; + + return r; +} + 1328: 00008067 ret + FP_TO_INT_D (r, A, SI_BITS, 0); + 132c: 00c7e7b3 or a5,a5,a2 + 1330: 43300613 li a2,1075 + 1334: 40e60633 sub a2,a2,a4 + 1338: 01f00593 li a1,31 + 133c: 00c5cc63 blt a1,a2,1354 <__fixunsdfsi+0x64> + 1340: bed70713 addi a4,a4,-1043 # 7ffbed <_data_lma+0x7fe495> + 1344: 00e797b3 sll a5,a5,a4 + 1348: 00c6d533 srl a0,a3,a2 + 134c: 00a7e533 or a0,a5,a0 + 1350: 00008067 ret + 1354: 41300693 li a3,1043 + 1358: 40e68733 sub a4,a3,a4 + 135c: 00e7d533 srl a0,a5,a4 + 1360: 00008067 ret + 1364: 00000513 li a0,0 + 1368: 00008067 ret + +0000136c <__mulsi3>: +/* Our RV64 64-bit routine is equivalent to our RV32 32-bit routine. */ +# define __muldi3 __mulsi3 +#endif + +FUNC_BEGIN (__muldi3) + mv a2, a0 + 136c: 00050613 mv a2,a0 + li a0, 0 + 1370: 00000513 li a0,0 +.L1: + andi a3, a1, 1 + 1374: 0015f693 andi a3,a1,1 + beqz a3, .L2 + 1378: 00068463 beqz a3,1380 <__mulsi3+0x14> + add a0, a0, a2 + 137c: 00c50533 add a0,a0,a2 +.L2: + srli a1, a1, 1 + 1380: 0015d593 srli a1,a1,0x1 + slli a2, a2, 1 + 1384: 00161613 slli a2,a2,0x1 + bnez a1, .L1 + 1388: fe0596e3 bnez a1,1374 <__mulsi3+0x8> + ret + 138c: 00008067 ret + +00001390 <__divsi3>: + li t0, -1 + beq a1, t0, .L20 +#endif + +FUNC_BEGIN (__divdi3) + bltz a0, .L10 + 1390: 06054063 bltz a0,13f0 <__umodsi3+0x10> + bltz a1, .L11 + 1394: 0605c663 bltz a1,1400 <__umodsi3+0x20> + +00001398 <__udivsi3>: + /* Since the quotient is positive, fall into __udivdi3. */ + +FUNC_BEGIN (__udivdi3) + mv a2, a1 + 1398: 00058613 mv a2,a1 + mv a1, a0 + 139c: 00050593 mv a1,a0 + li a0, -1 + 13a0: fff00513 li a0,-1 + beqz a2, .L5 + 13a4: 02060c63 beqz a2,13dc <__udivsi3+0x44> + li a3, 1 + 13a8: 00100693 li a3,1 + bgeu a2, a1, .L2 + 13ac: 00b67a63 bgeu a2,a1,13c0 <__udivsi3+0x28> +.L1: + blez a2, .L2 + 13b0: 00c05863 blez a2,13c0 <__udivsi3+0x28> + slli a2, a2, 1 + 13b4: 00161613 slli a2,a2,0x1 + slli a3, a3, 1 + 13b8: 00169693 slli a3,a3,0x1 + bgtu a1, a2, .L1 + 13bc: feb66ae3 bltu a2,a1,13b0 <__udivsi3+0x18> +.L2: + li a0, 0 + 13c0: 00000513 li a0,0 +.L3: + bltu a1, a2, .L4 + 13c4: 00c5e663 bltu a1,a2,13d0 <__udivsi3+0x38> + sub a1, a1, a2 + 13c8: 40c585b3 sub a1,a1,a2 + or a0, a0, a3 + 13cc: 00d56533 or a0,a0,a3 +.L4: + srli a3, a3, 1 + 13d0: 0016d693 srli a3,a3,0x1 + srli a2, a2, 1 + 13d4: 00165613 srli a2,a2,0x1 + bnez a3, .L3 + 13d8: fe0696e3 bnez a3,13c4 <__udivsi3+0x2c> +.L5: + ret + 13dc: 00008067 ret + +000013e0 <__umodsi3>: +FUNC_END (__udivdi3) + +FUNC_BEGIN (__umoddi3) + /* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */ + move t0, ra + 13e0: 00008293 mv t0,ra + jal __udivdi3 + 13e4: fb5ff0ef jal ra,1398 <__udivsi3> + move a0, a1 + 13e8: 00058513 mv a0,a1 + jr t0 + 13ec: 00028067 jr t0 +FUNC_END (__umoddi3) + + /* Handle negative arguments to __divdi3. */ +.L10: + neg a0, a0 + 13f0: 40a00533 neg a0,a0 + /* Zero is handled as a negative so that the result will not be inverted. */ + bgtz a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */ + 13f4: 00b04863 bgtz a1,1404 <__umodsi3+0x24> + + neg a1, a1 + 13f8: 40b005b3 neg a1,a1 + j __udivdi3 /* Compute __udivdi3(-a0, -a1). */ + 13fc: f9dff06f j 1398 <__udivsi3> +.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */ + neg a1, a1 + 1400: 40b005b3 neg a1,a1 +.L12: + move t0, ra + 1404: 00008293 mv t0,ra + jal __udivdi3 + 1408: f91ff0ef jal ra,1398 <__udivsi3> + neg a0, a0 + 140c: 40a00533 neg a0,a0 + jr t0 + 1410: 00028067 jr t0 + +00001414 <__modsi3>: +FUNC_END (__divdi3) + +FUNC_BEGIN (__moddi3) + move t0, ra + 1414: 00008293 mv t0,ra + bltz a1, .L31 + 1418: 0005ca63 bltz a1,142c <__modsi3+0x18> + bltz a0, .L32 + 141c: 00054c63 bltz a0,1434 <__modsi3+0x20> +.L30: + jal __udivdi3 /* The dividend is not negative. */ + 1420: f79ff0ef jal ra,1398 <__udivsi3> + move a0, a1 + 1424: 00058513 mv a0,a1 + jr t0 + 1428: 00028067 jr t0 +.L31: + neg a1, a1 + 142c: 40b005b3 neg a1,a1 + bgez a0, .L30 + 1430: fe0558e3 bgez a0,1420 <__modsi3+0xc> +.L32: + neg a0, a0 + 1434: 40a00533 neg a0,a0 + jal __udivdi3 /* The dividend is hella negative. */ + 1438: f61ff0ef jal ra,1398 <__udivsi3> + neg a0, a1 + 143c: 40b00533 neg a0,a1 + jr t0 + 1440: 00028067 jr t0 + +00001444 <__clzsi2>: +int +__clzSI2 (UWtype x) +{ + Wtype ret; + + count_leading_zeros (ret, x); + 1444: 000107b7 lui a5,0x10 + 1448: 02f57a63 bgeu a0,a5,147c <__clzsi2+0x38> + 144c: 10053793 sltiu a5,a0,256 + 1450: 0017c793 xori a5,a5,1 + 1454: 00379793 slli a5,a5,0x3 + 1458: 00001737 lui a4,0x1 + 145c: 02000693 li a3,32 + 1460: 40f686b3 sub a3,a3,a5 + 1464: 00f55533 srl a0,a0,a5 + 1468: 65870793 addi a5,a4,1624 # 1658 <__clz_tab> + 146c: 00a787b3 add a5,a5,a0 + 1470: 0007c503 lbu a0,0(a5) # 10000 <_data_lma+0xe8a8> + + return ret; +} + 1474: 40a68533 sub a0,a3,a0 + 1478: 00008067 ret + count_leading_zeros (ret, x); + 147c: 01000737 lui a4,0x1000 + 1480: 01000793 li a5,16 + 1484: fce56ae3 bltu a0,a4,1458 <__clzsi2+0x14> + 1488: 01800793 li a5,24 + 148c: fcdff06f j 1458 <__clzsi2+0x14> diff --git a/contrib/hello.elf b/contrib/hello.elf index 9b63df72a75d994b5d4fdb0d8ea230a51171fbb3..49c13150b44a2b2fba49f0c13604f3b7e07445db 100755 GIT binary patch literal 51556 zcmeIb4R}?>wKqO{@3Z$lCnukrknp7(NFb=>1A;{>)uaXirAiefhUg)jBqSOVngoeT z`Dpm6A1(G!;caQbTYIIqw%6O(%5A;(h8BzMV=LaO*w(k&i&fj&E8Z&53grL$&FtCd zoDdLiuh08F|CjS*_N=vL&6+i9)~uPm&+MEvGv{7q7>3XvQ~X&Fiy}=!diqIR@R5c9+tm1V>Z*jH3cF~r(bgj&f6^%zb#pBS{6j3y(8f||PIy9jDPeI>xX3_Zj z&7$H5&7z6_WEM@@YZhJjtXVYqw`Nh<+h$SJuu61J;Fx-FsoRZC$j^?!9QQZA~_u-pSRDRl3gUE#2!_Wro{ZR_$8l>)hV*y)JAN z>=Mxmj1BFj#)e~}#|L8*zkZjQ2n?5FG-!PC{PFQ@&vI#h&-Q;V$$hG8LT*3$|J0!` zy?c`5F@1v&GXLUs_=(*@*c+#TqT+QT;><%^w%7(=Ol){^Y{Z7YOw6P0?1&A&5Nop^ zXI;Y>NNliMln*?4p5n=Mx4Edd$^C8DmW35)zanweHRGFI@%U09y0*9#UGpkLZ*(u~ z8-v@%ILfvn>uva>gSLblH*F_=Z@{EqRtC3<>F&Tl!r28q4~X6pR~-7ed$M;w=0^0W zU>^U>K{K&oxH$9$dmyqQAlrgp(k_0Rx?WLqzvws|I}x!D4|E*fiTvGx$i)++J+|T5 zSz^d?5HR@ z|84dK{`;&^G=4A28;Bc4lMDm?i821Ic6L_N{0XwO2vO{dYC_2t6Dw|>yO|C{8pETHhB!qYn=r`Uv{POP;8HYtA zV~a?H`Ug5hm6c$Qo%Aa-uV{F3iYW`ecn3x}ibs^@}g@_M^VR7txAI7+? zeOTs+O@)YW?`mH>N#9m_!B^;mm>00u|7QG(k9t?eDzrgaD$d9;96JE~ZS+0s@eEOw z*!0%{*edJsOtH3T{M#b2|2Ta-8?~nSg(Bj9wQZVa*I6R$e^NdsV(jWaW#e#*ShrGY}hax zzME}bU}VFFS+HRiY?x(TWMm=6WLlHgW%f?4&a_I6%-+(yVe~(TwoTmQh~BFTMZ~3! zg?_t-j=g(K>TS<6sdr?37U#e_nz!Td*drF}-RGQO-Gu9$NH~s&H@|Bp3QM8e!$!n~ zJWLSkYhC4n*FB;64y}Io_@P_Eha=%E!M;P@+o|ngp8ct}#PD^qzU4x?8UX zxqFs~-tllt01j@zLT;gdztY6CWVaoc$q@B6ZTl7P?kZTyxIAAvCy0=mJ+HXan#e#FU9 z?#aGQk5^ZQ->XWKr~40i)a#IA|CM?{?h*EZI$2*={b2u8o3Us07|H(CWlFw?eL(6~ znYp%_e2I)*^sQIP8@YR>h}?PiKyT^QqW8iK*!6BX=5n5F%n}^K}auS>N zw^`qW|9^89#trjhgM;`4f7lqtTnS@r`zJ>-Mu|iQ=I4D#4#szrEe?(O#EHZP*bV-I z@h?o+SSP~tg)I~4Hwkx(h#y%xQud^Q2ZjtI6m@hJR7Og#kKI|VzY%IW7 zym36@78rfu5)rT4g_s(~xP7y_1N*ezSw{zo#8J%KqXUOV9X#20&o`?R?ki@|+V^0y ziALW&CD6|>4)xsi&(_SavU_;6^5GG8aoirq{!98K$4mOSz1Afx#}o5Q&o}Fl{os%N zG%*Wv;o#9~#(>JZ-jgu{a=x3$65`O)Z9fD2b0y~h_Gq7!e%@PxHFe@%QF-)nBa!9G zaZY4lpLsa8PmTM_KZ@VD*r3lJ+Vb8D%13|p)rh@T`aNVGh~P^n#D_ojIp0O!uy${^ z8C#X#-hIUPTg0Z;CG5o?`=wE*%S#99rxWzU-2 z7ezMOLdoB-HDP1Fj5e@_U=RCtpeXv=KvA)QeQF-|rj#Aq){DJ!5n{RAn_*3?v^P{C zrkiNX_S!nZH9PUknQ{+NgtZ;(k+*(-%1CT|(%VO1ZJ*R&B>wW3HPj;!b}*+fFP_^c z62E%ah;I(fNVtdB#5exs3#R9I^g7kob4k zs9b#q_7p2cA{N4Z0>);8i@8_Tn7|k&HkcThEkci~Kce;y=%AA=-e# zS5F^GY_PQaMbgGBSMAkB4x+v6&tcy0HyCf?x5GBLr|5H@6w||qZ`qhbG4yXG_JoD5 z(RcFaMql?8YzxcLdc zU$Wo*bCdmMoBh`$EVL>6E%B?_W@YwjQTaLa+oqjYi$42{;&JpnvGK@2-^$;}wi4UW zR!%u|+a&rfe;N5vqjCfKpYxWeoc7ZI#f57|j)Lw~iFn3-tQ)f+_o!??;krqA z84@0#A6It23K_wwi2KT#__YViB8ATxiG$N+JCXU*#N(KEi3hHNzWYSqkt1kxANOu% z-)kF%oa-ZwL05es66;bj3fMF8`qWt{gv*+RfzvT z;NA=RO;!4hJsyF6m0Rz@T0s4Fo{;T)#>IMoH5oRJI8who5$G2I5AP44&*KVbxzz7_ zj5~b~ye1+?og3mK+(6=8r#QaV9+o(=F?i^1=X;SL=CzAB6?|=2#H|qV?ALN5xUV=g z=Czl!Y^>?wgmW1Fg8ND5QS6Hj9*=BBz4Za;hkY~lA+X_l(*r@NZv_zHV>AX-Cao1XhYWDvXeK6uz?ROHJ->9xE%s2X8*f09F7aEmI4~o7^a^bIl8IM!^ zG$H-;;1GU_xJEB=|99fFHTrW>+Xi-71N=Y|=QzClOyuB9V>*hlsw$s|a<$9^&zzB96|* zzVz_Uqq;7657pWy$%j43kxJm?f7~^o8}7ZP+qsGTh;Q4bi|Kqe;Rv&DXme-Nr=ktr;E&F}Gecy|>+D$Cuq@ir(1l8^-A#?r zm95<^(RfE=(??OKqDP2H?JL^aE)e38w+9BcBL)9U<%D$_kwRMq`tEmC8R0!=k+huu zoAdrZ4-CA7L>+_gB>SGKv$hdwhhc*r&kn?odp0_jLYoGfFig|JC*XbTK_BORKJMT6 z3H~4c&_~aG&RO7`1XR(3lvvX^RRzsYghbsVO$6>kZX6|UOBaO z>hdYEJ6q#jol}=r0BCM%k2ir>A%aFmc-ECyel$8M-r3RB)!ot2R(kEM=#;Xl7nfCB z5S;>`tU^2iQ8o_tmm$ZusqbZHG4oy$05H}>ftZeD0?si%PCj`NwiyL7(lSCpVOW;D zDme9Oh5{%xPIC=-bV^XQPURmybX`!P>Jg~=LG-_x`pXOS$0ILcWg6D0ZJtiw4@&>= zBr8qMEZ<78?wL71XuneVKRn5&_R(gK)X4wY8~I9(=xIH-4yDp_t?K~^dD+7n_Ha1B zWO(;T+k^v1ies&oK#uYVdpK~kXA{pvZaT`5ZP&s#As`fZc^D7y>HoGR%z&l2A_`Hg z=M%BkNG@66iOP_4A={BW4w%?zfmgtGaHl3|hU2Lkf@W;b^Id2M8{p)CZEiv5tYNAO zh*q~$6cs~W*H$V?z*W~)o<-MmUs)sBJ$9NU=j(3iE`d(Y^Zl-PjJg{kUDNcnP=?V4 z_F{n{RfFyZ+X;=p#kded#tC1~K^$t>@q9{%7m$93bPb&3F(ls&g3o|z$V&kvnI*Vb z6}SY>=Y_6ef0U3kCZ3%LYYh6VG_Y-zTRqgrgO!uwX&xxcPN5Hzl-mc>?Vw`?Nwi(< zEqZJnD^prex2e1Ds1WPxlA(?0MOQnY&Y_)x+Jw{O*jAQo5b`=DU|ZQ9d#7Y1&S5i9 zPH*>cUq8!{?09C7?2Qd+tGs4pEJy8CvNoP9knYu14giZ$us3@=n(~zb-5ciA0*@O5 z+8qcgZVAbSB1xkTURxIBt8sx4_{WW2khqznK9slMX`c|cV3_GG^b~rG3>cvsK{ez> zdJ3JyqPs{>vA8f=^c3q;xTv`|$pRYo-Nl=$Q18>yVj`3)doPztTX%GfHgGlp+9$)C z?Zps4Q)HvB5OSA9TrhEvFVY4Z?->k^q}YAOm_QqGe8@j0#b7q39ch_bhM^3IBQmn3 zo=`qYLtab8nkz$j0II^4G1%+<7hYOcZ5-~QmE=XvtVdz0Lf@B1>n1!!R1;IY!Mg!X zz5n3psVF{g} zG6xIc(T~-4$$6ITjSDBvnBSEj6bRK}rWel2 zXwSerr+B>kBN|O!hVppn>~iqtqot90@Ss0xrCwD~01+$!>1YfJ(m0-<5l4T}mk}P9 z*L8YjzBdBn^iBx6J z2OZ2fv>qzv$nM4>&l%Tzy6GTSKF&B!1wFd{%9nA3qbn~1faJ<&a-6L}^CE~TVatV3 z4t5kF(i*|BOc`i9pbeDa8N}Zf_?}B!qN|RzTv{+?JzFE^MFz?_-iBuq;xzRXB@s5E zgD4JNqKpTbFQ^jiByN+z%CLsBF;tig5f>uBaZ-h>C8}-5Dj<;Bg&|-S0=z{YLewZQ z;!-caV>;4u_~_*sYU(DJ@(aDO#N<{YD2gKBHF7}hVUCp{>jtgcb&1}sL*x*;siv@P zkb4ibsg_&4RSkPO*j~8Gv_@*VOC=DYE;J_gsFGk<>x@to1axQfn$Qg0Dpv(HK)U0R zq>iepl*OKFSrBnt`aTrrC@5vID^3&SSdYmVmkhOy(gqQ$MQY?)(`1f8jY~kTh-@d~ z^$sO!ETBP)tXtsqGjlM9zqXyn<(I}EtHV zs>jntvjRuZJ#`Ati(}ISpl3$1FNxJ zOb*9-Sc&qDfGR)L>&!lRlcV(ahQjvpLfv#8RD?=&Sk)9tR8tIqY%1s#fJ1FN{7ro! z?9I9%wGir!i-n5HXVf%HYm4JkI7o7qXLMf&IKL8s*`pR^FKBZ*Deck-RHBl5LjpOd z%f$xLR0mL^6;c~B%vKd%Tx&qF_?rO+ISPRp2ko(jdtr(li0Umm)KQ|N$XPPg%cC;T zdo;iSj~)UnyGhIPj?nM3EK!C?C4Yj5cegrB6{r?ffog%R$?j4GwbrSiL7}EMe!S;wOIt&g#+7mBXt`Ay(6a7Z!>u7)l^q6M z>5iT%foOQgQME3afaU#dt22`S>>^WnAXQM$e0G7Uq zKI+*3=A9@znqk!`4`3W*RRoD*uSA+f5hxrEpeT@andEi!2o%6Ww`J6fX$`MtV|RYrSMu-NO|E5kh%Y18P~{ z)gJDxYg%{cd{RYDOx6{$J&>{_fK_;r)Y`Qs$c8b=zO4EKweu*SV%UsQ%aUUB7^4@sSDAqS3B-GqOHOyMVlKvA#xqFrc0I5VkRdO_c^5mD7kT$ljGG>- zDA`RlAl!tILw8x43E}Zs9o|eZv5*1~e$6Z7Pll zkXG)^3$Xhdro!kMypLsI^q?edCVrl|wZQ zAvo9|c|)}!<#|((suP4k3Hq9x4odd>Y-%KXn}j|{zg25qjikmhOsKNdrAK}wLY7|(iYW%H`>Up}9B<;*l zQUhhv_m}eF)lfD~*Fd$F>02@zkkXV;vGg!Ps+WXRjSm8yZQUf_nW3ZxNllZqq3R|} z|EFsxn+|0SZZnlGyp2vmss?FENa;t~|1^|r_smeTU1gzkU52Xr;ng_3UATKwy72LE z5>mQ&kBku$-yc%3lYFYbr<3=$w2`bk6qM9CS(>E%zXnZ{k>>r!?aX$;-Sb(EzLGK# zqp$W>gpxG9ipwppx5BD1N-p<=R1NL~lnE+`rRFrOEN}EQ|Yl6=Ga<=ZrzcV-R^SPYyMZmr=Iz$jg$% zG)QSb12hF)o(8EVt^rMrJs~A}uFpp(NgE7Zi&7OO2&vL^NJ%D5Y48a^ibhD)xEYX= zLMTZ~LMUawRmCfk?l+5|T4JvTq?)*zL|H>Vr&0qD!m|OxSmAwLeYOt@+WBNaUIslV zI6Ulcc~Ef18-L#H-^s4<0g(Luj^hkmJ^b= zzMNq2#KScCtu#TuCLvWbNgEHE3NVD!kR)kkehosZlu&ZOpg9bG`}>~X;1im=U~YAO zoTLi`~_MZ6okEc|}d6n}*4Rh)hT|vv&c|(5sBd6&tKf_w`!sBghd7rc} z8APQRG)nL&#TjRV%gbsT3J_JPD_2o?2INrczSj6gkSI`@O+D z{aHww^gMi%F9*}&OOAMx9hXJC$R}+zcyMQZ+fF`IQ*%OlHQ1Ct`CcWThN=lJ9|Ed? zk?oiB+zV>KpHZxyeo6#SAQ9)}5+1&>e3nZ@MFX zTlvb4&f6L~n;OcmpL4^Nr8kz(pM~qp>*rim-n_EBrKzp0qZBM{jiRiqd`Z{x@}~CN zMOSx2XLs2RqN%;R^A6;att>9eJC=8sceOxVW4Sz0UCJZX@s@_x_O9}!@%WS}Gd*7nwJ zw4GFs)DKsc@?{P2me%&Bzp<6J)+MyckR4ZN&(S&6_Yc*w<*>4dH8wRjtZ3_wb>FeP zsS9R?xj_ODqv6}T0j+3n1)LlLbYLakVP*aDm7RD=H8~C`MUb>&$Tkl!$xMgfoJfK2q5YYz{1oyGq48N zEUa6?e99*8gGkxyamf+6E0Gz)B$+4cyNT|oM#FjdrxU^`$Z0}m-rq8eG;-kkDv(DM z05z}2g?NM)tDdC$+X5}fcY_c`vRi?S1mN`J@&h3F=uot!hjSw9n70i$djvUnrdN@qFvlu2-EsdtqdP$3E z-5T%|gDBO#3xE(~BH(5c*we~E+yEq34q`tU@Zs@!_Vk~)gM0r$G&fO!>qag>mGl8M zceA8*WCu%va&Yt1;F>d7^2VsosyZBF^JevR~4xUEA( zC0Lh996y_$zM(>$qho*t6EZ_a@TXV0+5z!iK4u=_xWF8zBX35bkWKsCZ4`nK+xv12J)Zf+E#$Q&lJ zyt`9eNb&??ZB6asBM+i%0kH7D<6>k*mLX&G$eiUBWZilzbjy1X=yyRE*)^~oCu5FL zXMN4UndU$n=(z#TqP$-L4B8R4Xbo%X>;!V2oPOdfAaOA6#^9K8FnYYf;QI$0z)RtX zXAzo)G`f{$bT4LjCJp=vO5rpXBd%`C*kQvmIAKNNVfITrh$|I*1qz0wf}9-u@Wlkq z+#P49pv9OlWbE|fWk#B^mKP&Gg%&IZzCfbzR>IPKRiMN_u%vC|N@+hxSOwEe3o07U zs2w0V8Gu>w86;O^y$(^%yCdmyTz]P?z953&RAf{>G&PYEGM_tDt#dDP1rC#h18 zB7no*1JTIL-ige-f1cmeM}Z>-7sF(1wU)&QOjAu`k=Y5b-uQ$FR-m*WrJqVIg$|L~ zUNv3Cww^%PVXY|$K)X?e?G2}4&J#BE690$`2k9-`E4y-#{t@c&!xtf*M*eIFnyLlP zI?E}o2dn|rhxD#s`hcZOX*o#VY?cG*&1N}}=_{BwWFc={*uDQilB-idLL5br5qJaF za3)97a2?$(<*@mjOE;jz#yyD`N3Y;4%HozH6kZSXD?qb3Wiuq2Gm&D#LBt)*;K&*fSYsIV2+oTP<7RA#v99AiKa{ck#c02l$PU(%?ctCY z+xr-JWP7G=uV6Qreestl@kWIbUMGb&3Q=B)ibg!E8|9CYXUAp?_1HI{YyAAL09=Cd zvD1itbUV;504-!coaLI+W?Ifv*zpd;cfVrecr z;zCpgmzbsbL`Sr*SSDKXJ`eB#l!V?zwN{rUdx$hnyM0XOE^|IlBp)V30&C)ue z3yDr7`X{0^%&pQNoS+aDm!Z^HWsSTK`R-$oHf2cz){t@W z6#hFDY=-i?Ao2U|=L1+Sp8?7I6)uw@GIt-bf5zonVCJ_0EC-N7e%pYAF96HKe=ro* z{kvA%!vPG(tQr*sPyv9Nu7;BK1Q2cj!L7$-43Y>h25BuI?kI1x7>muXfz%6T`$$|U7ne|;NTnNo> zgcLIiKpcQF8%J?Gxc<{^#^B}BY|>=i;K-%Pq`B^6MVjmT1Zb{j0pze^y1Cu}*`1Ga z+4F7yvgd0(it`A7%h3?#vbjljX4pHRf>Lm|sJfU5fm(e4imzYIBM8_-My2(tk|8GsxX+ADy~1cqKd2jMRPW#s#L)?QYk$A6NQ4gt7@ zY|fjYKPwfJjX4j&KVO%4o!P4ub@IV~;uPu(NY4Vlr>Ij8yh!30m8hmZ0_vq6)$h9V z9H?_r>K+3g({=TTI_ojUD>PLbWY`ux@;%x_Q#n0VcqSx*-{pm&YV^l3cWUyjtI>l1 z!&c2ChOGcYR!t3=GZ|cFPLd1^9W$rYpmKos;xlIutPC2nEY8$uqnMpZzUT@uC;Mk8 z5*aJR)%NcoC1c5oX0agnNt8zBpz4BQjN{|z?-{M)`b-KE{WIQka zItXJ6*ft{tImedxoMX!+=jd0!G$PBO4`(94j~GjG;9I0#$R0#^S2HT(m!OJ^uLB%h z8M+3rv5qykhUT636!6S;k#_+LBGbVXk*kLI2;T}1y<}4+*RUC^xMLq`7NV`pJkmSh z=mqmp_!}1T-kNT6e;bxMZbm0icP_6ZWZgdjo5FkEsOFP+>AwH0=qB?6Pk!9)H4v4^9Lw# z9?nUK#YjAn{WQ$85Nf%~Idaub$yFO6SM82mwI6cTmdW*=+U$Y^^ID^z5pB3?k2LHT zpjoqXCV~_RTGv^905Tr~ap4?5QIYw5z_o<)qxnre%Y}7QHnH%u%uxZXo`j7n#PEqw zGic3qIbsFPZQa7UHsdzHgBMv=h+-4$cU_tD*~1~H7(bud!a5;2Cb znGI&%X-wd~bT6=x%h7jZf<;`|)v>sk$jUoV1guM8&nv7+VFfv;(GMXL_k!~W#CX76 zVi#e-u|EzeC6sbdVOsE$~xf zz6IVS=3C$xuz+s?!|#1gA-H@Cj3(w=paht;#nZe84WC9kYnR8f;|x5HdOVy{r;(Gv zhY6=C6IL$fXAdm!G6pDVfy=3}Z-J|c`4(s(=3Ahbm~VkE0UOE({+?XE1^xw?m5+w$ z19zg~(`aWEdput~1J5*%=ZB}~$>2`nG;N5`EEN8dk<6a~KcTjM@1G~;_ufRTPxgK! zu;lm;)$_~9@Av$AVAf_&<8Cy18m+AD9uHUF)A8)~c%C>tPe$9BdcFpQ1MK-u*iO#x zR%*-JK8dXbCNj7UNOHWL#&LoiB7=_#i~wA)tQ6?SM}qVcN%-FmqKwh44kY6OG7#$` zHcw;s61!YuUnjPW7-PbBfZ=03gq4EMvJ>IXj>URJIZOY8rNKu*b0p0oQ3Ur6B7|_F zR(u0RfmM)OP8EZf5&Z^HDimn)p(lN)8MS0H0p8n5C^!bpX>FAbB4nqQ3TrObAL_jj zY)QTUQ|jF^sA}+z!Gya96TUo%kltFxG1xrNPi5sQBV6^!1^bS5&|wsk3 zxDj={C-B}wSMN*8jFcTtSnqI5xx-r|Uv| z9Sfevj9N^LB-7<+pMw4iOaVFS&wHcJ^G|aj;>Q<(BkkF%{#IFkcYOBWM$2z14fQmhO27eV|F7&**uyNpN8(A^+pHe#@{ z_OO-jm=;;w(YSMs#o#g?VKNB#JcmRJK9PmNPqX0tlVQ^j!E!b&XWUg#jh69*AMjZi zX*Kx1hvZJcWk8sJk4zc~|M$Fr1tEULX@1qrv8~zyfJUCkEzC29&XJl9I}e&(Z!9RR4c`=A7^W!vB-8?^l0Vy^zN8FS zAm(YRWHug^HSi-wR#0g~B}Sw+f?Fki|2GP>6qeCto`JMtW6H!8BWH|k&!$0zkz(9} z6pdkGZ9M$G4cn6Dg>hk?aRCxsS|B)BPi3T#?nj1KKF-iq?3^^1j)gy9H%HS5d0Sr%a*h%ED=Ou@Im>Ta$Y7dn5`KhFm zk(&(IOO6hwcLD9Ehc?+(VQL*sW~C8fgDAm~sl!D#9);ob91Oh&VRY*Fk}xLe8|S4q zTrx6>W%T@X61@b^VFnYmHdy$SE_nXrTUk2enH@pu1mlmxJWy%|d?&C^HL;U4v8zmc zIww(%rCr3IXIfvHj2@C^p-j#hmSoAnmz9)K+1lrFwCCn>yz->)_`+$SVX0Og)b~^S zVRcOiwLkCdZRbQ|Def&e9P_O|+yVgih5lBdKFp zMYGIQ!*Rl&KA`DFA%o2z{>J=kOLhb2c# zU|*me-ADGAR(JJk7W5}wNGhT$kvl_bswtQ@{$eAes9ZZT zwOQpfMt9SFQLk%iP0Hm;iy_zRtn3g5IIU$YU5qt)F&VBKu=TJN=wVaqme!9NbLk5D z9VcaEhHr{-2rGz=dTpl}u#WkLV(=qvOmf25myWYjCnSr{;{tWQZU-EUUZ9OlvpJi_ zlcE%55FYVcjSw(idvTHU;&EezC{9xY0avX=69%ucxN%S$l#){&b`sr@tM3I#&%KZ| zY|>REn4IpSIuMl7eaqw!gfH`rT%H=>v^P`z3TaRo`SA565N}&R+fE&Bl*l!$vJl4< z)sBL7rf~~#@!;l_xj!Qqc z?U<2nNBj(Os*N~){zldty}@?Gf6q_yU=-8sIA|?PF4y!vu4cY?dMj5mpP)jWkJ5AV zwWAGJj#r>JQ$ydi40U&tbY4?-eVoZ%G3{oli61!Ce0I_e@yoSpRdw}92c`YJV4zm{ zCp+oJzz3NyQ)ePd!itD`3mhD-_C!{UrN^>izIrrItq}KSy>QbE7 z)3fWuG%+ipRG{hk8H0r9EcoF00X|Wr@A>l zYbNAM4xi^MzO{gMpHe;scdM#gAH~!xs{S_|U9Jx!rkBevnI-87JO|jW3z4h(Z{faF z$=7GYG>a<#JACu4%A?c-_v`wj$`3KVN|OH0Exr6nu&HwW#45eK^L$+{AN=S-75Jrl-7erQZniU&Hud@0QKFc0siIhUnC?%1iXS zJ9y6w@0zLi%i22Hmqz7trHH!rLXSOWT_oqb#GKE2m8Ne!3%Cx~ySI>&N8l zGJxaD@Z))HA6wSc*wB6l%R1vNACqs?sGkS%e;XuPx-?pP-Bi5q zM6>>NKhf3F(b*mKnb>|ThWApsS}VOWN#YA?VrdiJtZH4>)ET?Ip>0JI7+0VW2Y+Lz z)Ya8`XA^)V6Mqd*EMtWjj&$>f0%Ot`qNSm|u?@VSh-LAH6e^X)EN@Mf1r)Eir3 zSyNY6!_p?v-O+Vnj8e5mb4$D{I^{Z~$59>M!y8nhp{={Qtzjt$d?~8CwH+plwc*V(R+b|Hh4I#pG;?=n1>OK!+66%! zaVQm|z}7DQ!s5!-#%>%+YwD(@1zK(J2Q-FrBTJe((ZtgB6>(pFn{2nOp{qN_b8ubi zow1l~mVzi}NrNB6fNdgb3EayRp+f_Nm^6g2nyrB^t=SyiZ^~M$7 zM{DQVZ_n&r>mqj5yx6?zE3b)NS$*ww*Uq`JdTwlfthwSe^eI#T@9f1^w21|?7xHC3 zARYLz8(yb~=FWzAg}j1OOTNB(VQgxw8J<>im8|jcSThCnOqDzft{v2VS4(Six42$w zan<$JSH^C*{)X5z_)Tm4wmSr;ji{DFn&}j1NHfg`S0i5eJcS599K_ajTPqIPXeCp- zkJlAXCAW5AhPB^us+gge=i@Ox6g-U?VKd10`kk~6EHXvFHZ*2WB`&wa(u0&<0hMF7 zx8V|RyR)lRTX4>G*T!lj^CuR}jeTNf_54^3jSeSmip8}eLzi(VbSu?0HL=QAT#5DB zJvn#AIE{KL#FEx-m}qb%HR67yWcy3b&_2qhoH?u}!>Ej#2%Y}lbyE>XyBJHo1h`qg z>WDWlOV!(QptN_CVp7C!E5#)4ZsL!pf_OV-@sifI*6uq#*3ybsQQ_wumn+BmC7a6W6?Ck1VrlvpH#N}4px5t%SwJ+?!ul%GC#UgxZG|% zN@U7Tm-!P&_*#kCzY$#IGTVn_^{mz@1zGFSDQp zp6O#bTVT$!FKB^TjNl@dStF8cfdD0-g_&r`*E)c`TM!99&f)SkucydU=Q4Xyu}ktk z!i!vHBtwTqJH>BP1#uI3B?Z;F%(!RtH1$gs$&!1?RO>R^u9z0>bP2Hv4dCnZ%W}mOZl@QiQn0p6+7J?X_3n;NT!=`h|Xui=(v2}VHc8l2@nDgAsI23*$D{}Q`b=Q5jzn-Z9V*(%Suyo@F$a2-oLdB>Cr(|0b82#}8-o z`Qbc1f4$^C&ZcTzX8Ejoo69Up@D`WZY=X5?1drqbWOgsXTU=&5bPOu9M+n~LGCQEC z%!2%8@)jI!^pu7neI;&|%~gR5Us}pWMu3el^T|j!Z08gOcDjV8Az?h3U4le5<~2x~ zjWCaggN<1b_he*a-j8H7y37uEWad0(4KlMgJTi0n%TtXmGyXGc3SrJu{gBO!Cz(lR zz5_|CKzKJ2*qA+yL^kF;EDy3gGmr5jSs;&cEE`>B99EEpn+YAFNU&!yvP%@mYzC5b z4+12C7DZ>a9Lcec;bsjX81Nod#0Ewnc|}5wH7yRwbc_~S>o)f|vVf{V3yokuZ*zN~ z@IESin|l};W#Lq)^qfB`Cq1k^r%t*{F(f*l7Qum0J6$%y7U0Ts6rNbpMNb2MgGKc& zvv&yI>@qv1sAHgm?0%i>K2PO93=i|pRp4XDWDo1`xE;F7ZnU`m(6zYzP?$zHTGSYE zFw82CqSn?%3>bmgRKMBXiflWQvr()OV+PBjP&q`mN(J`-g;-|&NYsP*sjUUk@Fb-J zCrP~m*)M6!Tcs_f)ozvZfW3lXc8V?nQ2U^9>#24+wco+0vLHi(6@*#@IL^jWHC<>< zuL1hcpawXhB*#rs1<7$!QUydSpJPdqV@Z+&@oy4ja5g$kiNGz1fSj4LiQlYn!t+yb z!u*HqPMs=W4!GOH7oonMrn)}o>KjOue;djPQ_K)|+BNuyD?n?WpwH1g}w0;~$C#*hWF z#z#|XaMMOn_aI?rF?)hwv&-z?6qOlkf~uP`nv*IxyZ(#=F2XPK@Dv95>RYl^N8yU$ zAqeMYjyd&4jM0sNj5BIzm=^S|8MCDaYsBw5-wK(l)){6uAenc;B#cCt zFkscW%xVe7TxRu(%51TuDrQ!|u1(jo?t;p!ITwj4!%Oa>OA()k6b20h?6yE8Vg4XS z;%qOCkp#9%@v2?QgOXaT+P-OdD9~b5!O$I82RHC{rrb_$MPm43xFS3w7x>q#uV+kz z*8-kP+$$%%KBb)Srj&BRyHd&tznD@^n2(!1`H09`f%-%MAvR5cOizL9D8MTxtQBCn zuYgycssPJ<1-$Z91yHUO*bXHa=Ga>@NbjL3bOG}>5t}gUSpFE_1Zj5rksVXuW9ZWX zB+jEYF!Rtk4h_nE3#GD##&tD~>$)B;+!hF6>u#^e7~sx_$V*5@T&lPV0{t=?;L%h9 zkv&MEyF|@|i~$$*iT0=R5P2${hv~LJ!Z3}g(bD7Pfb(To=dccJp zJToc>Dzoj1%8X+|bL+7I^NS!!t0Hb_t1fZ1Wq4ykqx7)7n_OnAklZ^&RaNmg>=}UE zixj>~%qX5QK@mydnSE5?2(%#q>_)a#fmG!Q1u~-nTqR(qOXO))#*FIuWxlQmeOlL> zlDZ-aK8L1XL}DkIPo{C|U7BtO%~vlgzM{Zak-eip_ID4xs9v~_pdP;e6wZ3(MY>gu z>!vlXZRO#@-3bGAj z+ka6}+5Q^}^xMZhDc`5sjJFBc2P*v-S?b+m$OML%p`NrYmu{uAZurXkXJyFjiVEdXsw4W#@zMD9#J5(N0F@6 zt8ga?;4#u~ahV+;7;~AugoL%Tazc;z1Sd7|SCE3FtrnmVdld;AHi;8{gB+}}h8)B= z*&&@a?`J<_(p2-Qc+6#1izIa+P*3_TF0j3(7i@suLdw697~xbx7f`Ro}Md1NxM z-r{ZsxJ6N!F`yc^z?qOAR%B+JSs2zy$SMfdxy(4RjGHkj;HdW^WhMfj5ud}ZB@svj zT~heUR@RMaWRmFBHpq!g-AcpsB*iSvuYv3O$g~^fzE`x$phtf0p3k|oy$y+4CNjLyho9lJx8$3eF@nyg6M2N za=vHACx4{BL3*9bEJ`wlf<`ABSqSU)w*aQqaUZAShk;u+N?Yqm~U*_*5i&37Yz zlyIHP>}i5+?sLebkhY|dHsS8k1oY^gaGB{>!;KN>=*&6+#iRCG$o zy(}pNqlSMsC;~`%Yvdi?=jF9j?%GHmgETg+NZk*@zwkdAO2sd>;r#ar+Wio_%RSLQBk6A$bqo0d0{5n5D?ym#G#^ZLAOz(^Fb-wg6#rw&KELM9xFFJdGqA zeiybDNiy*`l;8_R+VBp)$ytl!Y{z9clK4n!F~0!Wj^ymZh2MHOyK#AfKtC?85O@_A z{?jP&qtu%GCpcS?oab0Qv|? zwcw~na`aBq*$#|*2AB^FFOumM)Zu~+J76u~jC6RJfg~I*S@lRx3ocyRgu_+jX_8*V zg{uvkMhKjT3ml`ullI)PKR3}}Q5p6_L5_}Tlj>Aj6EPDgj<0J{#BY@-tamhsz4)?d* z@Hq^1+)X*$KQXqb|D!7CrJ#~>jK#-s31H4Tj5iE1>3p1&oO2E@-2^y!Ic535pojr{ zEMcrNvP=;r5g&b~uqHb?Z=JE({H)csx8|wYKcV%bl0(hbZouRr$2!BD3#OW%%+5YV zF59U^;w)y<8s7?>KCAH^zzJ)7H*j`%1QP4>yXncuYqE1^Z#L(zV=T~R{6=~%@Y&h9 z&>8wdS1qR)QGs%Zr}noP_+cb|*}NG!Gqe9ISb<=9e|Us`<4iQ|llfDMCK=pbmWgS1Wa> zYFiho-wPM<_1lB8Hd!`r{^pGOb)lBMv!8;z!8WY|5B-CojNg>OPBjU;mb%hP+d?q! z7Xl9itw*d3NSOPRniM_fsy+{vN&GNmayG33JXCou#&Gc2Pq6x*s0U#VNob3YLohyi zu2}+t@TtYAVty=dDg)%q2aZ8d9}h<-@xlD?a4ZD;T%vK#oa9ITd_oe1JgzFqk0oH} zl#eBQnLOEtgTAV{JqeQa9^IVtD)*y10e-gQ#zb5)8?c=+JDPkzs^OfbTgX)u?^Fw`1 z(Wyb?x_!BpNV+N33{lQKtNNHSCTdLA=Q(Lz{y7aI*X5im>SKz*<&1?o9^r?Q#V+7F z_7eXVa2@lB^L1;vKp@M7eSV~HIUjPdM(zi$V=(!j2fiKp(XPWxQ@o5^uPH2l6S!VO zh#v#4=RWyuOkutDv7G;PPp>P)hXdEKjre)MUqO3Ri1kZ=>p0HxDZq8?U^)K-t*BBH zCl?*#f)E9XpJA9C{3ipnKi4Jl&jP*{{z{Wl-a_DdO(EV0T*pK5^Zz01c*^osz;*n{ z#f{=-;G93*p1k{j>-mxk{_Vi^n#}qSlOOu5_w?bvanfrk%fAO)y#tRMK+_Wa!13|M z#}+>Zp4$G;2I2fS&N?3E!h>D{uGb36{{!&DSg@7Qw+G$^o)2SGfWZE$Q^RE)qPWNZ zxfOLhzC)h+#!naMU*Pb6R73xQhJQL6OzIRefb_%7$K8%{xV&JjczG@BVr9)HCie98uRlAdzzP z9>+d$m^^u6TA#W0yQ#{~K@6rY61Z7}6z>Hr}xxEZOzS7yc zWJPxq3UK0c8IS&#H8w3-u@vX+@$)t*FuLEV@z(a{4h=UfS<=~byN`7?v@fMJB_yRz zTSuHn`2C{J_N8e!&ZRGFqVu2Shxf&pB8ZGCu0$~tm#5Ta89(EYG~X7$TfmpPnCc~} z#N*?V$$iWg1STE|)gR4Q4g%#daXtqtG>6Jb=ZClanh#*^>G-bj_`DrNE+;(Vi2otX zG~3I$5(xiowGr&NKOZ@%JLu7yy)i#38=^EG=gisk2H0LFVTGu_7y z57tF7@Ew?}v7|hFeJ|^1dF3|?(d4iDNqP4SlDBmUet#f(s=RH3_*#3huBB|}bU(g6 zh;RG-SkH7J%4jow9z!Bo>(`SI;%#p`%5vS`fAe6{_-Xwz)_Xdo_tB!C0j^;dJ&1*V ztsET1sLQy1YnUa)--iwZRKg55nOld%a T+{vc${brw#dk2u^NAvxEjiMuKi0h z+H}H>N}|KpuU6pF6z6e@1nko`Y!6bsPCe_ zJKPZ2^hQHyQ#fEiuj75gp=Fznt%07mnxn&CGg~u}Ey7y8Uu0IF5Y`&Q$gJ67Ske7P zCVIlK>J2kfzs0l~_M4f86Q;G+urh16SXSeHE7N$wvYHG#)3n95*6p`5>rU9#dc(=A z-{M#o?{_j6pKz=VMj*3cOTgN=KakmYB49NeZl-yQYqjimGc6}v_$@drBCVdEW}|DX z;fMWZ*fy+a^8+(kHw3>;&B^E5sks3$YGxV_%w-xT&_Av?8;V_(b( zN2QJ7>1o+7*?V2%n7c|GoqkKSbxn(7u87I!mIq!!{v(?v*#Y z^94R<9q8cq%?$bt<3q-Y%{Yl}cyuPZeqtutbb2Pb_T?EZ*FrnTTtgh)GcA(0!*)j) zVJ9a0D7w~`F_Jw}V}!@ZXG%WC&Qa*jI6~~qChu}h;*Pnt(DmQh-zY#yrhY>#-#&K~_D45N%~*(q zOyk7NnGTPCJ#p>C%}So8shLc}fmy4;p2ax7h2t;N;N>ZC>faE~9zY&yv}ehu^4F+Q z$hUp3f<3wj$$Ce}rgWZ=e$3QwIj1kPW5#~=P4bXyhMf>&{g+{fd1=)z!_)zE#;oS^ z@=viZ3vwgLV;;do%Ozn87}mV@koof-T3qa<~im9lCq{Uz{@+ z=*;{S4r~`kFlS@Fe?$61#46Eea;}hlAjB%fP(fYz>Zf7MJ=wsd5f0#qIX%pIeKP*| zv6IM`2i*wb=^p{VM*Xw79Pj+{tk_hu6@0EkI?&Lh}D9Vuw=2D#_5%aU0FRg|N#HlEw{>cMwkogdKE5P>X?+pBY z<{1~`9_gB8UVTZ z5aaaMGA7hKwaA>EpMNNWYlCD^<-@ES5y|D#f;g-d@XXC&=bk^1BaW!NdOGtk{P^%z zVSN+1@|!1x^`L8H9^7hJ4~-eorlqsd_4aIZ1Lm7%%r_C_{xzpD2fjR)dG4eUUCwoi zJsS?3G8hkGCjwjUe-$>*+%6`@)=2FI{w zI#Q3h!ks^gbz1a4y!w{a2);)9&166N2>ez<`qGxw3l&)<%9>J--I z!u&=BpOf=kcgQE!9nm#de>B;$4&yYs=Hx+JaNb-mTbwAtsWeHvBg+d*&&Zu`?@WNq+hxM{+ zgRfofgD3C*PjdXN~KAC8wx7Ph+q zIpiGe!hShl$@Y;K5cg<*3~LImj}CB-oXrNP1N1_ydO94!+VfFa7yh>(17*2S34_Ns z_e!0z4(3#Rs1oK6Ho))8pzr*#nph;tbAz?j824kJ4BJ=-!d}{n@o=H_&Hba9#)Br- zhBCK>9UJSJYhRaj8&%!S^|45JZ0p@&yZ!Dq`{fwUp`^UKIKsG}rEIAa%!!H&x_33 zZK0#Dd>?bg^Py~@Muck`MfA^~lX*S*z%kk9UTk9h`bn%~6Y$}e4fGX#DbL$b#yR6^ zoVi_ML^o`~c;1h*q^}#{GQ`fE_?3r5=7AHV;k! z^A6E=;DAVev4nn>V*-9Q;b#-)f`+vo=ZWjL7}mvxfpbA&;mi%^g2LJ;`$3+^B}Yrm z+A z2;T-@VZ6ycEf1Jk^jq?#?}_B~$0dLEUex*0_vR=s`O1^x=)osrZK`#}A@MkG6 zAmwFmm3z&1sYlnSi8j9$OKy8a9CaRv!G_=Psd!fXhBWdJPCkv;yT;+ZV_MfG@0shJ zIr1TQz10So{8uHC>4Bl1L~o>LIMUEriY1%4vcEGjuq%?fF_j!i_YCwCmmW$Cl9(JA zN=0@JrM?_Vq$3TzBav-4$vV81ZXX)xO7um#6T_(7lTLL;_VlE?Bguiz)Q3QCy-|p! z{*m6^bwa#7JwIRn&is5ieti0Wr#u>Q-6+52!D&24-^b4{>tAZQ_3iojZNE`=$BOLF z=?orS9tZEk9zSu{d9*`5+$ofo!q2>{n?5CseTK23!o3j?nhgdK8*cDG&HbLn8K2pXkj zTd%m{Ly@MfpZLtW$R(FFU((zvroiP0TQuW|m$>g%R`9`j8b1_PnJCK3M7hc=W0^NY zI3UF$R>-i-lAtgw!*@4J>>`XIF&eL^#dq7QmB%mS*F364a{75xIj}&EuXWI1*jq5~ zcd?thd%4x8-G^v*d11?{h5ujfexEJW+4B5HAHO%}!n*%*Fn-M)TBLe@8Xd`=zmh?` zSj5{=P<|i3z4$$VpNxEG1xiBR{u>I$izK{)o8>G+NIY)DB6Us`+_h8~PMI1Ej%f)F z3MVW~+X4>Ie1DeOFp&xEy>*i2_ZSG>cLYBD1v8|SI1QH zai<0)cv2FFB~8a_+%PsF^lADI8nBq@0h%7f(4hG%@GNja@Rz`%B7Ss%`AL*4`oaD& zZ*+$9uYt224w4BIgQN`h`ZR$?)^ge)v9+Flcv_CM#m@_^;RW)p^1RyOd2=J4#D5G= zderjpD?OOD6JO?el;t+B%-*Q;==4o}t`!%p0CFyb6nZY;Np;i^aLO%P;=>*s0-c@? z04DzuJSm<0)NVztzAf>2I4Joq0-c&IvC1TU8MI-&C0@N{R=|_1^jYS$PdYsZvn4$* zSGDiKpi-NqmMg8&5n1l@NsZ4Z7y8O&Ufl{G@1EN$Jp5i*So{UDwP(7i> z#CpKg^fC`$>OH+N0?nwQizjOp_kYOKwi312YN=-lYeOSIlzjmpJ{e;wn$#%WfLhd> zv8r_-%-*6eF9N^z=}JhekX(*cDRrvwq&l7y1F@l`NnKT4+&Pk@|8Q5fs4TD?^{6v# zVk0xD|26BzJUVo)=0d;ueT(Y)a>Z`=$noi>>}WZEoAq9hLE zX6)uoCJyEdi`hda4(l{QCJsv`j-Lf%ks6sG*bQFiKwU?6OBjm5LFgtGJT!@>RV#Ba zER>0K8BMM9f`;Xbl~Jgx0%MKG%b`oU4u~r7(IFvUU7b+ty*drjaW_f6l^!4UD7Q)$ zga;id6Yvl$eeYF=cBEQu-3OUmHb?F(Haha z(z%|XwQcITxR;gzjo!}ZRfYj;S9sF7PM~zXmRlpOFGHGW0+t>Hx2K^Ch`dXzeNr>l zrAF&LnL#h_S3*^7 zFbUE#c$Xyc9Q>-D)Ys$ED_T-6L|^d9^i9pHtzfPNO5$wF7PSRzS-}eLX<`jaY^fD0 z;9d(oC|&DYn$urS5(AqCJ*Fk!_ug3KgYOCa0KTw*m??}-SW3oN9?*A*r%Va<$4C^au zq^VUNr>Rys?sW9&oCIdXqUvSIgDFi$25JC{GNTADPo-FnL?vFvH8_yZcO&7x_cVVw zk~4p5n!f=h!5jBY+m|Cp*L!n~QXXwmD|MIV6ksGC9BBDk%n`p!%W1aE8(U7Z<%wKF z+V%OS{c60YGM?HCRXrC*2FgOCQ~)g^P03j(O=-1I^M#y#jKA!&QMt6axus)xuqD;M zTMVZYL+R#Ei&TGlXfK}Ksovg!=A>xp9_UN8fI8eVlo}iuZnGa-3YqiAr9vGy--b8xWz);^p34J&>Rqe*RQ#US@Lb~>XPoI{-A-HfC_+d<9s0)IJ z(?GERpB4P8+_RC6f&@O21O2;tx)fgYjr4Z*v>~uMdv@c#TBZ>L1DoShUa`n`WGM)! zh3HYugv29^w{hd)Z>6CzAnC>qK+0HgR%+K<6ZQW-i%H73B(78fB+yowu?Z6u%@Fm4?10NxK77vrF zTdQ^H)kGP={dnMOUubFbFV;%_5(?N)Ijr{|@hct2txS}E5)WgEL^qkS2(iZa&vD1M zRYENPGD_y*UQuxy2|>w6lLjSUWe;#+iZl=JkQGW*h3=};V7eTHP!D*@$`lX(6FQGt z%2ibmUnyP1Q!lz|0`0F12=R~Lcpt8^&gm-aO~^KT>hQH2^pkF@Qf{+0lk(aHcaUPc z^q$4dxAkm|L@7^N^rWpkX-$J{U%oU+)(^7$sbzn}@)amM*&0qop0`8Xyaivtt@;D( z?UIULqg*0N>H5G^4q4gb&Px)#`?ZBu$j=B<9V!lc0ZCV;xzdqeL(UWO!*S zg})w{z&3s*u*UeZA>fU_3v2?0jK=t_K)8nhmIE~Lk9gT-NUIf}w_Vjs z#`xpF1@0wbH3?v}Q-et{(WanoQQi;YU$vvcqo5n(|AQ57B<>=%Ny%jw0DPc|4NV4O zk?SO10F9dyAUqiU1`v)lD8#5({sb__pR|(qZ6_Atz%s@k1FzjL{$!hyc#T;H#8;}7 z=AC8*p^FrBz4;fAaLA+eR;2p|Mb?A5%|8R}J`dVq{uIzxJ!pH)Ca6ZYj8ieX=Dvs$ zxl_2E9!=uE>fvEW?dPfPfrxsLse@ep{791RM( z-X0R0FHz;|>|J8>Wvaa0{<7HoF;%|CJcAmsa=HobbZ@s~k=IbJzzin#Rw{J25Oob` z#%QV7fyNJjZj6thaT_^Jw5(L3dhvHGNMK&$-Qt34sN{OtHJ77WL{?kDv}Hs~zYFMf z48H9WyYjyiTeh4|;gD>SSaA?orZ_Ck1^#LSDJ}_26a}6q&EVM(L_L+_%q>vSy14d( ztoz&2opo(pf_(NO=`Ntgtv6Q9D^zhQdtXG{GJfT4GIqV^)5=~7xCR|;|%nZJD)E!va8f}WH^$5KPbAQ}PEW{~W)-6TA^p3jnzM&rmiXE_rBuuv z6kn_*!RW9~gF9ZOxUO@P-C}2m78`$9CsX3irG(u6kv@^A{)&{CaQtvIsOZk zaIZ1`S-{d`P4)Dcb@;`brOTRPtZ5y7{$`tYu8Y!6>+tEDO&YrH5{9pJ_|(lNZCm$Y z>Tex>=4O)yth-8qPu*w&9XP8~1L)%=N9v$oM+v$jRoyeI_* zqq^cX3}LmjT4tjyba(YC#k0fwduUX>UPaIK);9r#OHZH`&Nr*@#!t8}%BW=;P%>D* zyjs;qCXaxbnd7gKBaF{f3&BI6`a`Jsr}(vin&0UCkUT#G507geHD(K#jA{|8sWz5W zS(Pg)8!Gu-Hr3^j$_!GGO`&=LMHoIa^L9Z$*0Tx?$Df;^wlv&h zz?&Reg759MM?8Y7TcowCZD}qIDlOJp*<9wKm2AH?^a#A5#jmbttkZ^)R3Q!Wt5mtL zE2{Ec5mJ3n?N>vou*8pQtQ#}x6h6#3XKAy@ca>`YraB>(`Rn-AS}rw~5mRhTjq(hY zuWio7m9C7vfxoJ5irg3Yb;wJl9xE0n?E`6LzKy~<1wCKb&sK5#*tt%07J4_3_pXj` zzgyU<@??n$mIWc8ZKsiCG6ub&#ttG$LZ64|vRvMx zGb;__>M-40wHo8LrL4$J3!*^UBYl7ow%TR-qZlVY=vI5EfNaV?4&8-L59XbIuH2_> zEu*ak*)KotG3s?t6!nMB5}s1NMD1Y~$zZwAMiQgFZr(VrQn1i3C8hafSB<%UK|HJ8 z#NT15WV!l)sU26&6o|x~(=%@rd!@2~l8gg8vDDhQX-i}@tw ze6TE^1NO;TWVy7q?86|bzO9iR=|j{ON2NdH>b&aS%y za3OsJHB|ixQyqI2(l=sdq3HT}rI7x;fTrtRex$V+;TI8uC{lh(7{rKZFvgLqecVbBF(tiyn*uWK+Z1z6bj%@5p z3?;iiB0uXU(9!dep5DQ>OHoet;m_N8Khl@#O!V&soF3^mI$fsu~hlt(6ZC^d|?MxrZ~jwc64;{2mK38Z`aQbY0GiQbWvXCTg; zU}1cCxaX!63ap`+WSx=WRPGg25--AT7#1UVqZa2ICee`?>5LC0(kVf#{=VeiBoyqUXr)cZ-oeE1u;@!AhDU}{c`X%7?|^_~(g|Hry>#&u z$Ge(7Px}vSqVjQ`)efb04X1i_H8!N%mSw8gy=!OyZ-nBzpuYU8#JGGf=*hYaqLL#+ zL%{Jh+eioSe7l7k-fU?=y|IGc!^4TL9G0)DgyiF!DEy^kXG)|8RK?DoE)WN~k@f_t z_fKNCdSWLWk9Ump^rn0IVPU)%@7P3dVmKY=COOfY-qoAv5}k>3LJT4{&~SWkD3$CP z=AT!hzu4b{BWW3gc!H6yvsy*3tQU`W^^YWTayt^}6Hkp{PY)eWaqI{?QbVlW&$CC! z<`BTUt*&9=F~?;~j4%9oCbmRU1b32qdOFhp6P?NYOR)t5Qocmp2!%GL2L^hfaZi5> zE$`$DwvGL%J$T2q5fRgsx^&U^l5z~S$kF4yj`Lo;iE`wFd0ZC%auLV+^? zTes~uZa3S@gTlP-MEg_aW@|e#isoxV&KyUb_R2_}Z&dO{$X6^s0^XhYO`u*Ap6!*P z_S+3gzYd~9tRgnxw-dkD!LuDt@NB0JcUxJToSjm9sQpLnKbHIv@a)7-pQq<#UXzol zd3NB;{Q!8Ouh*_Q2qvj3ZQ6<7&%ncX3GJ1!oK4olhHN#47B!!K2Z8o-d^dW!(GJ>2 zdHS^qjt=Go6bhLm^ zIY;tA-9@fggh=EjN#puX!RRDhP5AF<@M+;6UT@cG*p@K=e=#grIC1i>Q9dp8e~)2t zls8LYiH55;2V+Ub>oQHp63lm5qSObmK6haG%aT#(hp|NSU6x>W$X}MI$^$4_B2)z9 z49s^~Vu|Mwg|x-5=KUHHri2Moxgh%+KTe{Cq|1hxsQ8e)ulH`p_2NV~TqK z?+l7j>Jfr{4+7Ttn)IW95eD)KLEqzmbzUa@Z+-l00KW)$AC7Uip~e!^6t4i*a~=8L z0Ia`(AUqGa8~$OuRiphS81heq)mnq}dgf_Eef~l?4n94f5pD+k`lagCEn$8KvJ>@p zuzkSW08c=lkf+b5D9?NENBR!H%m=Fdp!{Z$e|yTehNSNUUBtA1N(5h901@GxqjMDS zKD5uZ5&7={+?kW-if;hc`!)LGJAhv|)q02gPXN|)7X9}Fz&eML{ybpn$M!<#h?fC3 zp}ubK9{}ro83F$kV7)$KeV)~8`GoPst2|~uKz*T4Enq$GlirE?A^2}8>45ox#ZI3+ zF9DBhl(!J_EB@xIK)nH~=gXIRw0Aiw5dH}0Z==6j z2}8fD0PA?8e{x?adf)KnwnM)Ci{5SVslN~OHfIaAQ+oG@KOD|)-1MhI9iU9J$9+Zbu?W6k4 zFW%KV(2?l%5Un636TKRgtP~kf3=JjrV&B#Y1|LFhGl8Pp3V5(pT7dH*biG10h1HuX zY@w8Dg99)#HB^sw3O0sdPu>vc4q8*ZU82XA+d+=tlbYe4Ho42zJyWo0)-5Tw#rZ)< z92>%pq|Y$lNrT?0c|3W4pwju$0ytgl%=)f~Qq@LZn#8?o`2twS4 z2Bi4rR5#8j5;#C;?oIUKyhk*5=ALN28KzJaIvsWRxBJcbigl=`VrTIPxh}HRH9_?jf^j%u?7T`1=ilgV^yV~PJTIDq=AP@6P?$YgE3rr9{^6B~K zo*Y-+4(@|ApI%2xgvYD(<2n+u2DJ$47tsKonvd&AmbIC8p|GTgk92;VrR$LVRq(CB zd9=PX?N%WC@{V62#7%U%cag^5-QLqfiw|8TM4NB} {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::INFO).coloredOutput(false).logAsync(false));} {} {} {}} ::pct::set_main_configuration Debug {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::DEBUG).coloredOutput(false).logAsync(false));} {} {} {}} diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index c3776cf..d254647 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -431,7 +431,7 @@ void core_complex::before_end_of_elaboration() { } void core_complex::start_of_simulation() { - quantum_keeper.reset(); + // quantum_keeper.reset(); if (GET_PROP_VALUE(elf_file).size() > 0) { istringstream is(GET_PROP_VALUE(elf_file)); string s; @@ -507,6 +507,7 @@ void core_complex::run() { while (curr_clk.read() == SC_ZERO_TIME) { wait(curr_clk.value_changed_event()); } + quantum_keeper.reset(); cpu->set_interrupt_execution(false); cpu->start(); } while (cpu->get_interrupt_execution()); @@ -515,8 +516,7 @@ void core_complex::run() { bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, bool is_fetch) { auto lut_entry = read_lut.getEntry(addr); - if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && - addr + length <= lut_entry.get_end_address() + 1) { + if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) { auto offset = addr - lut_entry.get_start_address(); std::copy(lut_entry.get_dmi_ptr() + offset, lut_entry.get_dmi_ptr() + offset + length, data); quantum_keeper.inc(lut_entry.get_read_latency()); @@ -537,7 +537,8 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, gp.set_extension(preExt); } initiator->b_transport(gp, delay); - SCCTRACE(this->name()) << "read_mem(0x" << std::hex << addr << ") : " << data; + quantum_keeper.set(delay); + SCCTRACE(this->name()) << "read_mem(0x" << std::hex << addr << ") : 0x" << (length==4?*(uint32_t*)data:length==2?*(uint16_t*)data:(unsigned)*data); if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { return false; } @@ -549,9 +550,6 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, if (dmi_data.is_read_allowed()) read_lut.addEntry(dmi_data, dmi_data.get_start_address(), dmi_data.get_end_address() - dmi_data.get_start_address() + 1); - if (dmi_data.is_write_allowed()) - write_lut.addEntry(dmi_data, dmi_data.get_start_address(), - dmi_data.get_end_address() - dmi_data.get_start_address() + 1); } } return true; @@ -582,7 +580,7 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *cons } initiator->b_transport(gp, delay); quantum_keeper.set(delay); - SCCTRACE() << "write_mem(0x" << std::hex << addr << ") : " << data; + SCCTRACE() << "write_mem(0x" << std::hex << addr << ") : 0x" << (length==4?*(uint32_t*)data:length==2?*(uint16_t*)data:(unsigned)*data); if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { return false; } @@ -591,9 +589,6 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *cons gp.set_address(addr); tlm_dmi_ext dmi_data; if (initiator->get_direct_mem_ptr(gp, dmi_data)) { - if (dmi_data.is_read_allowed()) - read_lut.addEntry(dmi_data, dmi_data.get_start_address(), - dmi_data.get_end_address() - dmi_data.get_start_address() + 1); if (dmi_data.is_write_allowed()) write_lut.addEntry(dmi_data, dmi_data.get_start_address(), dmi_data.get_end_address() - dmi_data.get_start_address() + 1); @@ -604,43 +599,25 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *cons } bool core_complex::read_mem_dbg(uint64_t addr, unsigned length, uint8_t *const data) { - auto lut_entry = read_lut.getEntry(addr); - if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && - addr + length <= lut_entry.get_end_address() + 1) { - auto offset = addr - lut_entry.get_start_address(); - std::copy(lut_entry.get_dmi_ptr() + offset, lut_entry.get_dmi_ptr() + offset + length, data); - quantum_keeper.inc(lut_entry.get_read_latency()); - return true; - } else { - tlm::tlm_generic_payload gp; - gp.set_command(tlm::TLM_READ_COMMAND); - gp.set_address(addr); - gp.set_data_ptr(data); - gp.set_data_length(length); - gp.set_streaming_width(length); - return initiator->transport_dbg(gp) == length; - } + tlm::tlm_generic_payload gp; + gp.set_command(tlm::TLM_READ_COMMAND); + gp.set_address(addr); + gp.set_data_ptr(data); + gp.set_data_length(length); + gp.set_streaming_width(length); + return initiator->transport_dbg(gp) == length; } bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *const data) { - auto lut_entry = write_lut.getEntry(addr); - if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && - addr + length <= lut_entry.get_end_address() + 1) { - auto offset = addr - lut_entry.get_start_address(); - std::copy(data, data + length, lut_entry.get_dmi_ptr() + offset); - quantum_keeper.inc(lut_entry.get_read_latency()); - return true; - } else { - write_buf.resize(length); - std::copy(data, data + length, write_buf.begin()); // need to copy as TLM does not guarantee data integrity - tlm::tlm_generic_payload gp; - gp.set_command(tlm::TLM_WRITE_COMMAND); - gp.set_address(addr); - gp.set_data_ptr(write_buf.data()); - gp.set_data_length(length); - gp.set_streaming_width(length); - return initiator->transport_dbg(gp) == length; - } + write_buf.resize(length); + std::copy(data, data + length, write_buf.begin()); // need to copy as TLM does not guarantee data integrity + tlm::tlm_generic_payload gp; + gp.set_command(tlm::TLM_WRITE_COMMAND); + gp.set_address(addr); + gp.set_data_ptr(write_buf.data()); + gp.set_data_length(length); + gp.set_streaming_width(length); + return initiator->transport_dbg(gp) == length; } } /* namespace SiFive */ } /* namespace sysc */ From b493745cd77fd3b6e2fc9f91f2c1877a2afcbccc Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 2 May 2023 11:21:42 +0200 Subject: [PATCH 083/184] sets reset start time to 0 --- contrib/tgc_import_tb.tcl | 2 +- src/sysc/core_complex.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/tgc_import_tb.tcl b/contrib/tgc_import_tb.tcl index 59d56e4..6a7ce1d 100644 --- a/contrib/tgc_import_tb.tcl +++ b/contrib/tgc_import_tb.tcl @@ -28,7 +28,7 @@ set clock "Clk" puts "instantiating reset manager" set reset "Rst" ::hw::create_hw_instance "" GenericIPlib:ResetGenerator ${reset}_reset - ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} start_time 1000 + ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} start_time 0 ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} start_time_unit sc_core::SC_PS ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} duration 10000 ::pct::set_param_value $hardware/${reset}_reset {Constructor Arguments} duration_unit sc_core::SC_PS diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index d254647..75da28e 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -500,6 +500,7 @@ void core_complex::local_irq_cb() { void core_complex::run() { wait(SC_ZERO_TIME); // separate from elaboration phase do { + wait(SC_ZERO_TIME); if (rst_i.read()) { cpu->reset(GET_PROP_VALUE(reset_address)); wait(rst_i.negedge_event()); From aa70d8a54a262179a53310cf9ad8273c78fd5c6f Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 2 May 2023 17:22:13 +0200 Subject: [PATCH 084/184] fixes CLIC to match clicinfo description in CLIC spec 11.04.2023 --- src/iss/arch/riscv_hart_m_p.h | 6 ------ src/iss/arch/riscv_hart_mu_p.h | 6 ------ 2 files changed, 12 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index bf1e32a..1462848 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -356,7 +356,6 @@ protected: std::unordered_map csr_rd_cb; std::unordered_map csr_wr_cb; uint8_t clic_cfg_reg{0}; - uint32_t clic_info_reg{0}; std::array clic_inttrig_reg; union clic_int_reg_t { struct{ @@ -521,7 +520,6 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr_wr_cb[mintthresh] = &this_class::write_intthresh; clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x20; - clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; clic_mact_lvl = clic_mprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; csr[mintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; insert_mem_range(cfg.clic_base, 0x5000UL, @@ -1178,8 +1176,6 @@ iss::status riscv_hart_m_p::read_clic(uint64_t addr, unsigned length if(addr==cfg.clic_base) { // cliccfg *data=clic_cfg_reg; for(auto i=1; i=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+8)){ // clicinfo - read_reg_uint32(addr, clic_info_reg, data, length); } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig auto offset = ((addr&0x7fff)-0x40)/4; read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); @@ -1196,8 +1192,6 @@ template iss::status riscv_hart_m_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { if(addr==cfg.clic_base) { // cliccfg clic_cfg_reg = (clic_cfg_reg&~0x1e) | (*data&0x1e); -// } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+4)){ // clicinfo -// write_uint32(addr, clic_info_reg, data, length); } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig auto offset = ((addr&0x7fff)-0x40)/4; write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 94f7e08..f8ab194 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -380,7 +380,6 @@ protected: std::unordered_map csr_rd_cb; std::unordered_map csr_wr_cb; uint8_t clic_cfg_reg{0}; - uint32_t clic_info_reg{0}; std::array clic_inttrig_reg; union clic_int_reg_t { struct{ @@ -589,7 +588,6 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) } clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); clic_cfg_reg=0x30; - clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + cfg.clic_num_irq; clic_mact_lvl = clic_mprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; clic_uact_lvl = clic_uprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; csr[mintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; @@ -1387,8 +1385,6 @@ iss::status riscv_hart_mu_p::read_clic(uint64_t addr, unsigned lengt if(addr==cfg.clic_base) { // cliccfg *data=clic_cfg_reg; for(auto i=1; i=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+8)){ // clicinfo - read_reg_uint32(addr, clic_info_reg, data, length); } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig auto offset = ((addr&0x7fff)-0x40)/4; read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); @@ -1405,8 +1401,6 @@ template iss::status riscv_hart_mu_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { if(addr==cfg.clic_base) { // cliccfg clic_cfg_reg = (clic_cfg_reg&~0x1e) | (*data&0x1e); -// } else if(addr>=(cfg.clic_base+4) && (addr+length)<=(cfg.clic_base+4)){ // clicinfo -// write_uint32(addr, clic_info_reg, data, length); } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig auto offset = ((addr&0x7fff)-0x40)/4; write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); From 916de2a26dd5e40c480e57431df2ae29941d8732 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 4 May 2023 16:08:33 +0200 Subject: [PATCH 085/184] changes build setup to compile specific files if a core is specified --- CMakeLists.txt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf7a3b0..3514f34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,19 +29,24 @@ endif() add_subdirectory(softfloat) -# library files -FILE(GLOB GEN_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp -) - set(LIB_SOURCES src/iss/plugin/instruction_count.cpp src/iss/arch/tgc_c.cpp src/vm/interp/vm_tgc_c.cpp src/vm/fp_functions.cpp - ${GEN_SOURCES} ) + +# library files +if(TARGET ${CORE_NAME}_cpp) + list(APPEND LIB_SOURCES ${${CORE_NAME}_OUTPUT_FILES}) +else() + FILE(GLOB GEN_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp + ) + list(APPEND LIB_SOURCES ${GEN_SOURCES}) +endif() + if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON) list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp src/iss/plugin/pctrace.cpp) endif() From d330307ed5fe7cae9c01bd875194e31f28cbe6d1 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 4 May 2023 21:59:31 +0200 Subject: [PATCH 086/184] splits bus into 2 sockets for i/dbus --- contrib/tgc_import_tb.tcl | 11 +++++++---- src/sysc/core_complex.cpp | 27 ++++++++++++++++++--------- src/sysc/core_complex.h | 9 +++++++-- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/contrib/tgc_import_tb.tcl b/contrib/tgc_import_tb.tcl index 6a7ce1d..fb44353 100644 --- a/contrib/tgc_import_tb.tcl +++ b/contrib/tgc_import_tb.tcl @@ -14,9 +14,11 @@ puts "instantiate testbench elements" ::BLWizard::generateFramework i_Bus SBLTLM2FT * {} \ { common_configuration:BackBone:/advanced/num_resources_per_target:1 } ::pct::set_bounds i_Bus 700 300 100 400 -::pct::create_connection C_init i_core_complex/initiator i_Bus/i_core_complex_initiator -::pct::set_location_on_owner i_Bus/i_core_complex_initiator 10 -::pct::create_connection C_targ i_Bus/i_Memory_Generic_MEM i_Memory_Generic/MEM +::pct::create_connection C_ibus i_core_complex/ibus i_Bus/i_core_complex_ibus +::pct::set_location_on_owner i_Bus/i_core_complex_ibus 10 +::pct::create_connection C_dbus i_core_complex/dbus i_Bus/i_core_complex_dbus +::pct::set_location_on_owner i_Bus/i_core_complex_dbus 10 +::pct::create_connection C_mem i_Bus/i_Memory_Generic_MEM i_Memory_Generic/MEM puts "instantiating clock manager" set clock "Clk" @@ -44,7 +46,8 @@ puts "connecting reset/clock" puts "setting parameters for DBT-RISE-TGC/Bus and memory components" ::pct::set_param_value $hardware/i_${top_design_name} {Extra properties} elf_file ${FW_name} -::pct::set_address $hardware/i_${top_design_name}/initiator:i_Memory_Generic/MEM 0x0 +::pct::set_address $hardware/i_${top_design_name}/ibus:i_Memory_Generic/MEM 0x0 +::pct::set_address $hardware/i_${top_design_name}/dbus:i_Memory_Generic/MEM 0x0 ::BLWizard::updateFramework i_Bus {} { common_configuration:BackBone:/advanced/num_resources_per_target:1 } ::pct::set_main_configuration Default {{#include } {::scc::init_logging(::scc::LogConfig().logLevel(::scc::log::INFO).coloredOutput(false).logAsync(false));} {} {} {}} diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 75da28e..9bb81cf 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -330,6 +330,7 @@ SC_HAS_PROCESS(core_complex);// NOLINT #ifndef CWR_SYSTEMC core_complex::core_complex(sc_module_name const& name) : sc_module(name) +, fetch_lut(tlm_dmi_ext()) , read_lut(tlm_dmi_ext()) , write_lut(tlm_dmi_ext()) { @@ -339,7 +340,13 @@ core_complex::core_complex(sc_module_name const& name) void core_complex::init(){ trc=new core_trace(); - initiator.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void { + ibus.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void { + auto lut_entry = fetch_lut.getEntry(start); + if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && end <= lut_entry.get_end_address() + 1) { + fetch_lut.removeEntry(lut_entry); + } + }); + dbus.register_invalidate_direct_mem_ptr([=](uint64_t start, uint64_t end) -> void { auto lut_entry = read_lut.getEntry(start); if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && end <= lut_entry.get_end_address() + 1) { read_lut.removeEntry(lut_entry); @@ -516,13 +523,15 @@ void core_complex::run() { } bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, bool is_fetch) { - auto lut_entry = read_lut.getEntry(addr); + auto& dmi_lut = is_fetch?fetch_lut:read_lut; + auto lut_entry = dmi_lut.getEntry(addr); if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) { auto offset = addr - lut_entry.get_start_address(); std::copy(lut_entry.get_dmi_ptr() + offset, lut_entry.get_dmi_ptr() + offset + length, data); quantum_keeper.inc(lut_entry.get_read_latency()); return true; } else { + auto& sckt = is_fetch? ibus : dbus; tlm::tlm_generic_payload gp; gp.set_command(tlm::TLM_READ_COMMAND); gp.set_address(addr); @@ -537,7 +546,7 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, auto preExt = new tlm::scc::scv::tlm_recording_extension(trc->tr_handle, this); gp.set_extension(preExt); } - initiator->b_transport(gp, delay); + sckt->b_transport(gp, delay); quantum_keeper.set(delay); SCCTRACE(this->name()) << "read_mem(0x" << std::hex << addr << ") : 0x" << (length==4?*(uint32_t*)data:length==2?*(uint16_t*)data:(unsigned)*data); if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { @@ -547,9 +556,9 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, gp.set_command(tlm::TLM_READ_COMMAND); gp.set_address(addr); tlm_dmi_ext dmi_data; - if (initiator->get_direct_mem_ptr(gp, dmi_data)) { + if (sckt->get_direct_mem_ptr(gp, dmi_data)) { if (dmi_data.is_read_allowed()) - read_lut.addEntry(dmi_data, dmi_data.get_start_address(), + dmi_lut.addEntry(dmi_data, dmi_data.get_start_address(), dmi_data.get_end_address() - dmi_data.get_start_address() + 1); } } @@ -579,7 +588,7 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *cons auto preExt = new tlm::scc::scv::tlm_recording_extension(trc->tr_handle, this); gp.set_extension(preExt); } - initiator->b_transport(gp, delay); + dbus->b_transport(gp, delay); quantum_keeper.set(delay); SCCTRACE() << "write_mem(0x" << std::hex << addr << ") : 0x" << (length==4?*(uint32_t*)data:length==2?*(uint16_t*)data:(unsigned)*data); if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { @@ -589,7 +598,7 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *cons gp.set_command(tlm::TLM_READ_COMMAND); gp.set_address(addr); tlm_dmi_ext dmi_data; - if (initiator->get_direct_mem_ptr(gp, dmi_data)) { + if (dbus->get_direct_mem_ptr(gp, dmi_data)) { if (dmi_data.is_write_allowed()) write_lut.addEntry(dmi_data, dmi_data.get_start_address(), dmi_data.get_end_address() - dmi_data.get_start_address() + 1); @@ -606,7 +615,7 @@ bool core_complex::read_mem_dbg(uint64_t addr, unsigned length, uint8_t *const d gp.set_data_ptr(data); gp.set_data_length(length); gp.set_streaming_width(length); - return initiator->transport_dbg(gp) == length; + return dbus->transport_dbg(gp) == length; } bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t *const data) { @@ -618,7 +627,7 @@ bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t * gp.set_data_ptr(write_buf.data()); gp.set_data_length(length); gp.set_streaming_width(length); - return initiator->transport_dbg(gp) == length; + return dbus->transport_dbg(gp) == length; } } /* namespace SiFive */ } /* namespace sysc */ diff --git a/src/sysc/core_complex.h b/src/sysc/core_complex.h index 9b53397..8c6680b 100644 --- a/src/sysc/core_complex.h +++ b/src/sysc/core_complex.h @@ -40,8 +40,10 @@ #include #ifdef CWR_SYSTEMC #include +#define SOCKET_WIDTH 32 #else #include +#define SOCKET_WIDTH scc::LT #endif #include #include @@ -69,7 +71,9 @@ struct core_trace; class core_complex : public sc_core::sc_module, public scc::traceable { public: - tlm::scc::initiator_mixin> initiator{"intor"}; + tlm::scc::initiator_mixin> ibus{"ibus"}; + + tlm::scc::initiator_mixin> dbus{"dbus"}; sc_core::sc_in rst_i{"rst_i"}; @@ -141,6 +145,7 @@ public: , dump_ir{"dump_ir", false} , mhartid{"mhartid", 0} , plugins{"plugins", ""} + , fetch_lut(tlm_dmi_ext()) , read_lut(tlm_dmi_ext()) , write_lut(tlm_dmi_ext()) { @@ -185,7 +190,7 @@ protected: void ext_irq_cb(); void local_irq_cb(); uint64_t last_sync_cycle = 0; - util::range_lut read_lut, write_lut; + util::range_lut fetch_lut, read_lut, write_lut; tlm_utils::tlm_quantumkeeper quantum_keeper; std::vector write_buf; core_wrapper* cpu{nullptr}; From cfa7b7236397dc84062dc108aadf4bb9c2a02e2b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 6 May 2023 19:57:29 +0200 Subject: [PATCH 087/184] changes time handling at sockets --- contrib/tgc_import_tb.tcl | 6 +++--- src/sysc/core_complex.cpp | 15 ++++++++++----- src/sysc/core_complex.h | 10 +++++++--- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/contrib/tgc_import_tb.tcl b/contrib/tgc_import_tb.tcl index fb44353..3150eb8 100644 --- a/contrib/tgc_import_tb.tcl +++ b/contrib/tgc_import_tb.tcl @@ -5,9 +5,9 @@ set FW_name ${scriptDir}/hello.elf puts "instantiate testbench elements" ::paultra::add_hw_instance GenericIPlib:Memory_Generic -inst_name i_Memory_Generic ::pct::set_param_value i_Memory_Generic/MEM:protocol {Protocol Common Parameters} address_width 30 -#::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/LT/clock_period_in_ns 1 -#::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/read/cmd_accept_cycles 1 -#::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/write/cmd_accept_cycles 1 +::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/LT/clock_period_in_ns 1 +::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/read/cmd_accept_cycles 1 +::pct::set_param_value i_Memory_Generic {Scml Properties} /timing/write/cmd_accept_cycles 1 ::pct::set_bounds i_Memory_Generic 1000 300 100 100 ::paultra::add_hw_instance Bus:Bus -inst_name i_Bus diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 9bb81cf..8b8d75c 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -107,7 +107,8 @@ public: heart_state_t &get_state() { return this->state; } void notify_phase(iss::arch_if::exec_phase p) override { - if (p == iss::arch_if::ISTART) owner->sync(this->icount); + if (p == iss::arch_if::ISTART) + owner->sync(this->instr_if.get_total_cycles()); } sync_type needed_sync() const override { return PRE_SYNC; } @@ -547,8 +548,12 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, gp.set_extension(preExt); } sckt->b_transport(gp, delay); - quantum_keeper.set(delay); - SCCTRACE(this->name()) << "read_mem(0x" << std::hex << addr << ") : 0x" << (length==4?*(uint32_t*)data:length==2?*(uint16_t*)data:(unsigned)*data); + auto incr = delay-quantum_keeper.get_local_time(); + if(is_fetch) + ibus_inc+=incr; + else + dbus_inc+=incr; + SCCTRACE(this->name()) << "[local time: "<b_transport(gp, delay); - quantum_keeper.set(delay); - SCCTRACE() << "write_mem(0x" << std::hex << addr << ") : 0x" << (length==4?*(uint32_t*)data:length==2?*(uint16_t*)data:(unsigned)*data); + dbus_inc+=delay-quantum_keeper.get_local_time(); + SCCTRACE() << "[local time: "< write_buf; core_wrapper* cpu{nullptr}; sc_core::sc_signal curr_clk; + sc_core::sc_time ibus_inc, dbus_inc; core_trace* trc{nullptr}; std::unique_ptr t2t; private: @@ -202,7 +206,7 @@ private: std::vector plugin_list; }; -} /* namespace SiFive */ +} /* namespace tgfs */ } /* namespace sysc */ #endif /* _SYSC_CORE_COMPLEX_H_ */ From afdf8fb97f7e8102ddc96129373a676cd0422bf0 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 11 May 2023 23:11:04 +0200 Subject: [PATCH 088/184] adds missing namespaces --- src/sysc/core_complex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sysc/core_complex.h b/src/sysc/core_complex.h index 933432d..f9430f4 100644 --- a/src/sysc/core_complex.h +++ b/src/sysc/core_complex.h @@ -165,8 +165,8 @@ public: quantum_keeper.reset(); } last_sync_cycle = cycle; - ibus_inc = SC_ZERO_TIME; - dbus_inc = SC_ZERO_TIME; + ibus_inc = sc_core::SC_ZERO_TIME; + dbus_inc = sc_core::SC_ZERO_TIME; } bool read_mem(uint64_t addr, unsigned length, uint8_t *const data, bool is_fetch); From fd6b7381683b62cd7860b74b6d05fb37f314c5b1 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 11 May 2023 23:43:12 +0200 Subject: [PATCH 089/184] changes compile dependencies --- CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3514f34..e135fb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -166,10 +166,8 @@ install(TARGETS tgc-sim ############################################################################### # ############################################################################### -project(dbt-rise-tgc_sc VERSION 1.0.0) - -include(SystemCPackage) -if(SystemC_FOUND) +if(TARGET scc-sysc) + project(dbt-rise-tgc_sc VERSION 1.0.0) add_library(${PROJECT_NAME} src/sysc/core_complex.cpp) target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC) target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) From 3bc4884a9d87a0a367ea462bdc455036cfa7e1ac Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 12 May 2023 09:28:43 +0200 Subject: [PATCH 090/184] remove unneeded cmake include --- softfloat/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/softfloat/CMakeLists.txt b/softfloat/CMakeLists.txt index c4ea4bd..b2ff9df 100644 --- a/softfloat/CMakeLists.txt +++ b/softfloat/CMakeLists.txt @@ -8,7 +8,7 @@ project("sotfloat" VERSION 3.0.0) # Set the version number of your project here (format is MAJOR.MINOR.PATCHLEVEL - e.g. 1.0.0) set(VERSION "3e") -include(Common) +#include(Common) include(GNUInstallDirs) set(SPECIALIZATION RISCV) From 6789cf4c328be24d8ae5e05b6c9d6f09c70244c8 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 12 May 2023 15:45:53 +0200 Subject: [PATCH 091/184] fixes case of unavailable backend --- src/main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 2948993..34e71b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -161,6 +161,14 @@ int main(int argc, char *argv[]) { LOG(ERR) << "Illegal argument value for '--isa': " << isa_opt << std::endl; return 127; } + if(!cpu ){ + LOG(ERR) << "Could not create cpu fore for isa " << isa_opt << " and backend " <()<< std::endl; + return 127; + } + if(!vm ){ + LOG(ERR) << "Could not create vm fore for isa " << isa_opt << " and backend " <()<< std::endl; + return 127; + } if (clim.count("plugin")) { for (std::string const& opt_val : clim["plugin"].as>()) { std::string plugin_name=opt_val; From 32848ec3969d02a40c43961e9302b8b7b49e915c Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 13 May 2023 16:57:01 +0200 Subject: [PATCH 092/184] fixes build system and typo in wt_cache --- CMakeLists.txt | 11 ++++++++++- src/iss/arch/riscv_hart_mu_p.h | 8 ++++---- src/iss/arch/wt_cache.h | 4 ++-- src/sysc/core_complex.cpp | 2 +- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e135fb7..1625ee5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,7 +131,16 @@ project(tgc-sim) find_package(Boost COMPONENTS program_options thread REQUIRED) add_executable(${PROJECT_NAME} src/main.cpp) -FILE(GLOB TGC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp) +if(TARGET ${CORE_NAME}_cpp) + list(APPEND TGC_SOURCES ${${CORE_NAME}_OUTPUT_FILES}) +else() + FILE(GLOB TGC_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp + ) + list(APPEND TGC_SOURCES ${GEN_SOURCES}) +endif() + foreach(F IN LISTS TGC_SOURCES) string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) string(TOUPPER ${CORE_NAME_LC} CORE_NAME) diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index f8ab194..719276d 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -803,7 +803,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc #ifndef NDEBUG if (access && iss::access_type::DEBUG) { LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; - } else if(access && iss::access_type::FETCH){ + } else if(is_fetch(access)){ LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; } else { LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; @@ -835,7 +835,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc } auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); auto res = iss::Err; - if(access != access_type::FETCH && memfn_range.size()){ + if(!is_fetch(access) && memfn_range.size()){ auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; }); @@ -922,7 +922,7 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac return iss::Err; } } - if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { + if (unlikely(is_fetch(access) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); this->trap_state = (1UL << 31); // issue trap 0 @@ -936,7 +936,7 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac } auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); auto res = iss::Err; - if(access != access_type::FETCH && memfn_range.size()){ + if(!is_fetch(access) && memfn_range.size()){ auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; }); diff --git a/src/iss/arch/wt_cache.h b/src/iss/arch/wt_cache.h index d5acf3c..2b3835b 100644 --- a/src/iss/arch/wt_cache.h +++ b/src/iss/arch/wt_cache.h @@ -120,7 +120,7 @@ iss::status iss::arch::wt_cache::read_cache(phys_addr_t a, unsigned l, uin if((a.val&io_addr_mask) != io_address) { auto set_addr=(a.val&(size-1))>>util::ilog2(line_sz*ways); auto tag_addr=a.val>>util::ilog2(line_sz); - auto& set = (a.access==access_type::FETCH?icache_ptr:dcache_ptr)->sets[set_addr]; + auto& set = (is_fetch(a.access)?icache_ptr:dcache_ptr)->sets[set_addr]; for(auto& cl: set.ways) { if(cl.st==cache::state::VALID && cl.tag_addr==tag_addr) { auto start_addr = a.val&(line_sz-1); @@ -156,7 +156,7 @@ iss::status iss::arch::wt_cache::write_cache(phys_addr_t a, unsigned l, co if(cl.st==cache::state::VALID && cl.tag_addr==tag_addr) { auto start_addr = a.val&(line_sz-1); for(auto i = 0U; iread_mem_dbg(addr.val, length, data) ? Ok : Err; else { - return owner->read_mem(addr.val, length, data, addr.access && access_type::FETCH) ? Ok : Err; + return owner->read_mem(addr.val, length, data, is_fetch(addr.access)) ? Ok : Err; } } From 95ba5c901a8ece103946f6f6aaee3734b0668837 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 14 May 2023 17:00:37 +0200 Subject: [PATCH 093/184] re-introduces last_branch register --- gen_input/templates/CORENAME.cpp.gtl | 1 + gen_input/templates/CORENAME.h.gtl | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl index b99a67e..07ce7a3 100644 --- a/gen_input/templates/CORENAME.cpp.gtl +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -34,6 +34,7 @@ def getRegisterSizes(){ def regs = registers.collect{it.size} regs[-1]=64 // correct for NEXT_PC //regs+=[32, 32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION + regs += [32] // append LAST_BRANCH return regs } %> diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 1765fde..8f10609 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -38,6 +38,7 @@ def nativeTypeSize(int size){ def getRegisterSizes(){ def regs = registers.collect{nativeTypeSize(it.size)} // regs+=[32,32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION + regs += [32] // append LAST_BRANCH return regs } def getRegisterOffsets(){ @@ -91,7 +92,7 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { constexpr static unsigned FP_REGS_SIZE = ${constants.find {it.name=='FLEN'}?.value?:0}; enum reg_e { - ${registers.collect{it.name}.join(', ')}, NUM_REGS + ${registers.collect{it.name}.join(', ')}, NUM_REGS, LAST_BRANCH=NUM_REGS }; using reg_t = uint${addrDataWidth}_t; @@ -162,6 +163,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { registers.each { reg -> if(reg.size>0) {%> uint${byteSize(reg.size)}_t ${reg.name} = 0;<% }}%> + uint32_t last_branch = 0; } reg; #pragma pack(pop) uint32_t trap_state = 0, pending_trap = 0; From ee2ded931d88a6ed91d1f8670c1f0b23259795de Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sun, 14 May 2023 17:16:42 +0200 Subject: [PATCH 094/184] adds remaining register offsets --- gen_input/templates/CORENAME.cpp.gtl | 3 +-- gen_input/templates/CORENAME.h.gtl | 10 +++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl index 07ce7a3..3a06133 100644 --- a/gen_input/templates/CORENAME.cpp.gtl +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -33,8 +33,7 @@ def getRegisterSizes(){ def regs = registers.collect{it.size} regs[-1]=64 // correct for NEXT_PC - //regs+=[32, 32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION - regs += [32] // append LAST_BRANCH + regs+=[32,32, 64, 64, 64, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH return regs } %> diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 8f10609..563631f 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -37,8 +37,7 @@ def nativeTypeSize(int size){ } def getRegisterSizes(){ def regs = registers.collect{nativeTypeSize(it.size)} - // regs+=[32,32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION - regs += [32] // append LAST_BRANCH + regs+=[32,32, 64, 64, 64, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH return regs } def getRegisterOffsets(){ @@ -92,7 +91,7 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { constexpr static unsigned FP_REGS_SIZE = ${constants.find {it.name=='FLEN'}?.value?:0}; enum reg_e { - ${registers.collect{it.name}.join(', ')}, NUM_REGS, LAST_BRANCH=NUM_REGS + ${registers.collect{it.name}.join(', ')}, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH }; using reg_t = uint${addrDataWidth}_t; @@ -163,6 +162,11 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { registers.each { reg -> if(reg.size>0) {%> uint${byteSize(reg.size)}_t ${reg.name} = 0;<% }}%> + uint32_t trap_state = 0, pending_trap = 0; + uint64_t icount = 0; + uint64_t cycle = 0; + uint64_t instret = 0; + uint32_t instruction = 0; uint32_t last_branch = 0; } reg; #pragma pack(pop) From 16cd6d5ff59d6aefeee13cf34d79afa2015b2e9b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 16 May 2023 08:54:08 +0200 Subject: [PATCH 095/184] fixes core name deduction in cmake build script --- CMakeLists.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1625ee5..01a433f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,9 +142,11 @@ else() endif() foreach(F IN LISTS TGC_SOURCES) - string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) - string(TOUPPER ${CORE_NAME_LC} CORE_NAME) - target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) + if (${F} MATCHES ".*/arch/([^/]*)\.cpp") + string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) + string(TOUPPER ${CORE_NAME_LC} CORE_NAME) + target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) + endif() endforeach() if(WITH_LLVM) @@ -181,9 +183,11 @@ if(TARGET scc-sysc) target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC) target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) foreach(F IN LISTS TGC_SOURCES) - string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) - string(TOUPPER ${CORE_NAME_LC} CORE_NAME) - target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) + if (${F} MATCHES ".*/arch/([^/]*)\.cpp") + string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) + string(TOUPPER ${CORE_NAME_LC} CORE_NAME) + target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) + endif() endforeach() target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc) if(WITH_LLVM) From 8a5fe58d51b6c5d7fae5953c8cf8b26bec840537 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 16 May 2023 08:56:18 +0200 Subject: [PATCH 096/184] adds needed arch state members for TCC to tgc_c --- src/iss/arch/tgc_c.cpp | 4 ++-- src/iss/arch/tgc_c.h | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/iss/arch/tgc_c.cpp b/src/iss/arch/tgc_c.cpp index 6357ced..ed4d7ca 100644 --- a/src/iss/arch/tgc_c.cpp +++ b/src/iss/arch/tgc_c.cpp @@ -41,8 +41,8 @@ using namespace iss::arch; constexpr std::array iss::arch::traits::reg_names; constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; tgc_c::tgc_c() = default; diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index 239ea60..53776c0 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -58,7 +58,7 @@ template <> struct traits { constexpr static unsigned FP_REGS_SIZE = 0; enum reg_e { - X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS + 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, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH }; using reg_t = uint32_t; @@ -71,11 +71,11 @@ template <> struct traits { using phys_addr_t = iss::typed_addr_t; - static constexpr std::array reg_bit_widths{ - {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32}}; + static constexpr std::array reg_bit_widths{ + {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64,32,32}}; - static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137}}; + static constexpr std::array reg_byte_offsets{ + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165,173,177}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); @@ -248,6 +248,12 @@ struct tgc_c: public arch_if { uint32_t NEXT_PC = 0; uint8_t PRIV = 0; uint32_t DPC = 0; + uint32_t trap_state = 0, pending_trap = 0; + uint64_t icount = 0; + uint64_t cycle = 0; + uint64_t instret = 0; + uint32_t instruction = 0; + uint32_t last_branch = 0; } reg; #pragma pack(pop) uint32_t trap_state = 0, pending_trap = 0; From 6ed7eafc5def291957a5fd539cc5ce403f46fb05 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Tue, 16 May 2023 21:51:35 +0200 Subject: [PATCH 097/184] adds inital version of tcc backend --- CMakeLists.txt | 3 + .../templates/tcc/vm-vm_CORENAME.cpp.gtl | 45 +- src/iss/arch/tgc_c.cpp | 4 +- src/iss/arch/tgc_c.h | 18 +- src/iss/factory.h | 2 +- src/main.cpp | 4 +- src/vm/tcc/vm_tgc_c.cpp | 3366 ++++++++--------- 7 files changed, 1715 insertions(+), 1727 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1625ee5..e6f37bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,6 +151,9 @@ if(WITH_LLVM) target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM) target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) endif() +if(WITH_TCC) + target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC) +endif() # Links the target exe against the libraries target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc) if(TARGET Boost::program_options) diff --git a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl index 23c5dd0..b37586c 100644 --- a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl @@ -55,10 +55,12 @@ using namespace iss::debugger; template class vm_impl : public iss::tcc::vm_base { public: + using traits = arch::traits; using super = typename iss::tcc::vm_base; using virt_addr_t = typename super::virt_addr_t; using phys_addr_t = typename super::phys_addr_t; using code_word_t = typename super::code_word_t; + using mem_type_e = typename traits::mem_type_e; using addr_t = typename super::addr_t; using tu_builder = typename super::tu_builder; @@ -82,7 +84,7 @@ protected: using compile_ret_t = std::tuple; using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&); - inline const char *name(size_t index){return traits::reg_aliases.at(index);} + inline const char *name(size_t index){return traits::reg_aliases.at(index);} void setup_module(std::string m) override { super::setup_module(m); @@ -104,10 +106,10 @@ protected: inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) { switch(reg_num){ - case traits::NEXT_PC: + case traits::NEXT_PC: tu("*next_pc = {:#x};", pc.val); break; - case traits::PC: + case traits::PC: tu("*pc = {:#x};", pc.val); break; default: @@ -123,7 +125,7 @@ protected: // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; std::array lut; @@ -170,6 +172,12 @@ protected: } return lut_val; } + template::type> + inline S sext(U from) { + auto mask = (1ULL< instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> /* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */ - {${instr.length}, 0b${instr.value}, 0b${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> + {${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> }}; /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> /* instruction ${idx}: ${instr.name} */ - compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){<%instr.code.eachLine{%> + compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("${instr.name}_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,${idx}); + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate console output when executing the command */<%instr.disass.eachLine{%> + ${it}<%}%> + } + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; + tu.open_scope();<%instr.behavior.eachLine{%> ${it}<%}%> + vm_base::gen_sync(tu, POST_SYNC,${idx}); + gen_trap_check(tu); + return returnValue; } <%}%> /**************************************************************************** @@ -233,7 +254,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; + const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); auto *const data = (uint8_t *)&insn; paddr = this->core.v2p(pc); @@ -260,13 +281,13 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(), 32)); } template void vm_impl::gen_leave_trap(tu_builder& tu, unsigned lvl) { tu("leave_trap(core_ptr, {});", lvl); - tu.store(tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN),traits::NEXT_PC); - tu.store(tu.constant(std::numeric_limits::max(), 32),traits::LAST_BRANCH); + tu.store(traits::NEXT_PC, tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN)); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(), 32)); } template void vm_impl::gen_wait(tu_builder& tu, unsigned type) { @@ -274,8 +295,8 @@ template void vm_impl::gen_wait(tu_builder& tu, unsigned t template void vm_impl::gen_trap_behavior(tu_builder& tu) { tu("trap_entry:"); - tu("enter_trap(core_ptr, *trap_state, *pc);"); - tu.store(tu.constant(std::numeric_limits::max(),32),traits::LAST_BRANCH); + tu("enter_trap(core_ptr, *trap_state, *pc, 0);"); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(),32)); tu("return *next_pc;"); } diff --git a/src/iss/arch/tgc_c.cpp b/src/iss/arch/tgc_c.cpp index 6357ced..ed4d7ca 100644 --- a/src/iss/arch/tgc_c.cpp +++ b/src/iss/arch/tgc_c.cpp @@ -41,8 +41,8 @@ using namespace iss::arch; constexpr std::array iss::arch::traits::reg_names; constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; tgc_c::tgc_c() = default; diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index 239ea60..d1fdfed 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -53,12 +53,12 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; - enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; + enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, PGMASK=0b111111111111, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; constexpr static unsigned FP_REGS_SIZE = 0; enum reg_e { - X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS + 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, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH }; using reg_t = uint32_t; @@ -71,11 +71,11 @@ template <> struct traits { using phys_addr_t = iss::typed_addr_t; - static constexpr std::array reg_bit_widths{ - {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32}}; + static constexpr std::array reg_bit_widths{ + {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64,32,32}}; - static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137}}; + static constexpr std::array reg_byte_offsets{ + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165,173,177}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); @@ -248,6 +248,12 @@ struct tgc_c: public arch_if { uint32_t NEXT_PC = 0; uint8_t PRIV = 0; uint32_t DPC = 0; + uint32_t trap_state = 0, pending_trap = 0; + uint64_t icount = 0; + uint64_t cycle = 0; + uint64_t instret = 0; + uint32_t instruction = 0; + uint32_t last_branch = 0; } reg; #pragma pack(pop) uint32_t trap_state = 0, pending_trap = 0; diff --git a/src/iss/factory.h b/src/iss/factory.h index 1664e38..0d43538 100644 --- a/src/iss/factory.h +++ b/src/iss/factory.h @@ -50,7 +50,7 @@ std::tuple create_cpu(std::string const& backend, unsigned gdb_ if(backend == "llvm") return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}}; #endif -#ifdef WITH_LLVM +#ifdef WITH_TCC if(backend == "tcc") return {cpu_ptr{lcpu}, vm_ptr{iss::tcc::create(lcpu, gdb_port)}}; #endif diff --git a/src/main.cpp b/src/main.cpp index 34e71b5..2cd1316 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -162,11 +162,11 @@ int main(int argc, char *argv[]) { return 127; } if(!cpu ){ - LOG(ERR) << "Could not create cpu fore for isa " << isa_opt << " and backend " <()<< std::endl; + LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " <()<< std::endl; return 127; } if(!vm ){ - LOG(ERR) << "Could not create vm fore for isa " << isa_opt << " and backend " <()<< std::endl; + LOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " <()<< std::endl; return 127; } if (clim.count("plugin")) { diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index ceda6ce..bd988a0 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -55,10 +55,12 @@ using namespace iss::debugger; template class vm_impl : public iss::tcc::vm_base { public: + using traits = arch::traits; using super = typename iss::tcc::vm_base; using virt_addr_t = typename super::virt_addr_t; using phys_addr_t = typename super::phys_addr_t; using code_word_t = typename super::code_word_t; + using mem_type_e = typename traits::mem_type_e; using addr_t = typename super::addr_t; using tu_builder = typename super::tu_builder; @@ -82,7 +84,7 @@ protected: using compile_ret_t = std::tuple; using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&); - inline const char *name(size_t index){return traits::reg_aliases.at(index);} + inline const char *name(size_t index){return traits::reg_aliases.at(index);} void setup_module(std::string m) override { super::setup_module(m); @@ -104,10 +106,10 @@ protected: inline void gen_set_pc(tu_builder& tu, virt_addr_t pc, unsigned reg_num) { switch(reg_num){ - case traits::NEXT_PC: + case traits::NEXT_PC: tu("*next_pc = {:#x};", pc.val); break; - case traits::PC: + case traits::PC: tu("*pc = {:#x};", pc.val); break; default: @@ -123,7 +125,7 @@ protected: // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; std::array lut; @@ -170,6 +172,12 @@ protected: } return lut_val; } + template::type> + inline S sext(U from) { + auto mask = (1ULL< instr_descr = {{ + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ - /* instruction LUI, encoding '.........................0110111' */ + /* instruction LUI, encoding '0b00000000000000000000000000110111' */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC, encoding '.........................0010111' */ + /* instruction AUIPC, encoding '0b00000000000000000000000000010111' */ {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL, encoding '.........................1101111' */ + /* instruction JAL, encoding '0b00000000000000000000000001101111' */ {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR, encoding '.................000.....1100111' */ + /* instruction JALR, encoding '0b00000000000000000000000001100111' */ {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ, encoding '.................000.....1100011' */ + /* instruction BEQ, encoding '0b00000000000000000000000001100011' */ {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE, encoding '.................001.....1100011' */ + /* instruction BNE, encoding '0b00000000000000000001000001100011' */ {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT, encoding '.................100.....1100011' */ + /* instruction BLT, encoding '0b00000000000000000100000001100011' */ {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE, encoding '.................101.....1100011' */ + /* instruction BGE, encoding '0b00000000000000000101000001100011' */ {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU, encoding '.................110.....1100011' */ + /* instruction BLTU, encoding '0b00000000000000000110000001100011' */ {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU, encoding '.................111.....1100011' */ + /* instruction BGEU, encoding '0b00000000000000000111000001100011' */ {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB, encoding '.................000.....0000011' */ + /* instruction LB, encoding '0b00000000000000000000000000000011' */ {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH, encoding '.................001.....0000011' */ + /* instruction LH, encoding '0b00000000000000000001000000000011' */ {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW, encoding '.................010.....0000011' */ + /* instruction LW, encoding '0b00000000000000000010000000000011' */ {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU, encoding '.................100.....0000011' */ + /* instruction LBU, encoding '0b00000000000000000100000000000011' */ {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU, encoding '.................101.....0000011' */ + /* instruction LHU, encoding '0b00000000000000000101000000000011' */ {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB, encoding '.................000.....0100011' */ + /* instruction SB, encoding '0b00000000000000000000000000100011' */ {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH, encoding '.................001.....0100011' */ + /* instruction SH, encoding '0b00000000000000000001000000100011' */ {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW, encoding '.................010.....0100011' */ + /* instruction SW, encoding '0b00000000000000000010000000100011' */ {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI, encoding '.................000.....0010011' */ + /* instruction ADDI, encoding '0b00000000000000000000000000010011' */ {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI, encoding '.................010.....0010011' */ + /* instruction SLTI, encoding '0b00000000000000000010000000010011' */ {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU, encoding '.................011.....0010011' */ + /* instruction SLTIU, encoding '0b00000000000000000011000000010011' */ {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI, encoding '.................100.....0010011' */ + /* instruction XORI, encoding '0b00000000000000000100000000010011' */ {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI, encoding '.................110.....0010011' */ + /* instruction ORI, encoding '0b00000000000000000110000000010011' */ {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI, encoding '.................111.....0010011' */ + /* instruction ANDI, encoding '0b00000000000000000111000000010011' */ {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI, encoding '0000000..........001.....0010011' */ + /* instruction SLLI, encoding '0b00000000000000000001000000010011' */ {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI, encoding '0000000..........101.....0010011' */ + /* instruction SRLI, encoding '0b00000000000000000101000000010011' */ {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI, encoding '0100000..........101.....0010011' */ + /* instruction SRAI, encoding '0b01000000000000000101000000010011' */ {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD, encoding '0000000..........000.....0110011' */ + /* instruction ADD, encoding '0b00000000000000000000000000110011' */ {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB, encoding '0100000..........000.....0110011' */ + /* instruction SUB, encoding '0b01000000000000000000000000110011' */ {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL, encoding '0000000..........001.....0110011' */ + /* instruction SLL, encoding '0b00000000000000000001000000110011' */ {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT, encoding '0000000..........010.....0110011' */ + /* instruction SLT, encoding '0b00000000000000000010000000110011' */ {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU, encoding '0000000..........011.....0110011' */ + /* instruction SLTU, encoding '0b00000000000000000011000000110011' */ {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR, encoding '0000000..........100.....0110011' */ + /* instruction XOR, encoding '0b00000000000000000100000000110011' */ {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL, encoding '0000000..........101.....0110011' */ + /* instruction SRL, encoding '0b00000000000000000101000000110011' */ {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA, encoding '0100000..........101.....0110011' */ + /* instruction SRA, encoding '0b01000000000000000101000000110011' */ {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR, encoding '0000000..........110.....0110011' */ + /* instruction OR, encoding '0b00000000000000000110000000110011' */ {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND, encoding '0000000..........111.....0110011' */ + /* instruction AND, encoding '0b00000000000000000111000000110011' */ {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE, encoding '0000.............000.....0001111' */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I, encoding '.................001.....0001111' */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL, encoding '00000000000000000000000001110011' */ + /* instruction FENCE, encoding '0b00000000000000000000000000001111' */ + {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, &this_class::__fence}, + /* instruction ECALL, encoding '0b00000000000000000000000001110011' */ {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK, encoding '00000000000100000000000001110011' */ + /* instruction EBREAK, encoding '0b00000000000100000000000001110011' */ {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET, encoding '00000000001000000000000001110011' */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET, encoding '00010000001000000000000001110011' */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET, encoding '00110000001000000000000001110011' */ + /* instruction MRET, encoding '0b00110000001000000000000001110011' */ {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI, encoding '00010000010100000000000001110011' */ + /* instruction WFI, encoding '0b00010000010100000000000001110011' */ {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA, encoding '0001001..........000000001110011' */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW, encoding '.................001.....1110011' */ + /* instruction CSRRW, encoding '0b00000000000000000001000001110011' */ {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS, encoding '.................010.....1110011' */ + /* instruction CSRRS, encoding '0b00000000000000000010000001110011' */ {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC, encoding '.................011.....1110011' */ + /* instruction CSRRC, encoding '0b00000000000000000011000001110011' */ {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI, encoding '.................101.....1110011' */ + /* instruction CSRRWI, encoding '0b00000000000000000101000001110011' */ {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI, encoding '.................110.....1110011' */ + /* instruction CSRRSI, encoding '0b00000000000000000110000001110011' */ {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI, encoding '.................111.....1110011' */ + /* instruction CSRRCI, encoding '0b00000000000000000111000001110011' */ {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction MUL, encoding '0000001..........000.....0110011' */ + /* instruction FENCE_I, encoding '0b00000000000000000001000000001111' */ + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, + /* instruction MUL, encoding '0b00000010000000000000000000110011' */ {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH, encoding '0000001..........001.....0110011' */ + /* instruction MULH, encoding '0b00000010000000000001000000110011' */ {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU, encoding '0000001..........010.....0110011' */ + /* instruction MULHSU, encoding '0b00000010000000000010000000110011' */ {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU, encoding '0000001..........011.....0110011' */ + /* instruction MULHU, encoding '0b00000010000000000011000000110011' */ {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV, encoding '0000001..........100.....0110011' */ + /* instruction DIV, encoding '0b00000010000000000100000000110011' */ {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU, encoding '0000001..........101.....0110011' */ + /* instruction DIVU, encoding '0b00000010000000000101000000110011' */ {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM, encoding '0000001..........110.....0110011' */ + /* instruction REM, encoding '0b00000010000000000110000000110011' */ {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU, encoding '0000001..........111.....0110011' */ + /* instruction REMU, encoding '0b00000010000000000111000000110011' */ {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction C.ADDI4SPN, encoding '000...........00' */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW, encoding '010...........00' */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW, encoding '110...........00' */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI, encoding '000...........01' */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP, encoding '0000000000000001' */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL, encoding '001...........01' */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI, encoding '010...........01' */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI, encoding '011...........01' */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP, encoding '011.00010.....01' */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI, encoding '100000........01' */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI, encoding '100001........01' */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI, encoding '100.10........01' */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB, encoding '100011...00...01' */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR, encoding '100011...01...01' */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR, encoding '100011...10...01' */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND, encoding '100011...11...01' */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J, encoding '101...........01' */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ, encoding '110...........01' */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ, encoding '111...........01' */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI, encoding '0000..........10' */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP, encoding '010...........10' */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV, encoding '1000..........10' */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR, encoding '1000.....0000010' */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD, encoding '1001..........10' */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR, encoding '1001.....0000010' */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK, encoding '1001000000000010' */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP, encoding '110...........10' */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII, encoding '0000000000000000' */ + /* instruction CADDI4SPN, encoding '0b0000000000000000' */ + {16, 0b0000000000000000, 0b1110000000000011, &this_class::__caddi4spn}, + /* instruction CLW, encoding '0b0100000000000000' */ + {16, 0b0100000000000000, 0b1110000000000011, &this_class::__clw}, + /* instruction CSW, encoding '0b1100000000000000' */ + {16, 0b1100000000000000, 0b1110000000000011, &this_class::__csw}, + /* instruction CADDI, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110000000000011, &this_class::__caddi}, + /* instruction CNOP, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110111110000011, &this_class::__cnop}, + /* instruction CJAL, encoding '0b0010000000000001' */ + {16, 0b0010000000000001, 0b1110000000000011, &this_class::__cjal}, + /* instruction CLI, encoding '0b0100000000000001' */ + {16, 0b0100000000000001, 0b1110000000000011, &this_class::__cli}, + /* instruction CLUI, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1110000000000011, &this_class::__clui}, + /* instruction CADDI16SP, encoding '0b0110000100000001' */ + {16, 0b0110000100000001, 0b1110111110000011, &this_class::__caddi16sp}, + /* instruction __reserved_clui, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1111000001111111, &this_class::____reserved_clui}, + /* instruction CSRLI, encoding '0b1000000000000001' */ + {16, 0b1000000000000001, 0b1111110000000011, &this_class::__csrli}, + /* instruction CSRAI, encoding '0b1000010000000001' */ + {16, 0b1000010000000001, 0b1111110000000011, &this_class::__csrai}, + /* instruction CANDI, encoding '0b1000100000000001' */ + {16, 0b1000100000000001, 0b1110110000000011, &this_class::__candi}, + /* instruction CSUB, encoding '0b1000110000000001' */ + {16, 0b1000110000000001, 0b1111110001100011, &this_class::__csub}, + /* instruction CXOR, encoding '0b1000110000100001' */ + {16, 0b1000110000100001, 0b1111110001100011, &this_class::__cxor}, + /* instruction COR, encoding '0b1000110001000001' */ + {16, 0b1000110001000001, 0b1111110001100011, &this_class::__cor}, + /* instruction CAND, encoding '0b1000110001100001' */ + {16, 0b1000110001100001, 0b1111110001100011, &this_class::__cand}, + /* instruction CJ, encoding '0b1010000000000001' */ + {16, 0b1010000000000001, 0b1110000000000011, &this_class::__cj}, + /* instruction CBEQZ, encoding '0b1100000000000001' */ + {16, 0b1100000000000001, 0b1110000000000011, &this_class::__cbeqz}, + /* instruction CBNEZ, encoding '0b1110000000000001' */ + {16, 0b1110000000000001, 0b1110000000000011, &this_class::__cbnez}, + /* instruction CSLLI, encoding '0b0000000000000010' */ + {16, 0b0000000000000010, 0b1111000000000011, &this_class::__cslli}, + /* instruction CLWSP, encoding '0b0100000000000010' */ + {16, 0b0100000000000010, 0b1110000000000011, &this_class::__clwsp}, + /* instruction CMV, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000000000011, &this_class::__cmv}, + /* instruction CJR, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000001111111, &this_class::__cjr}, + /* instruction __reserved_cmv, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111111111111111, &this_class::____reserved_cmv}, + /* instruction CADD, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000000000011, &this_class::__cadd}, + /* instruction CJALR, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000001111111, &this_class::__cjalr}, + /* instruction CEBREAK, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__cebreak}, + /* instruction CSWSP, encoding '0b1100000000000010' */ + {16, 0b1100000000000010, 0b1110000000000011, &this_class::__cswsp}, + /* instruction DII, encoding '0b0000000000000000' */ {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, }}; @@ -366,851 +372,854 @@ private: /* instruction 0: LUI */ compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 0); + vm_base::gen_sync(tu, PRE_SYNC,0); uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.constant(imm, 32U), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.constant((uint32_t)((int32_t)imm),32)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 0); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,0); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 1: AUIPC */ compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("AUIPC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 1); + vm_base::gen_sync(tu, PRE_SYNC,1); uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)imm,32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 1); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,1); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 2: JAL */ compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 2); + vm_base::gen_sync(tu, PRE_SYNC,2); uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); + uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 4,32))); + } + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)sext<21>(imm),32)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } } - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 2); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,2); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 3: JALR */ compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 3); + vm_base::gen_sync(tu, PRE_SYNC,3); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto new_pc_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.add( - cur_pc_val, - tu.constant(4, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto new_pc = tu.assignment(tu.bitwise_and((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),tu.constant(~ 0x1,8)),32); + tu.open_if(tu.srem(new_pc,tu.constant(static_cast(traits:: INSTR_ALIGNMENT),32))); + this->gen_raise_trap(tu, 0, 0); + tu.open_else(); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 4,32))); + } + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + tu.close_scope(); } - auto PC_val_v = tu.assignment("PC_val", tu.l_and( - new_pc_val, - tu.l_not(tu.constant(0x1, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 3); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,3); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 4: BEQ */ compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BEQ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 4); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + vm_base::gen_sync(tu, PRE_SYNC,4); + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 4); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,4); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 5: BNE */ compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BNE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 5); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + vm_base::gen_sync(tu, PRE_SYNC,5); + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 5); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,5); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 6: BLT */ compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 6); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + vm_base::gen_sync(tu, PRE_SYNC,6); + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 6); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,6); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 7: BGE */ compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BGE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 7); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + vm_base::gen_sync(tu, PRE_SYNC,7); + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_SGE, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_SGE,tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 7); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,7); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 8: BLTU */ compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 8); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + vm_base::gen_sync(tu, PRE_SYNC,8); + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 8); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,8); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 9: BGEU */ compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BGEU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 9); - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + vm_base::gen_sync(tu, PRE_SYNC,9); + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_UGE, - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(4, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_SGE,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); + } + else{ + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + tu.close_scope(); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 9); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,9); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /* instruction 10: LB */ compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 10); + vm_base::gen_sync(tu, PRE_SYNC,10); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - false), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 8),8,false),8); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 10); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,10); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 11: LH */ compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 11); + vm_base::gen_sync(tu, PRE_SYNC,11); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - false), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 16),16,false),16); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 11); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,11); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 12: LW */ compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 12); + vm_base::gen_sync(tu, PRE_SYNC,12); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,false),32); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 12); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,12); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 13: LBU */ compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LBU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 13); + vm_base::gen_sync(tu, PRE_SYNC,13); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 8), - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 8),8,true),8); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 13); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,13); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 14: LHU */ compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 14); + vm_base::gen_sync(tu, PRE_SYNC,14); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - if(rd != 0){ - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 16), - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 16),16,true),16); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 14); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,14); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 15: SB */ compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 15); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + vm_base::gen_sync(tu, PRE_SYNC,15); + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 8)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),8,false)); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 15); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,15); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 16: SH */ compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 16); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + vm_base::gen_sync(tu, PRE_SYNC,16); + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 16)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),16,false)); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 16); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,16); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 17: SW */ compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 17); - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + vm_base::gen_sync(tu, PRE_SYNC,17); + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); + if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),32,false)); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 17); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,17); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 18: ADDI */ compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 18); + vm_base::gen_sync(tu, PRE_SYNC,18); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 18); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,18); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 19: SLTI */ compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLTI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 19); + vm_base::gen_sync(tu, PRE_SYNC,19); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant((int16_t)sext<12>(imm),16))), tu.constant( 1,32),tu.constant( 0,32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 19); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,19); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 20: SLTIU */ compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLTIU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 20); + vm_base::gen_sync(tu, PRE_SYNC,20); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - int32_t full_imm_val = imm; - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.load(rs1 + traits::X0, 0), - tu.constant(full_imm_val, 32U)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))), tu.constant( 1,32),tu.constant( 0,32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 20); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,20); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 21: XORI */ compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("XORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 21); + vm_base::gen_sync(tu, PRE_SYNC,21); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_xor(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 21); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,21); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 22: ORI */ compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ORI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 22); + vm_base::gen_sync(tu, PRE_SYNC,22); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_or(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 22); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,22); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 23: ANDI */ compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 23); + vm_base::gen_sync(tu, PRE_SYNC,23); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_and(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 23); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,23); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 24: SLLI */ compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 24); + vm_base::gen_sync(tu, PRE_SYNC,24); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1218,32 +1227,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),tu.constant(shamt,8))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 24); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,24); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 25: SRLI */ compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 25); + vm_base::gen_sync(tu, PRE_SYNC,25); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1251,32 +1260,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.lshr(tu.load(rs1+ traits::X0, 0),tu.constant(shamt,8))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 25); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,25); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 26: SRAI */ compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 26); + vm_base::gen_sync(tu, PRE_SYNC,26); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1284,32 +1293,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(shamt > 31){ - this->gen_raise_trap(tu, 0, 0); - } else { - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rd + traits::X0); - } + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant(shamt,8))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 26); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,26); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 27: ADD */ compile_ret_t __add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 27); + vm_base::gen_sync(tu, PRE_SYNC,27); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1317,28 +1326,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.add( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 27); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,27); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 28: SUB */ compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 28); + vm_base::gen_sync(tu, PRE_SYNC,28); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1346,28 +1359,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.sub( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.sub(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 28); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,28); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 29: SLL */ compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 29); + vm_base::gen_sync(tu, PRE_SYNC,29); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1375,32 +1392,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 29); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,29); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 30: SLT */ compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLT_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 30); + vm_base::gen_sync(tu, PRE_SYNC,30); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1408,36 +1425,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_SLT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true)), tu.constant( 1,32),tu.constant( 0,32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 30); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,30); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 31: SLTU */ compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLTU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 31); + vm_base::gen_sync(tu, PRE_SYNC,31); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1445,38 +1458,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.choose( - tu.icmp( - ICmpInst::ICMP_ULT, - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, - true)), - tu.constant(1, 32U), - tu.constant(0, 32U)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0)), tu.constant( 1,32),tu.constant( 0,32))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 31); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,31); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 32: XOR */ compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 32); + vm_base::gen_sync(tu, PRE_SYNC,32); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1484,28 +1491,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_xor( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_xor(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 32); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,32); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 33: SRL */ compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 33); + vm_base::gen_sync(tu, PRE_SYNC,33); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1513,32 +1524,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.lshr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.lshr(tu.load(rs1+ traits::X0, 0),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 33); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,33); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 34: SRA */ compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 34); + vm_base::gen_sync(tu, PRE_SYNC,34); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1546,32 +1557,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.ashr( - tu.load(rs1 + traits::X0, 0), - tu.l_and( - tu.load(rs2 + traits::X0, 0), - tu.sub( - tu.constant(32, 32U), - tu.constant(1, 32U)))), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 34); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,34); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 35: OR */ compile_ret_t __or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 35); + vm_base::gen_sync(tu, PRE_SYNC,35); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1579,28 +1590,32 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_or( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_or(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 35); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,35); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 36: AND */ compile_ret_t __and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 36); + vm_base::gen_sync(tu, PRE_SYNC,36); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1608,220 +1623,137 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.l_and( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.bitwise_and(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 36); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,36); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } /* instruction 37: FENCE */ compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("FENCE_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 37); + vm_base::gen_sync(tu, PRE_SYNC,37); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t succ = ((bit_sub<20,4>(instr))); uint8_t pred = ((bit_sub<24,4>(instr))); + uint8_t fm = ((bit_sub<28,4>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence"); + auto mnemonic = fmt::format( + "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), + fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(0, 64U), - tu.trunc(tu.l_or( - tu.shl( - tu.constant(pred, 32U), - tu.constant(4, 32U)), - tu.constant(succ, 32U)), 32)); + tu.write_mem(traits::MEM, static_cast(traits:: fence), tu.constant(pred<< 4|succ,8)); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 37); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,37); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 38: FENCE_I */ - compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("FENCE_I_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 38); - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "fence_i"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(1, 64U), - tu.trunc(tu.constant(imm, 32U), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 38); - gen_trap_check(tu); - return std::make_tuple(FLUSH); - } - - /* instruction 39: ECALL */ + /* instruction 38: ECALL */ compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ECALL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 39); + vm_base::gen_sync(tu, PRE_SYNC,38); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ecall"); + this->core.disass_output(pc.val, "ecall"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - this->gen_raise_trap(tu, 0, 11); + this->gen_raise_trap(tu, 0, 11); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 39); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,38); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 40: EBREAK */ + /* instruction 39: EBREAK */ compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 40); + vm_base::gen_sync(tu, PRE_SYNC,39); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ebreak"); + this->core.disass_output(pc.val, "ebreak"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); + this->gen_raise_trap(tu, 0, 3); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 40); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,39); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 41: URET */ - compile_ret_t __uret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("URET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 41); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "uret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 0); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 41); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 42: SRET */ - compile_ret_t __sret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 42); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sret"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - this->gen_leave_trap(tu, 1); - tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 42); - gen_trap_check(tu); - return std::make_tuple(BRANCH); - } - - /* instruction 43: MRET */ + /* instruction 40: MRET */ compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MRET_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 43); + vm_base::gen_sync(tu, PRE_SYNC,40); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "mret"); + this->core.disass_output(pc.val, "mret"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); this->gen_leave_trap(tu, 3); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 43); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,40); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 44: WFI */ + /* instruction 41: WFI */ compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("WFI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 44); + vm_base::gen_sync(tu, PRE_SYNC,41); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "wfi"); + this->core.disass_output(pc.val, "wfi"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); this->gen_wait(tu, 1); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 44); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,41); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 45: SFENCE.VMA */ - compile_ret_t __sfence_vma(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("SFENCE_VMA_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 45); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "sfence.vma"); - } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+4; - tu.open_scope(); - tu.write_mem( - traits::FENCE, - tu.constant(2, 64U), - tu.trunc(tu.constant(rs1, 32U), 32)); - tu.write_mem( - traits::FENCE, - tu.constant(3, 64U), - tu.trunc(tu.constant(rs2, 32U), 32)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 45); - gen_trap_check(tu); - return std::make_tuple(CONT); - } - - /* instruction 46: CSRRW */ + /* instruction 42: CSRRW */ compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 46); + vm_base::gen_sync(tu, PRE_SYNC,42); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1829,37 +1761,37 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto rs_val_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - auto csr_val_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); - tu.store(csr_val_val, rd + traits::X0); - } else { - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(rs_val_val, 32)); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); + if(rd!= 0){ auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + tu.write_mem(traits::MEM, csr, xrs1); + tu.store(rd + traits::X0,xrd); + } + else{ + tu.write_mem(traits::MEM, csr, xrs1); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 46); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,42); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 47: CSRRS */ + /* instruction 43: CSRRS */ compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRS_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 47); + vm_base::gen_sync(tu, PRE_SYNC,43); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1867,36 +1799,37 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - xrd_val, - xrs1_val), 32)); + else{ + auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); + if(rs1!= 0) { + tu.write_mem(traits::MEM, csr, tu.bitwise_or(xrd,xrs1)); + } + if(rd!= 0) { + tu.store(rd + traits::X0,xrd); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 47); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,43); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 48: CSRRC */ + /* instruction 44: CSRRC */ compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRC_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 48); + vm_base::gen_sync(tu, PRE_SYNC,44); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1904,36 +1837,37 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto xrd_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - auto xrs1_val = tu.assignment(tu.load(rs1 + traits::X0, 0), 32); - if(rd != 0){ - tu.store(xrd_val, rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); } - if(rs1 != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - xrd_val, - tu.l_not(xrs1_val)), 32)); + else{ + auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); + if(rs1!= 0) { + tu.write_mem(traits::MEM, csr, tu.bitwise_and(xrd,tu.logical_neg(xrs1))); + } + if(rd!= 0) { + tu.store(rd + traits::X0,xrd); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 48); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,44); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 49: CSRRWI */ + /* instruction 45: CSRRWI */ compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRWI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 49); + vm_base::gen_sync(tu, PRE_SYNC,45); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1941,33 +1875,34 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu.store(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + tu.write_mem(traits::MEM, csr, tu.constant((uint32_t)zimm,32)); + if(rd!= 0) { + tu.store(rd + traits::X0,xrd); + } } - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.ext( - tu.constant(zimm, 32U), - 32, - true), 32)); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 49); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,45); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 50: CSRRSI */ + /* instruction 46: CSRRSI */ compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRSI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 50); + vm_base::gen_sync(tu, PRE_SYNC,46); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1975,38 +1910,36 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_or( - res_val, - tu.ext( - tu.constant(zimm, 32U), - 32, - true)), 32)); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); } - if(rd != 0){ - tu.store(res_val, rd + traits::X0); + else{ + auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + if(zimm!= 0) { + tu.write_mem(traits::MEM, csr, tu.bitwise_or(xrd,tu.constant((uint32_t)zimm,32))); + } + if(rd!= 0) { + tu.store(rd + traits::X0,xrd); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 50); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,46); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 51: CSRRCI */ + /* instruction 47: CSRRCI */ compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRCI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 51); + vm_base::gen_sync(tu, PRE_SYNC,47); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2014,38 +1947,62 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - auto res_val = tu.assignment(tu.read_mem(traits::CSR, tu.constant(csr, 16U), 32), 32); - if(rd != 0){ - tu.store(res_val, rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); } - if(zimm != 0){ - tu.write_mem( - traits::CSR, - tu.constant(csr, 16U), - tu.trunc(tu.l_and( - res_val, - tu.l_not(tu.ext( - tu.constant(zimm, 32U), - 32, - true))), 32)); + else{ + auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + if(zimm!= 0) { + tu.write_mem(traits::MEM, csr, tu.bitwise_and(xrd,tu.constant(~ ((uint32_t)zimm),32))); + } + if(rd!= 0) { + tu.store(rd + traits::X0,xrd); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 51); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,47); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 52: MUL */ + /* instruction 48: FENCE_I */ + compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("FENCE_I_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,48); + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), + fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; + tu.open_scope(); + tu.write_mem(traits::MEM, static_cast(traits:: fencei), tu.constant(imm,16)); + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,48); + gen_trap_check(tu); + return returnValue; + } + + /* instruction 49: MUL */ compile_ret_t __mul(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MUL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 52); + vm_base::gen_sync(tu, PRE_SYNC,49); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2053,38 +2010,33 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - res_val, - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto res = tu.assignment(tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false)),64); + if(rd!=0) { + tu.store(rd + traits::X0,tu.ext(res,32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 52); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,49); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 53: MULH */ + /* instruction 50: MULH */ compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MULH_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 53); + vm_base::gen_sync(tu, PRE_SYNC,50); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2092,40 +2044,33 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - false)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto res = tu.assignment(tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false)),64); + if(rd!=0) { + tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 53); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,50); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 54: MULHSU */ + /* instruction 51: MULHSU */ compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MULHSU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 54); + vm_base::gen_sync(tu, PRE_SYNC,51); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2133,40 +2078,33 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto res = tu.assignment(tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.load(rs2+ traits::X0, 0),64,true)),64); + if(rd!=0) { + tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 54); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,51); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 55: MULHU */ + /* instruction 52: MULHU */ compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MULHU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 55); + vm_base::gen_sync(tu, PRE_SYNC,52); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2174,40 +2112,33 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - auto res_val = tu.assignment(tu.mul( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 64, - true), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 64, - true)), 64); - tu.store(tu.ext( - tu.lshr( - res_val, - tu.constant(32, 32U)), - 32, - true), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),64,true),tu.ext(tu.load(rs2+ traits::X0, 0),64,true)),64); + if(rd!=0) { + tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 55); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,52); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 56: DIV */ + /* instruction 53: DIV */ compile_ret_t __div(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("DIV_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 56); + vm_base::gen_sync(tu, PRE_SYNC,53); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2215,55 +2146,42 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - uint32_t M1_val = - 1; - uint8_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.constant(MMIN_val, 32U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs2 + traits::X0, 0), - tu.constant(M1_val, 32U)))); - tu.store(tu.constant(MMIN_val, 32U), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.sdiv( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 32U)), rd + traits::X0); - tu.close_scope(); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto dividend = tu.assignment(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),32); + auto divisor = tu.assignment(tu.ext(tu.load(rs2+ traits::X0, 0),32,false),32); + if(rd!= 0){ tu.open_if(tu.icmp(ICmpInst::ICMP_NE,divisor,tu.constant( 0,32))); + auto MMIN = tu.assignment(tu.constant(((uint32_t)1)<<(static_cast(traits:: XLEN)-1),32),32); + tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,divisor,tu.constant(- 1,32)))); + tu.store(rd + traits::X0,MMIN); + tu.open_else(); + tu.store(rd + traits::X0,tu.sdiv(dividend,divisor)); + tu.close_scope(); + tu.open_else(); + tu.store(rd + traits::X0,tu.constant((int32_t)- 1,32)); + tu.close_scope(); + } } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 56); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,53); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 57: DIVU */ + /* instruction 54: DIVU */ compile_ret_t __divu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("DIVU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 57); + vm_base::gen_sync(tu, PRE_SYNC,54); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2271,35 +2189,38 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - tu.store(tu.udiv( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.neg(tu.constant(1, 32U)), rd + traits::X0); - tu.close_scope(); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,32))); + if(rd!=0) { + tu.store(rd + traits::X0,tu.sdiv(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } + tu.open_else(); + if(rd!=0) { + tu.store(rd + traits::X0,tu.constant((int32_t)- 1,32)); + } + tu.close_scope(); } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 57); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,54); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 58: REM */ + /* instruction 55: REM */ compile_ret_t __rem(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("REM_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 58); + vm_base::gen_sync(tu, PRE_SYNC,55); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2307,55 +2228,45 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - uint32_t M1_val = - 1; - uint32_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - tu( " if({}) {{", tu.b_and( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + traits::X0, 0), - tu.constant(MMIN_val, 32U)), - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs2 + traits::X0, 0), - tu.constant(M1_val, 32U)))); - tu.store(tu.constant(0, 32U), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.srem( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.ext( - tu.load(rs2 + traits::X0, 0), - 32, false)), rd + traits::X0); - tu.close_scope(); - tu(" }} else {{"); - tu.store(tu.load(rs1 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,32))); + auto MMIN = tu.assignment(tu.constant( 1<<(static_cast(traits:: XLEN)-1),32),32); + tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,tu.ext(tu.load(rs2+ traits::X0, 0),32,false),tu.constant(- 1,32)))); + if(rd!=0) { + tu.store(rd + traits::X0,tu.constant( 0,32)); + } + tu.open_else(); + if(rd!=0) { + tu.store(rd + traits::X0,tu.srem(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false))); + } + tu.close_scope(); + tu.open_else(); + if(rd!=0) { + tu.store(rd + traits::X0,tu.load(rs1+ traits::X0, 0)); + } + tu.close_scope(); } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 58); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,55); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 59: REMU */ + /* instruction 56: REMU */ compile_ret_t __remu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("REMU_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 59); + vm_base::gen_sync(tu, PRE_SYNC,56); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2363,807 +2274,851 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; tu.open_scope(); - if(rd != 0){ - tu( " if({}) {{", tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs2 + traits::X0, 0), - tu.constant(0, 32U))); - tu.store(tu.urem( - tu.load(rs1 + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); - tu(" }} else {{"); - tu.store(tu.load(rs1 + traits::X0, 0), rd + traits::X0); - tu.close_scope(); + if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,32))); + if(rd!=0) { + tu.store(rd + traits::X0,tu.srem(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } + tu.open_else(); + if(rd!=0) { + tu.store(rd + traits::X0,tu.load(rs1+ traits::X0, 0)); + } + tu.close_scope(); } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 59); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,56); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 60: C.ADDI4SPN */ - compile_ret_t __c_addi4spn(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI4SPN_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 60); + /* instruction 57: CADDI4SPN */ + compile_ret_t __caddi4spn(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CADDI4SPN_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,57); uint8_t rd = ((bit_sub<2,3>(instr))); uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); + if(imm) { + tu.store(rd+ 8 + traits::X0,tu.add(tu.load(2+ traits::X0, 0),tu.constant(imm,8))); + } + else{ + this->gen_raise_trap(tu, 0, 2); } - tu.store(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(imm, 32U)), rd + 8 + traits::X0); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 60); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,57); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 61: C.LW */ - compile_ret_t __c_lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 61); + /* instruction 58: CLW */ + compile_ret_t __clw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CLW_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,58); uint8_t rd = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), + fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + 8 + traits::X0); + auto load_address = tu.assignment(tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8)),32); + tu.store(rd+ 8 + traits::X0,tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,false)); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 61); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,58); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 62: C.SW */ - compile_ret_t __c_sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SW_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 62); + /* instruction 59: CSW */ + compile_ret_t __csw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSW_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,59); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), + fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + 8 + traits::X0, 0), 32)); + auto load_address = tu.assignment(tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8)),32); + tu.write_mem(traits::MEM, load_address, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,false)); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 62); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,59); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 63: C.ADDI */ - compile_ret_t __c_addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 63); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + /* instruction 60: CADDI */ + compile_ret_t __caddi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CADDI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,60); + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(rs1 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rs1 + traits::X0); + if(rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rs1!= 0) { + tu.store(rs1 + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))); + } + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 63); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,60); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 64: C.NOP */ - compile_ret_t __c_nop(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_NOP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 64); + /* instruction 61: CNOP */ + compile_ret_t __cnop(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CNOP_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,61); + uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.nop"); + this->core.disass_output(pc.val, "cnop"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); tu.close_scope(); - /* TODO: describe operations for C.NOP ! */ - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 64); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,61); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 65: C.JAL */ - compile_ret_t __c_jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JAL_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 65); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + /* instruction 62: CJAL */ + compile_ret_t __cjal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CJAL_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,62); + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.add( - cur_pc_val, - tu.constant(2, 32U)), 1 + traits::X0); - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 65); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,62); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 66: C.LI */ - compile_ret_t __c_li(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 66); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + /* instruction 63: CLI */ + compile_ret_t __cli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CLI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,63); + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.constant((int8_t)sext<6>(imm),8)); + } } - tu.store(tu.constant(imm, 32U), rd + traits::X0); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 66); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,63); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 67: C.LUI */ - compile_ret_t __c_lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LUI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 67); - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); + /* instruction 64: CLUI */ + compile_ret_t __clui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CLUI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,64); + uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - if(rd == 0){ - this->gen_raise_trap(tu, 0, 2); + if(imm== 0||rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); } - if(imm == 0){ - this->gen_raise_trap(tu, 0, 2); + if(rd!= 0) { + tu.store(rd + traits::X0,tu.constant((int32_t)sext<18>(imm),32)); } - tu.store(tu.constant(imm, 32U), rd + traits::X0); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 67); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,64); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 68: C.ADDI16SP */ - compile_ret_t __c_addi16sp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADDI16SP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 68); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); + /* instruction 65: CADDI16SP */ + compile_ret_t __caddi16sp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CADDI16SP_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,65); + uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), + fmt::arg("nzimm", nzimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.add( - tu.ext( - tu.load(2 + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), 2 + traits::X0); + if(nzimm) { + tu.store(2 + traits::X0,tu.add(tu.load(2+ traits::X0, 0),tu.constant((int16_t)sext<10>(nzimm),16))); + } + else{ + this->gen_raise_trap(tu, 0, 2); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 68); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,65); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 69: C.SRLI */ - compile_ret_t __c_srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 69); + /* instruction 66: __reserved_clui */ + compile_ret_t ____reserved_clui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("__reserved_clui_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,66); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "__reserved_clui"); + } + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; + tu.open_scope(); + this->gen_raise_trap(tu, 0, 2); + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,66); + gen_trap_check(tu); + return returnValue; + } + + /* instruction 67: CSRLI */ + compile_ret_t __csrli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSRLI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,67); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.lshr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 32U)), rs1_idx_val + traits::X0); + tu.store(rs1+ 8 + traits::X0,tu.lshr(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(shamt,8))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 69); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,67); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 70: C.SRAI */ - compile_ret_t __c_srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SRAI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 70); + /* instruction 68: CSRAI */ + compile_ret_t __csrai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSRAI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,68); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.ashr( - tu.load(rs1_idx_val + traits::X0, 0), - tu.constant(shamt, 32U)), rs1_idx_val + traits::X0); + if(shamt){ tu.store(rs1+ 8 + traits::X0,tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant(shamt,8))); + } + else{ + if(static_cast(traits:: XLEN)== 128){ tu.store(rs1+ 8 + traits::X0,tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant( 64,32))); + } + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 70); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,68); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 71: C.ANDI */ - compile_ret_t __c_andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ANDI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 71); - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + /* instruction 69: CANDI */ + compile_ret_t __candi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CANDI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,69); + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rs1_idx_val = rs1 + 8; - tu.store(tu.l_and( - tu.ext( - tu.load(rs1_idx_val + traits::X0, 0), - 32, false), - tu.constant(imm, 32U)), rs1_idx_val + traits::X0); + tu.store(rs1+ 8 + traits::X0,tu.bitwise_and(tu.load(rs1+ 8+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 71); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,69); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 72: C.SUB */ - compile_ret_t __c_sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SUB_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 72); + /* instruction 70: CSUB */ + compile_ret_t __csub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSUB_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,70); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.sub( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); + tu.store(rd+ 8 + traits::X0,tu.sub(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 72); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,70); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 73: C.XOR */ - compile_ret_t __c_xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_XOR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 73); + /* instruction 71: CXOR */ + compile_ret_t __cxor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CXOR_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,71); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_xor( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); + tu.store(rd+ 8 + traits::X0,tu.bitwise_xor(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 73); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,71); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 74: C.OR */ - compile_ret_t __c_or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_OR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 74); + /* instruction 72: COR */ + compile_ret_t __cor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("COR_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,72); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_or( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); + tu.store(rd+ 8 + traits::X0,tu.bitwise_or(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 74); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,72); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 75: C.AND */ - compile_ret_t __c_and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_AND_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 75); + /* instruction 73: CAND */ + compile_ret_t __cand(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CAND_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,73); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - uint8_t rd_idx_val = rd + 8; - tu.store(tu.l_and( - tu.load(rd_idx_val + traits::X0, 0), - tu.load(rs2 + 8 + traits::X0, 0)), rd_idx_val + traits::X0); + tu.store(rd+ 8 + traits::X0,tu.bitwise_and(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 75); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,73); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 76: C.J */ - compile_ret_t __c_j(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_J_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 76); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + /* instruction 74: CJ */ + compile_ret_t __cj(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CJ_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,74); + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 76); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,74); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 77: C.BEQZ */ - compile_ret_t __c_beqz(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BEQZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 77); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + /* instruction 75: CBEQZ */ + compile_ret_t __cbeqz(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CBEQZ_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,75); + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_EQ, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 32U)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(2, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 77); + tu.close_scope(); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,75); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 78: C.BNEZ */ - compile_ret_t __c_bnez(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_BNEZ_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 78); - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + /* instruction 76: CBNEZ */ + compile_ret_t __cbnez(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CBNEZ_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,76); + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.choose( - tu.icmp( - ICmpInst::ICMP_NE, - tu.load(rs1 + 8 + traits::X0, 0), - tu.constant(0, 32U)), - tu.add( - tu.ext( - cur_pc_val, - 32, false), - tu.constant(imm, 32U)), - tu.add( - cur_pc_val, - tu.constant(2, 32U))), 32); - tu.store(PC_val_v, traits::NEXT_PC); - auto is_cont_v = tu.choose( - tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32U, true), tu.constant(pc.val, 32U)), - tu.constant(0U, 32), tu.constant(1U, 32)); + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); + auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 78); + tu.close_scope(); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,76); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 79: C.SLLI */ - compile_ret_t __c_slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SLLI_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 79); - uint8_t shamt = ((bit_sub<2,5>(instr))); + /* instruction 77: CSLLI */ + compile_ret_t __cslli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSLLI_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,77); + uint8_t nzuimm = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - if(rs1 == 0){ - this->gen_raise_trap(tu, 0, 2); + if(rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rs1!= 0) { + tu.store(rs1 + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),tu.constant(nzuimm,8))); + } } - tu.store(tu.shl( - tu.load(rs1 + traits::X0, 0), - tu.constant(shamt, 32U)), rs1 + traits::X0); tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 79); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,77); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 80: C.LWSP */ - compile_ret_t __c_lwsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_LWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 80); + /* instruction 78: CLWSP */ + compile_ret_t __clwsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CLWSP_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,78); uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.store(tu.ext( - tu.read_mem(traits::MEM, offs_val, 32), - 32, - false), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)||rd== 0) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto res = tu.assignment(tu.read_mem(traits::MEM, tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8)), 32),32); + tu.store(rd + traits::X0,tu.ext(res,32,false)); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 80); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,78); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 81: C.MV */ - compile_ret_t __c_mv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_MV_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 81); + /* instruction 79: CMV */ + compile_ret_t __cmv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CMV_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,79); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.load(rs2 + traits::X0, 0), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.load(rs2+ traits::X0, 0)); + } + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 81); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,79); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 82: C.JR */ - compile_ret_t __c_jr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 82); + /* instruction 80: CJR */ + compile_ret_t __cjr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CJR_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,80); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 32); - tu.store(PC_val_v, traits::NEXT_PC); + if(rs1&&rs1(traits:: RFS)) { + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0),tu.constant(~ 0x1,8)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } + else{ + this->gen_raise_trap(tu, 0, 2); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 82); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,80); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 83: C.ADD */ - compile_ret_t __c_add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_ADD_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 83); + /* instruction 81: __reserved_cmv */ + compile_ret_t ____reserved_cmv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("__reserved_cmv_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,81); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "__reserved_cmv"); + } + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; + tu.open_scope(); + this->gen_raise_trap(tu, 0, 2); + tu.close_scope(); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,81); + gen_trap_check(tu); + return returnValue; + } + + /* instruction 82: CADD */ + compile_ret_t __cadd(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CADD_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,82); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.add( - tu.load(rd + traits::X0, 0), - tu.load(rs2 + traits::X0, 0)), rd + traits::X0); + if(rd>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + if(rd!= 0) { + tu.store(rd + traits::X0,tu.add(tu.load(rd+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + } + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 83); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,82); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 84: C.JALR */ - compile_ret_t __c_jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_JALR_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 84); + /* instruction 83: CJALR */ + compile_ret_t __cjalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CJALR_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,83); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - tu.store(tu.add( - cur_pc_val, - tu.constant(2, 32U)), 1 + traits::X0); - auto PC_val_v = tu.assignment("PC_val", tu.load(rs1 + traits::X0, 0), 32); - tu.store(PC_val_v, traits::NEXT_PC); + if(rs1>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto new_pc = tu.assignment(tu.load(rs1+ traits::X0, 0),32); + tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); + tu.store(traits::NEXT_PC, PC_val_v); + auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); + tu.store(traits::LAST_BRANCH, noJump); + } tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 84); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,83); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 85: C.EBREAK */ - compile_ret_t __c_ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_EBREAK_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 85); + /* instruction 84: CEBREAK */ + compile_ret_t __cebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CEBREAK_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,84); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c.ebreak"); + this->core.disass_output(pc.val, "cebreak"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - this->gen_raise_trap(tu, 0, 3); + this->gen_raise_trap(tu, 0, 3); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 85); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,84); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } - /* instruction 86: C.SWSP */ - compile_ret_t __c_swsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("C_SWSP_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 86); + /* instruction 85: CSWSP */ + compile_ret_t __cswsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("CSWSP_{:#010x}:", pc.val); + vm_base::gen_sync(tu, PRE_SYNC,85); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - auto offs_val = tu.assignment(tu.add( - tu.load(2 + traits::X0, 0), - tu.constant(uimm, 32U)), 32); - tu.write_mem( - traits::MEM, - offs_val, - tu.trunc(tu.load(rs2 + traits::X0, 0), 32)); + if(rs2>=static_cast(traits:: RFS)) { + this->gen_raise_trap(tu, 0, 2); + } + else{ + auto offs = tu.assignment(tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8)),32); + tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ traits::X0, 0),32,true)); + } tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); - vm_base::gen_sync(tu, POST_SYNC, 86); + gen_set_pc(tu, pc, traits::NEXT_PC); + auto returnValue = std::make_tuple(CONT); + vm_base::gen_sync(tu, POST_SYNC,85); gen_trap_check(tu); - return std::make_tuple(CONT); + return returnValue; } - /* instruction 87: DII */ + /* instruction 86: DII */ compile_ret_t __dii(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("DII_{:#010x}:", pc.val); - vm_base::gen_sync(tu, PRE_SYNC, 87); + vm_base::gen_sync(tu, PRE_SYNC,86); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "dii"); + this->core.disass_output(pc.val, "dii"); } - auto cur_pc_val = tu.constant(pc.val, arch::traits::reg_bit_widths[traits::PC]); - pc=pc+2; + auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); + pc=pc+4; tu.open_scope(); - this->gen_raise_trap(tu, 0, 2); + this->gen_raise_trap(tu, 0, 2); tu.close_scope(); - vm_base::gen_sync(tu, POST_SYNC, 87); + auto returnValue = std::make_tuple(BRANCH); + vm_base::gen_sync(tu, POST_SYNC,86); gen_trap_check(tu); - return std::make_tuple(BRANCH); + return returnValue; } /**************************************************************************** @@ -3205,7 +3160,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; + const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); auto *const data = (uint8_t *)&insn; paddr = this->core.v2p(pc); @@ -3232,11 +3187,13 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(), 32)); } template void vm_impl::gen_leave_trap(tu_builder& tu, unsigned lvl) { tu("leave_trap(core_ptr, {});", lvl); - tu.store(tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN),traits::NEXT_PC); + tu.store(traits::NEXT_PC, tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN)); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(), 32)); } template void vm_impl::gen_wait(tu_builder& tu, unsigned type) { @@ -3244,7 +3201,8 @@ template void vm_impl::gen_wait(tu_builder& tu, unsigned t template void vm_impl::gen_trap_behavior(tu_builder& tu) { tu("trap_entry:"); - tu("enter_trap(core_ptr, *trap_state, *pc);"); + tu("enter_trap(core_ptr, *trap_state, *pc, 0);"); + tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(),32)); tu("return *next_pc;"); } From ce5b2e60b96c22f0418d542cfdf9cc764170a1a4 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Mon, 22 May 2023 17:00:36 +0200 Subject: [PATCH 098/184] amends template to fix branching instructions --- gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl index b37586c..bd0d7fa 100644 --- a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl @@ -208,8 +208,10 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope();<%instr.behavior.eachLine{%> ${it}<%}%> + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,${idx}); gen_trap_check(tu); return returnValue; From ee6218279e1d385f3d6a70a17176185d2e921ff3 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 25 May 2023 12:52:30 +0200 Subject: [PATCH 099/184] adapts to latest code gen changes --- src/iss/arch/tgc_c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index d1fdfed..53776c0 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -53,7 +53,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; - enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, PGMASK=0b111111111111, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; + enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; constexpr static unsigned FP_REGS_SIZE = 0; From a123beb3011f388db3ba9e56eb746af02c89a8f7 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 27 May 2023 10:20:49 +0200 Subject: [PATCH 100/184] fixes duplicate variable declaration and templates --- gen_input/TGC_C.core_desc | 10 +- gen_input/templates/CORENAME.cpp.gtl | 4 +- gen_input/templates/CORENAME.h.gtl | 10 +- gen_input/templates/CORENAME_instr.yaml.gtl | 5 +- gen_input/templates/interp/CORENAME.cpp.gtl | 22 +- ...m-vm_CORENAME.cpp.gtl => CORENAME.cpp.gtl} | 18 +- .../templates/tcc/CORENAME_cyles.txt.gtl | 9 - gen_input/templates/tcc/incl-CORENAME.h.gtl | 223 ---------- gen_input/templates/tcc/src-CORENAME.cpp.gtl | 107 ----- src/iss/arch/riscv_hart_m_p.h | 96 ++--- src/iss/arch/riscv_hart_msu_vp.h | 83 ++-- src/iss/arch/riscv_hart_mu_p.h | 92 ++--- src/iss/arch/tgc_c.cpp | 4 +- src/iss/arch/tgc_c.h | 10 +- src/main.cpp | 2 +- src/vm/interp/vm_tgc_c.cpp | 104 ++--- src/vm/tcc/vm_tgc_c.cpp | 389 +++++++++--------- 17 files changed, 380 insertions(+), 808 deletions(-) rename gen_input/templates/tcc/{vm-vm_CORENAME.cpp.gtl => CORENAME.cpp.gtl} (96%) delete mode 100644 gen_input/templates/tcc/CORENAME_cyles.txt.gtl delete mode 100644 gen_input/templates/tcc/incl-CORENAME.h.gtl delete mode 100644 gen_input/templates/tcc/src-CORENAME.cpp.gtl diff --git a/gen_input/TGC_C.core_desc b/gen_input/TGC_C.core_desc index 72f549d..8377d41 100644 --- a/gen_input/TGC_C.core_desc +++ b/gen_input/TGC_C.core_desc @@ -1,13 +1,13 @@ -import "RV32I.core_desc" -import "RVM.core_desc" -import "RVC.core_desc" +import "ISA/RV32I.core_desc" +import "ISA/RVM.core_desc" +import "ISA/RVC.core_desc" Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { architectural_state { XLEN=32; // definitions for the architecture wrapper // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000001000100000100; - unsigned MARCHID_VAL = 0x80000003; + unsigned int MISA_VAL = 0b01000000000000000001000100000100; + unsigned int MARCHID_VAL = 0x80000003; } } diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl index 3a06133..b7468c7 100644 --- a/gen_input/templates/CORENAME.cpp.gtl +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -62,8 +62,8 @@ void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { reg.PC=address; reg.NEXT_PC=reg.PC; reg.PRIV=0x3; - trap_state=0; - icount=0; + reg.trap_state=0; + reg.icount=0; } uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 563631f..9c8082e 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -136,7 +136,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { uint8_t* get_regs_base_ptr() override; - inline uint64_t get_icount() { return icount; } + inline uint64_t get_icount() { return reg.icount; } inline bool should_stop() { return interrupt_sim; } @@ -154,7 +154,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } - inline uint32_t get_last_branch() { return last_branch; } + inline uint32_t get_last_branch() { return reg.last_branch; } #pragma pack(push, 1) @@ -170,12 +170,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { uint32_t last_branch = 0; } reg; #pragma pack(pop) - uint32_t trap_state = 0, pending_trap = 0; - uint64_t icount = 0; - uint64_t cycle = 0; - uint64_t instret = 0; - uint32_t instruction = 0; - uint32_t last_branch = 0; std::array addr_mode; uint64_t interrupt_sim=0; diff --git a/gen_input/templates/CORENAME_instr.yaml.gtl b/gen_input/templates/CORENAME_instr.yaml.gtl index 9b29705..542fed6 100644 --- a/gen_input/templates/CORENAME_instr.yaml.gtl +++ b/gen_input/templates/CORENAME_instr.yaml.gtl @@ -13,5 +13,8 @@ ${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %> - ${it.instruction.name}: encoding: ${it.encoding} mask: ${it.mask}<%if(it.attributes.size) {%> - attributes: ${it.attributes}<%}}}%> + attributes: ${it.attributes}<%}%> + size: ${it.length} + branch: ${it.modifiesPC} + delay: ${it.isConditional?"[1,1]":"1"}<%}}%> diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 7b26430..ef645bf 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -121,7 +121,7 @@ protected: inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; - this->core.trap_state = trap_val; + this->core.reg.trap_state = trap_val; this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); } @@ -244,16 +244,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto pc=start; auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - auto& trap_state = this->core.trap_state; - auto& icount = this->core.icount; - auto& cycle = this->core.cycle; - auto& instret = this->core.instret; - auto& instr = this->core.instruction; + auto& trap_state = this->core.reg.trap_state; + auto& icount = this->core.reg.icount; + auto& cycle = this->core.reg.cycle; + auto& instret = this->core.reg.instret; + auto& instr = this->core.reg.instruction; // we fetch at max 4 byte, alignment is 2 auto *const data = reinterpret_cast(&instr); while(!this->core.should_stop() && - !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ + !(is_count_limit_enabled(cond) && icount >= icount_limit)){ if(fetch_ins(pc, data)!=iss::Ok){ this->do_sync(POST_SYNC, std::numeric_limits::max()); pc.val = super::core.enter_trap(std::numeric_limits::max(), pc.val, 0); @@ -262,7 +262,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' auto inst_id = decode_inst_id(instr); // pre execution stuff - this->core.last_branch = 0; + this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> case arch::traits::opcode_e::${instr.name}: { @@ -289,8 +289,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // post execution stuff process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); - // if(!this->core.trap_state) // update trap state if there is a pending interrupt - // this->core.trap_state = this->core.pending_trap; + // if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt + // this->core.reg.trap_state = this->core.reg.pending_trap; // trap check if(trap_state!=0){ super::core.enter_trap(trap_state, pc.val, instr); @@ -301,7 +301,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co cycle++; pc.val=*NEXT_PC; this->core.reg.PC = this->core.reg.NEXT_PC; - this->core.trap_state = this->core.pending_trap; + this->core.reg.trap_state = this->core.reg.pending_trap; } } return pc; diff --git a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl similarity index 96% rename from gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl rename to gen_input/templates/tcc/CORENAME.cpp.gtl index bd0d7fa..9ce0e26 100644 --- a/gen_input/templates/tcc/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -256,20 +256,20 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; + // const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); auto *const data = (uint8_t *)&insn; paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { +// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary +// auto res = this->core.read(paddr, 2, data); +// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); +// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction +// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); +// } +// } else { auto res = this->core.read(paddr, 4, data); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } +// } if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; diff --git a/gen_input/templates/tcc/CORENAME_cyles.txt.gtl b/gen_input/templates/tcc/CORENAME_cyles.txt.gtl deleted file mode 100644 index 3a1ad8e..0000000 --- a/gen_input/templates/tcc/CORENAME_cyles.txt.gtl +++ /dev/null @@ -1,9 +0,0 @@ -{ - "${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","} - { - "name" : "${instr.name}", - "size" : ${instr.length}, - "delay" : ${generator.hasAttribute(instr.instruction, com.minres.coredsl.coreDsl.InstrAttribute.COND)?[1,1]:1} - }<%}%> - ] -} \ No newline at end of file diff --git a/gen_input/templates/tcc/incl-CORENAME.h.gtl b/gen_input/templates/tcc/incl-CORENAME.h.gtl deleted file mode 100644 index 0a5b99f..0000000 --- a/gen_input/templates/tcc/incl-CORENAME.h.gtl +++ /dev/null @@ -1,223 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -<% -import com.minres.coredsl.coreDsl.Register -import com.minres.coredsl.coreDsl.RegisterFile -import com.minres.coredsl.coreDsl.RegisterAlias -def getTypeSize(size){ - if(size > 32) 64 else if(size > 16) 32 else if(size > 8) 16 else 8 -} -def getOriginalName(reg){ - if( reg.original instanceof RegisterFile) { - if( reg.index != null ) { - return reg.original.name+generator.generateHostCode(reg.index) - } else { - return reg.original.name - } - } else if(reg.original instanceof Register){ - return reg.original.name - } -} -def getRegisterNames(){ - def regNames = [] - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{ - regNames+=reg.name.toLowerCase()+it - } - } else if(reg instanceof Register){ - regNames+=reg.name.toLowerCase() - } - } - return regNames -} -def getRegisterAliasNames(){ - def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]} - return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg -> - if( reg instanceof RegisterFile) { - return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() } - } else if(reg instanceof Register){ - regMap[reg.name]?:reg.name.toLowerCase() - } - }.flatten() -} -%> -#ifndef _${coreDef.name.toUpperCase()}_H_ -#define _${coreDef.name.toUpperCase()}_H_ - -#include -#include -#include -#include - -namespace iss { -namespace arch { - -struct ${coreDef.name.toLowerCase()}; - -template <> struct traits<${coreDef.name.toLowerCase()}> { - - constexpr static char const* const core_type = "${coreDef.name}"; - - static constexpr std::array reg_names{ - {"${getRegisterNames().join("\", \"")}"}}; - - static constexpr std::array reg_aliases{ - {"${getRegisterAliasNames().join("\", \"")}"}}; - - enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}}; - - constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0}; - - enum reg_e {<% - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{%> - ${reg.name}${it},<% - } - } else if(reg instanceof Register){ %> - ${reg.name},<% - } - }%> - NUM_REGS, - NEXT_${pc.name}=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - LAST_BRANCH, - ICOUNT<% - allRegs.each { reg -> - if(reg instanceof RegisterAlias){ def aliasname=getOriginalName(reg)%>, - ${reg.name} = ${aliasname}<% - } - }%> - }; - - using reg_t = uint${regDataWidth}_t; - - using addr_t = uint${addrDataWidth}_t; - - using code_word_t = uint${addrDataWidth}_t; //TODO: check removal - - using virt_addr_t = iss::typed_addr_t; - - using phys_addr_t = iss::typed_addr_t; - - static constexpr std::array reg_bit_widths{ - {${regSizes.join(",")}}}; - - static constexpr std::array reg_byte_offsets{ - {${regOffsets.join(",")}}}; - - static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); - - enum sreg_flag_e { FLAGS }; - - enum mem_type_e { ${allSpaces.collect{s -> s.name}.join(', ')} }; -}; - -struct ${coreDef.name.toLowerCase()}: public arch_if { - - using virt_addr_t = typename traits<${coreDef.name.toLowerCase()}>::virt_addr_t; - using phys_addr_t = typename traits<${coreDef.name.toLowerCase()}>::phys_addr_t; - using reg_t = typename traits<${coreDef.name.toLowerCase()}>::reg_t; - using addr_t = typename traits<${coreDef.name.toLowerCase()}>::addr_t; - - ${coreDef.name.toLowerCase()}(); - ~${coreDef.name.toLowerCase()}(); - - void reset(uint64_t address=0) override; - - uint8_t* get_regs_base_ptr() override; - /// deprecated - void get_reg(short idx, std::vector& value) override {} - void set_reg(short idx, const std::vector& value) override {} - /// deprecated - bool get_flag(int flag) override {return false;} - void set_flag(int, bool value) override {}; - /// deprecated - void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; - - inline uint64_t get_icount() { return reg.icount; } - - inline bool should_stop() { return interrupt_sim; } - - inline uint64_t stop_code() { return interrupt_sim; } - - inline phys_addr_t v2p(const iss::addr_t& addr){ - if (addr.space != traits<${coreDef.name.toLowerCase()}>::MEM || addr.type == iss::address_type::PHYSICAL || - addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { - return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask); - } else - return virt2phys(addr); - } - - virtual phys_addr_t virt2phys(const iss::addr_t& addr); - - virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } - - inline uint32_t get_last_branch() { return reg.last_branch; } - -protected: - struct ${coreDef.name}_regs {<% - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{%> - uint${generator.getSize(reg)}_t ${reg.name}${it} = 0;<% - } - } else if(reg instanceof Register){ %> - uint${generator.getSize(reg)}_t ${reg.name} = 0;<% - } - }%> - uint${generator.getSize(pc)}_t NEXT_${pc.name} = 0; - uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; - uint64_t icount = 0; - } reg; - - std::array addr_mode; - - uint64_t interrupt_sim=0; -<% -def fcsr = allRegs.find {it.name=='FCSR'} -if(fcsr != null) {%> - uint${generator.getSize(fcsr)}_t get_fcsr(){return reg.FCSR;} - void set_fcsr(uint${generator.getSize(fcsr)}_t val){reg.FCSR = val;} -<%} else { %> - uint32_t get_fcsr(){return 0;} - void set_fcsr(uint32_t val){} -<%}%> -}; - -} -} -#endif /* _${coreDef.name.toUpperCase()}_H_ */ diff --git a/gen_input/templates/tcc/src-CORENAME.cpp.gtl b/gen_input/templates/tcc/src-CORENAME.cpp.gtl deleted file mode 100644 index 8ed478f..0000000 --- a/gen_input/templates/tcc/src-CORENAME.cpp.gtl +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - <% -import com.minres.coredsl.coreDsl.Register -import com.minres.coredsl.coreDsl.RegisterFile -import com.minres.coredsl.coreDsl.RegisterAlias -def getOriginalName(reg){ - if( reg.original instanceof RegisterFile) { - if( reg.index != null ) { - return reg.original.name+generator.generateHostCode(reg.index) - } else { - return reg.original.name - } - } else if(reg.original instanceof Register){ - return reg.original.name - } -} -def getRegisterNames(){ - def regNames = [] - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{ - regNames+=reg.name.toLowerCase()+it - } - } else if(reg instanceof Register){ - regNames+=reg.name.toLowerCase() - } - } - return regNames -} -def getRegisterAliasNames(){ - def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]} - return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg -> - if( reg instanceof RegisterFile) { - return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() } - } else if(reg instanceof Register){ - regMap[reg.name]?:reg.name.toLowerCase() - } - }.flatten() -} -%> -#include "util/ities.h" -#include -#include -#include -#include -#include - -using namespace iss::arch; - -constexpr std::array iss::arch::traits::reg_names; -constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; - -${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { - reg.icount = 0; -} - -${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default; - -void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { - for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits<${coreDef.name.toLowerCase()}>::reg_t),0)); - reg.PC=address; - reg.NEXT_PC=reg.PC; - reg.trap_state=0; - reg.machine_state=0x3; - reg.icount=0; -} - -uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { - return reinterpret_cast(®); -} - -${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address -} - diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 1462848..1111146 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -280,7 +280,7 @@ public: void disass_output(uint64_t pc, const std::string instr) override { CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", - pc, instr, (reg_t)state.mstatus, this->icount + cycle_offset); + pc, instr, (reg_t)state.mstatus, this->reg.icount + cycle_offset); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } @@ -308,17 +308,17 @@ protected: uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; - uint64_t get_instr_word() override { return arch.instruction; } + uint64_t get_instr_word() override { return arch.reg.instruction; } - uint64_t get_instr_count() override { return arch.icount; } + uint64_t get_instr_count() override { return arch.reg.icount; } - uint64_t get_pendig_traps() override { return arch.trap_state; } + uint64_t get_pendig_traps() override { return arch.reg.trap_state; } - uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } + uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; - bool is_branch_taken() override { return arch.last_branch; }; + bool is_branch_taken() override { return arch.reg.last_branch; }; riscv_hart_m_p &arch; }; @@ -657,12 +657,12 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { fault_data = addr; if (is_debug(access)) throw trap_access(0, addr); - this->trap_state = (1UL << 31); // issue trap 0 + this->reg.trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { if(!is_debug(access) && (addr&(alignment-1))){ - this->trap_state = (1UL << 31) | 4<<16; + this->reg.trap_state = (1UL << 31) | 4<<16; fault_data=addr; return iss::Err; } @@ -681,12 +681,12 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce res = hart_mem_rd_delegate( phys_addr, length, data); } if (unlikely(res != iss::Ok)){ - this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault + this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; } return res; } catch (trap_access &ta) { - this->trap_state = (1UL << 31) | ta.id; + this->reg.trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -712,7 +712,7 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce } return iss::Ok; } catch (trap_access &ta) { - this->trap_state = (1UL << 31) | ta.id; + this->reg.trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -750,12 +750,12 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->trap_state = (1UL << 31); // issue trap 0 + this->reg.trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ - this->trap_state = (1UL << 31) | 6<<16; + this->reg.trap_state = (1UL << 31) | 6<<16; fault_data=addr; return iss::Err; } @@ -774,12 +774,12 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc res = write_mem( phys_addr, length, data); } if (unlikely(res != iss::Ok)) { - this->trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) + this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } return res; } catch (trap_access &ta) { - this->trap_state = (1UL << 31) | ta.id; + this->reg.trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -839,7 +839,7 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc } return iss::Ok; } catch (trap_access &ta) { - this->trap_state = (1UL << 31) | ta.id; + this->reg.trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -885,7 +885,7 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { - auto cycle_val = this->icount + cycle_offset; + auto cycle_val = this->reg.icount + cycle_offset; if (addr == mcycle) { val = static_cast(cycle_val); } else if (addr == mcycleh) { @@ -904,35 +904,35 @@ template iss::status riscv_hart_m_p mcycle_csr = (static_cast(val)<<32) + (mcycle_csr & 0xffffffff); } } - cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around + cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around return iss::Ok; } template iss::status riscv_hart_m_p::read_instret(unsigned addr, reg_t &val) { if ((addr&0xff) == (minstret&0xff)) { - val = static_cast(this->instret); + val = static_cast(this->reg.instret); } else if ((addr&0xff) == (minstreth&0xff)) { - val = static_cast(this->instret >> 32); + val = static_cast(this->reg.instret >> 32); } return iss::Ok; } template iss::status riscv_hart_m_p::write_instret(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { - this->instret = static_cast(val); + this->reg.instret = static_cast(val); } else { if ((addr&0xff) == (minstret&0xff)) { - this->instret = (this->instret & 0xffffffff00000000) + val; + this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; } else { - this->instret = (static_cast(val)<<32) + (this->instret & 0xffffffff); + this->reg.instret = (static_cast(val)<<32) + (this->reg.instret & 0xffffffff); } } - this->instret--; + this->reg.instret--; return iss::Ok; } template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t &val) { - uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052; + uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; if (addr == time) { val = static_cast(time_val); } else if (addr == timeh) { @@ -1074,18 +1074,6 @@ iss::status riscv_hart_m_p::write_xtvt(unsigned addr, reg_t val) { template iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { switch (paddr.val) { - case 0x0200BFF8: { // CLINT base, mtime reg - if (sizeof(reg_t) < length) return iss::Err; - reg_t time_val; - this->read_csr(time, time_val); - std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + 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->icount > 30000) data[3] |= 0x80; - } break; default: { for(auto offs=0U; offs::read_mem(phys_addr_t paddr, unsigned len template iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { switch (paddr.val) { - case 0x10013000: // UART0 base, TXFIFO reg - case 0x10023000: // UART1 base, TXFIFO reg - uart_buf << (char)data[0]; + case 0xFFFF0000: // UART0 base, TXFIFO reg if (((char)data[0]) == '\n' || data[0] == 0) { - LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<>12)&0x3)<<" send '"<::write_mem(phys_addr_t paddr, unsigned le LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } - this->trap_state=std::numeric_limits::max(); + this->reg.trap_state=std::numeric_limits::max(); this->interrupt_sim=hostvar; break; //throw(iss::simulation_stopped(hostvar)); @@ -1227,7 +1199,7 @@ template void riscv_hart_m_p::check enabled_interrupts >>= 1; res++; } - this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id + this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id } } @@ -1275,7 +1247,7 @@ template uint64_t riscv_hart_m_p::e fault_data = 0; } else { csr[mepc] = this->reg.NEXT_PC & get_pc_mask(); // store next address if interrupt - this->pending_trap = 0; + this->reg.pending_trap = 0; } csr[mcause] = (trap_id << (traits::XLEN-1)) + cause; // update mstatus @@ -1305,7 +1277,7 @@ template uint64_t riscv_hart_m_p::e } // reset trap state this->reg.PRIV = new_priv; - this->trap_state = 0; + this->reg.trap_state = 0; std::array buffer; #if defined(_MSC_VER) sprintf(buffer.data(), "0x%016llx", addr); @@ -1326,7 +1298,7 @@ template uint64_t riscv_hart_m_p::l this->reg.NEXT_PC = csr[mepc] & get_pc_mask(); CLOG(INFO, disass) << "Executing xRET"; check_interrupt(); - this->trap_state = this->pending_trap; + this->reg.trap_state = this->reg.pending_trap; return this->reg.NEXT_PC; } diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index 5936329..49d1363 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -307,7 +307,7 @@ public: void disass_output(uint64_t pc, const std::string instr) override { CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->icount + cycle_offset); + pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } @@ -607,12 +607,12 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->trap_state = (1 << 31); // issue trap 0 + this->reg.trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { if(!is_debug(access) && (addr&(alignment-1))){ - this->trap_state = 1<<31 | 4<<16; + this->reg.trap_state = 1<<31 | 4<<16; fault_data=addr; return iss::Err; } @@ -631,12 +631,12 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data): read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); if (unlikely(res != iss::Ok)){ - this->trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault + this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; } return res; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->reg.trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -652,7 +652,7 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ case 3: { // SFENCE:VMA upper auto tvm = state.mstatus.TVM; if (this->reg.PRIV == PRIV_S & tvm != 0) { - this->trap_state = (1 << 31) | (2 << 16); + this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; } @@ -673,7 +673,7 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ } return iss::Ok; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->reg.trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -711,7 +711,7 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->trap_state = (1 << 31); // issue trap 0 + this->reg.trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { @@ -730,12 +730,12 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access write_mem(phys_addr_t{access, space, addr}, length, data): write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); if (unlikely(res != iss::Ok)) { - this->trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) + this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } return res; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->reg.trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -784,7 +784,7 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access ptw.clear(); auto tvm = state.mstatus.TVM; if (this->reg.PRIV == PRIV_S & tvm != 0) { - this->trap_state = (1 << 31) | (2 << 16); + this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; } @@ -800,7 +800,7 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access } return iss::Ok; } catch (trap_access &ta) { - this->trap_state = (1 << 31) | ta.id; + this->reg.trap_state = (1 << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -846,7 +846,7 @@ template iss::status riscv_hart_msu_vp::write_reg(unsigned } template iss::status riscv_hart_msu_vp::read_cycle(unsigned addr, reg_t &val) { - auto cycle_val = this->icount + cycle_offset; + auto cycle_val = this->reg.icount + cycle_offset; if (addr == mcycle) { val = static_cast(cycle_val); } else if (addr == mcycleh) { @@ -868,7 +868,7 @@ template iss::status riscv_hart_msu_vp::write_cycle(unsign mcycle_csr = (static_cast(val)<<32) + (mcycle_csr & 0xffffffff); } } - cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around + cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around return iss::Ok; } @@ -899,7 +899,7 @@ template iss::status riscv_hart_msu_vp::write_instret(unsi } template iss::status riscv_hart_msu_vp::read_time(unsigned addr, reg_t &val) { - uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052; + uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; if (addr == time) { val = static_cast(time_val); } else if (addr == timeh) { @@ -968,7 +968,7 @@ template iss::status riscv_hart_msu_vp::write_epc(unsigned template iss::status riscv_hart_msu_vp::read_satp(unsigned addr, reg_t &val) { reg_t tvm = state.mstatus.TVM; if (this->reg.PRIV == PRIV_S & tvm != 0) { - this->trap_state = (1 << 31) | (2 << 16); + this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; } @@ -979,7 +979,7 @@ template iss::status riscv_hart_msu_vp::read_satp(unsigned template iss::status riscv_hart_msu_vp::write_satp(unsigned addr, reg_t val) { reg_t tvm = state.mstatus.TVM; if (this->reg.PRIV == PRIV_S & tvm != 0) { - this->trap_state = (1 << 31) | (2 << 16); + this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; } @@ -1024,18 +1024,6 @@ template iss::status riscv_hart_msu_vp::write_fcsr(unsigne template iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { switch (paddr.val) { - case 0x0200BFF8: { // CLINT base, mtime reg - if (sizeof(reg_t) < length) return iss::Err; - reg_t time_val; - this->read_csr(time, time_val); - std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + 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->icount > 30000) data[3] |= 0x80; - } break; default: { for(auto offs=0U; offs::read_mem(phys_addr_t paddr, unsigned length template iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { switch (paddr.val) { - case 0x10013000: // UART0 base, TXFIFO reg - case 0x10023000: // UART1 base, TXFIFO reg - uart_buf << (char)data[0]; + case 0xFFFF0000: // UART0 base, TXFIFO reg if (((char)data[0]) == '\n' || data[0] == 0) { - // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send - // '"<>12)&0x3)<<" send '"<::write_mem(phys_addr_t paddr, unsigned lengt LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } - this->trap_state=std::numeric_limits::max(); + this->reg.trap_state=std::numeric_limits::max(); this->interrupt_sim=hostvar; break; //throw(iss::simulation_stopped(hostvar)); @@ -1162,7 +1133,7 @@ template void riscv_hart_msu_vp::check_interrupt() { if (enabled_interrupts != 0) { int res = 0; while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++; - this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id + this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id } } @@ -1306,7 +1277,7 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f 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->pending_trap = 0; + this->reg.pending_trap = 0; } size_t adr = ucause | (new_priv << 8); csr[adr] = (trap_id << 31) + cause; @@ -1351,7 +1322,7 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f << lvl[cur_priv] << " to " << lvl[new_priv]; // reset trap state this->reg.PRIV = new_priv; - this->trap_state = 0; + this->reg.trap_state = 0; update_vm_info(); return this->reg.NEXT_PC; } @@ -1363,7 +1334,7 @@ template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t f auto tsr = state.mstatus.TSR; if (cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) { - this->trap_state = (1 << 31) | (2 << 16); + this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return this->reg.PC; } @@ -1402,7 +1373,7 @@ template void riscv_hart_msu_vp::wait_until(uint64_t flags auto status = state.mstatus; auto tw = status.TW; if (this->reg.PRIV == PRIV_S && tw != 0) { - this->trap_state = (1 << 31) | (2 << 16); + this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; } } diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 719276d..513ca20 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -304,7 +304,7 @@ public: void disass_output(uint64_t pc, const std::string instr) override { CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->icount + cycle_offset); + pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset); }; iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } @@ -816,7 +816,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc if(!pmp_check(access, addr, length) && !is_debug(access)) { fault_data = addr; if (is_debug(access)) throw trap_access(0, addr); - this->trap_state = (1UL << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1 + this->reg.trap_state = (1UL << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1 return iss::Err; } } @@ -824,12 +824,12 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { fault_data = addr; if (is_debug(access)) throw trap_access(0, addr); - this->trap_state = (1UL << 31); // issue trap 0 + this->reg.trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { if(!is_debug(access) && (addr&(alignment-1))){ - this->trap_state = (1UL << 31) | 4<<16; + this->reg.trap_state = (1UL << 31) | 4<<16; fault_data=addr; return iss::Err; } @@ -848,12 +848,12 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc res = hart_mem_rd_delegate( phys_addr, length, data); } if (unlikely(res != iss::Ok)){ - this->trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault + this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; } return res; } catch (trap_access &ta) { - this->trap_state = (1UL << 31) | ta.id; + this->reg.trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -879,7 +879,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc } return iss::Ok; } catch (trap_access &ta) { - this->trap_state = (1UL << 31) | ta.id; + this->reg.trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -918,19 +918,19 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->trap_state = (1UL << 31) | (7 << 16); // issue trap 1 + this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 1 return iss::Err; } } if (unlikely(is_fetch(access) && (addr & 0x1) == 1)) { fault_data = addr; if (access && iss::access_type::DEBUG) throw trap_access(0, addr); - this->trap_state = (1UL << 31); // issue trap 0 + this->reg.trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ - this->trap_state = (1UL << 31) | 6<<16; + this->reg.trap_state = (1UL << 31) | 6<<16; fault_data=addr; return iss::Err; } @@ -949,12 +949,12 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac res = hart_mem_wr_delegate( phys_addr, length, data); } if (unlikely(res != iss::Ok)) { - this->trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) + this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } return res; } catch (trap_access &ta) { - this->trap_state = (1UL << 31) | ta.id; + this->reg.trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -1014,7 +1014,7 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac } return iss::Ok; } catch (trap_access &ta) { - this->trap_state = (1UL << 31) | ta.id; + this->reg.trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -1060,7 +1060,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_cycle(unsigned addr, reg_t &val) { - auto cycle_val = this->icount + cycle_offset; + auto cycle_val = this->reg.icount + cycle_offset; if (addr == mcycle) { val = static_cast(cycle_val); } else if (addr == mcycleh) { @@ -1079,35 +1079,35 @@ template iss::status riscv_hart_mu_p(val)<<32) + (mcycle_csr & 0xffffffff); } } - cycle_offset = mcycle_csr-this->icount; // TODO: relying on wrap-around + cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around return iss::Ok; } template iss::status riscv_hart_mu_p::read_instret(unsigned addr, reg_t &val) { if ((addr&0xff) == (minstret&0xff)) { - val = static_cast(this->instret); + val = static_cast(this->reg.instret); } else if ((addr&0xff) == (minstreth&0xff)) { - val = static_cast(this->instret >> 32); + val = static_cast(this->reg.instret >> 32); } return iss::Ok; } template iss::status riscv_hart_mu_p::write_instret(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { - this->instret = static_cast(val); + this->reg.instret = static_cast(val); } else { if ((addr&0xff) == (minstret&0xff)) { - this->instret = (this->instret & 0xffffffff00000000) + val; + this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; } else { - this->instret = (static_cast(val)<<32) + (this->instret & 0xffffffff); + this->reg.instret = (static_cast(val)<<32) + (this->reg.instret & 0xffffffff); } } - this->instret--; + this->reg.instret--; return iss::Ok; } template iss::status riscv_hart_mu_p::read_time(unsigned addr, reg_t &val) { - uint64_t time_val = this->icount / (100000000 / 32768 - 1); //-> ~3052; + uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; if (addr == time) { val = static_cast(time_val); } else if (addr == timeh) { @@ -1283,18 +1283,6 @@ iss::status riscv_hart_mu_p::write_xtvt(unsigned addr, reg_t val) { template iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { switch (paddr.val) { - case 0x0200BFF8: { // CLINT base, mtime reg - if (sizeof(reg_t) < length) return iss::Err; - reg_t time_val; - this->read_csr(time, time_val); - std::copy((uint8_t *)&time_val, ((uint8_t *)&time_val) + 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->icount > 30000) data[3] |= 0x80; - } break; default: { for(auto offs=0U; offs::read_mem(phys_addr_t paddr, unsigned le template iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { switch (paddr.val) { - case 0x10013000: // UART0 base, TXFIFO reg - case 0x10023000: // UART1 base, TXFIFO reg - uart_buf << (char)data[0]; + case 0xFFFF0000: // UART0 base, TXFIFO reg if (((char)data[0]) == '\n' || data[0] == 0) { - LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send '"<>12)&0x3)<<" send '"<::write_mem(phys_addr_t paddr, unsigned l LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } - this->trap_state=std::numeric_limits::max(); + this->reg.trap_state=std::numeric_limits::max(); this->interrupt_sim=hostvar; break; //throw(iss::simulation_stopped(hostvar)); @@ -1436,14 +1408,14 @@ template void riscv_hart_mu_p::chec enabled_interrupts >>= 1; res++; } - this->pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id + this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id } } template uint64_t riscv_hart_mu_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val - if(flags==std::numeric_limits::max()) flags=this->trap_state; + if(flags==std::numeric_limits::max()) flags=this->reg.trap_state; auto trap_id = bit_sub<0, 16>(flags); auto cause = bit_sub<16, 15>(flags); if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause @@ -1490,7 +1462,7 @@ template uint64_t riscv_hart_mu_p:: if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) new_priv = PRIV_U; csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt - this->pending_trap = 0; + this->reg.pending_trap = 0; } size_t adr = ucause | (new_priv << 8); csr[adr] = (trap_id << (traits::XLEN-1)) + cause; @@ -1543,7 +1515,7 @@ template uint64_t riscv_hart_mu_p:: << lvl[this->reg.PRIV] << " to " << lvl[new_priv]; // reset trap state this->reg.PRIV = new_priv; - this->trap_state = 0; + this->reg.trap_state = 0; return this->reg.NEXT_PC; } @@ -1552,7 +1524,7 @@ template uint64_t riscv_hart_mu_p:: auto inst_priv = (flags & 0x3)? 3:0; if(inst_priv>cur_priv){ auto trap_val = 0x80ULL << 24 | (2 << 16); // illegal instruction - this->trap_state = trap_val; + this->reg.trap_state = trap_val; this->reg.NEXT_PC = std::numeric_limits::max(); } else { auto status = state.mstatus; diff --git a/src/iss/arch/tgc_c.cpp b/src/iss/arch/tgc_c.cpp index ed4d7ca..e4fc905 100644 --- a/src/iss/arch/tgc_c.cpp +++ b/src/iss/arch/tgc_c.cpp @@ -55,8 +55,8 @@ void tgc_c::reset(uint64_t address) { reg.PC=address; reg.NEXT_PC=reg.PC; reg.PRIV=0x3; - trap_state=0; - icount=0; + reg.trap_state=0; + reg.icount=0; } uint8_t *tgc_c::get_regs_base_ptr() { diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index 53776c0..4d47835 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -189,7 +189,7 @@ struct tgc_c: public arch_if { uint8_t* get_regs_base_ptr() override; - inline uint64_t get_icount() { return icount; } + inline uint64_t get_icount() { return reg.icount; } inline bool should_stop() { return interrupt_sim; } @@ -207,7 +207,7 @@ struct tgc_c: public arch_if { virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } - inline uint32_t get_last_branch() { return last_branch; } + inline uint32_t get_last_branch() { return reg.last_branch; } #pragma pack(push, 1) @@ -256,12 +256,6 @@ struct tgc_c: public arch_if { uint32_t last_branch = 0; } reg; #pragma pack(pop) - uint32_t trap_state = 0, pending_trap = 0; - uint64_t icount = 0; - uint64_t cycle = 0; - uint64_t instret = 0; - uint32_t instruction = 0; - uint32_t last_branch = 0; std::array addr_mode; uint64_t interrupt_sim=0; diff --git a/src/main.cpp b/src/main.cpp index 2cd1316..e2b7850 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) { ("elf,f", po::value>(), "ELF file(s) to load") ("mem,m", po::value(), "the memory input file") ("plugin,p", po::value>(), "plugin to activate") - ("backend", po::value()->default_value("interp"), "the memory input file") + ("backend", po::value()->default_value("interp"), "the ISS backend to use, options are: interp, tcc") ("isa", po::value()->default_value("tgc_c"), "isa to use for simulation"); // clang-format on auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 3e54a25..e59d80d 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -115,7 +115,7 @@ protected: inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; - this->core.trap_state = trap_val; + this->core.reg.trap_state = trap_val; this->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); } @@ -322,16 +322,16 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto pc=start; auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); auto* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - auto& trap_state = this->core.trap_state; - auto& icount = this->core.icount; - auto& cycle = this->core.cycle; - auto& instret = this->core.instret; - auto& instr = this->core.instruction; + auto& trap_state = this->core.reg.trap_state; + auto& icount = this->core.reg.icount; + auto& cycle = this->core.reg.cycle; + auto& instret = this->core.reg.instret; + auto& instr = this->core.reg.instruction; // we fetch at max 4 byte, alignment is 2 auto *const data = reinterpret_cast(&instr); while(!this->core.should_stop() && - !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ + !(is_count_limit_enabled(cond) && icount >= icount_limit)){ if(fetch_ins(pc, data)!=iss::Ok){ this->do_sync(POST_SYNC, std::numeric_limits::max()); pc.val = super::core.enter_trap(std::numeric_limits::max(), pc.val, 0); @@ -340,7 +340,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' auto inst_id = decode_inst_id(instr); // pre execution stuff - this->core.last_branch = 0; + this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); switch(inst_id){ case arch::traits::opcode_e::LUI: { @@ -422,7 +422,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *(X+rd) = *PC + 4; } *NEXT_PC = *PC + (int32_t)sext<21>(imm); - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } } } @@ -457,7 +457,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *(X+rd) = *PC + 4; } *NEXT_PC = new_pc & ~ 0x1; - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } } } @@ -489,7 +489,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } } } @@ -522,7 +522,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } } } @@ -555,7 +555,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } } } @@ -588,7 +588,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } } } @@ -621,7 +621,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } } } @@ -654,7 +654,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { *NEXT_PC = *PC + (int16_t)sext<13>(imm); - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } } } @@ -683,7 +683,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); int8_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state>=0x80000000UL) goto TRAP_LB; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LB; int8_t res = (int8_t)read_res; if(rd != 0) { *(X+rd) = (uint32_t)res; @@ -714,7 +714,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); int16_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state>=0x80000000UL) goto TRAP_LH; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LH; int16_t res = (int16_t)read_res; if(rd != 0) { *(X+rd) = (uint32_t)res; @@ -745,7 +745,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); int32_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state>=0x80000000UL) goto TRAP_LW; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LW; int32_t res = (int32_t)read_res; if(rd != 0) { *(X+rd) = (uint32_t)res; @@ -776,7 +776,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); uint8_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state>=0x80000000UL) goto TRAP_LBU; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LBU; uint8_t res = (uint8_t)read_res; if(rd != 0) { *(X+rd) = (uint32_t)res; @@ -807,7 +807,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); uint16_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state>=0x80000000UL) goto TRAP_LHU; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LHU; uint16_t res = (uint16_t)read_res; if(rd != 0) { *(X+rd) = (uint32_t)res; @@ -838,7 +838,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); super::template write_mem(traits::MEM, store_address, (int8_t)*(X+rs2)); - if(this->core.trap_state>=0x80000000UL) goto TRAP_SB; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SB; } } TRAP_SB:break; @@ -865,7 +865,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); super::template write_mem(traits::MEM, store_address, (int16_t)*(X+rs2)); - if(this->core.trap_state>=0x80000000UL) goto TRAP_SH; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SH; } } TRAP_SH:break; @@ -892,7 +892,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); super::template write_mem(traits::MEM, store_address, (int32_t)*(X+rs2)); - if(this->core.trap_state>=0x80000000UL) goto TRAP_SW; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SW; } } TRAP_SW:break; @@ -1428,7 +1428,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { super::template write_mem(traits::FENCE, traits::fence, pred << 4 | succ); - if(this->core.trap_state>=0x80000000UL) goto TRAP_FENCE; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE; } TRAP_FENCE:break; }// @suppress("No break at end of case") @@ -1507,15 +1507,15 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t xrs1 = *(X+rs1); if(rd != 0) { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; uint32_t xrd = read_res; super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; *(X+rd) = xrd; } else { super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRW; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; } } } @@ -1542,12 +1542,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRS; uint32_t xrd = read_res; uint32_t xrs1 = *(X+rs1); if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd | xrs1); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRS; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRS; } if(rd != 0) { *(X+rd) = xrd; @@ -1577,12 +1577,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRC; uint32_t xrd = read_res; uint32_t xrs1 = *(X+rs1); if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRC; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRC; } if(rd != 0) { *(X+rd) = xrd; @@ -1612,10 +1612,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRWI; uint32_t xrd = read_res; super::template write_mem(traits::CSR, csr, (uint32_t)zimm); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRWI; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRWI; if(rd != 0) { *(X+rd) = xrd; } @@ -1644,11 +1644,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRSI; uint32_t xrd = read_res; if(zimm != 0) { super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRSI; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRSI; } if(rd != 0) { *(X+rd) = xrd; @@ -1678,11 +1678,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRCI; uint32_t xrd = read_res; if(zimm != 0) { super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSRRCI; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRCI; } if(rd != 0) { *(X+rd) = xrd; @@ -1707,7 +1707,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { super::template write_mem(traits::FENCE, traits::fencei, imm); - if(this->core.trap_state>=0x80000000UL) goto TRAP_FENCE_I; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE_I; } TRAP_FENCE_I:break; }// @suppress("No break at end of case") @@ -2015,7 +2015,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t load_address = *(X+rs1 + 8) + uimm; int32_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CLW; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLW; *(X+rd + 8) = (int32_t)read_res; } TRAP_CLW:break; @@ -2038,7 +2038,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { uint32_t load_address = *(X+rs1 + 8) + uimm; super::template write_mem(traits::MEM, load_address, (int32_t)*(X+rs2 + 8)); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSW; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSW; } TRAP_CSW:break; }// @suppress("No break at end of case") @@ -2097,7 +2097,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { *(X+1) = *PC + 2; *NEXT_PC = *PC + (int16_t)sext<12>(imm); - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } TRAP_CJAL:break; }// @suppress("No break at end of case") @@ -2342,7 +2342,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { *NEXT_PC = *PC + (int16_t)sext<12>(imm); - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } TRAP_CJ:break; }// @suppress("No break at end of case") @@ -2363,7 +2363,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { if(*(X+rs1 + 8) == 0) { *NEXT_PC = *PC + (int16_t)sext<9>(imm); - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } } TRAP_CBEQZ:break; @@ -2385,7 +2385,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { if(*(X+rs1 + 8) != 0) { *NEXT_PC = *PC + (int16_t)sext<9>(imm); - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } } TRAP_CBNEZ:break; @@ -2436,7 +2436,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { int32_t read_res = super::template read_mem(traits::MEM, *(X+2) + uimm); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CLWSP; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLWSP; int32_t res = read_res; *(X+rd) = (int32_t)res; } @@ -2485,7 +2485,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co { if(rs1 && rs1 < traits::RFS) { *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } else { raise(0, 2); @@ -2553,7 +2553,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t new_pc = *(X+rs1); *(X+1) = *PC + 2; *NEXT_PC = new_pc & ~ 0x1; - this->core.last_branch = 1; + this->core.reg.last_branch = 1; } } TRAP_CJALR:break; @@ -2592,7 +2592,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { uint32_t offs = *(X+2) + uimm; super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2)); - if(this->core.trap_state>=0x80000000UL) goto TRAP_CSWSP; + if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSWSP; } } TRAP_CSWSP:break; @@ -2618,8 +2618,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // post execution stuff process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); - // if(!this->core.trap_state) // update trap state if there is a pending interrupt - // this->core.trap_state = this->core.pending_trap; + // if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt + // this->core.reg.trap_state = this->core.reg.pending_trap; // trap check if(trap_state!=0){ super::core.enter_trap(trap_state, pc.val, instr); @@ -2630,7 +2630,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co cycle++; pc.val=*NEXT_PC; this->core.reg.PC = this->core.reg.NEXT_PC; - this->core.trap_state = this->core.pending_trap; + this->core.reg.trap_state = this->core.reg.pending_trap; } } return pc; diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index bd988a0..f68372f 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -384,6 +384,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -393,9 +394,8 @@ private: tu.store(rd + traits::X0,tu.constant((uint32_t)((int32_t)imm),32)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,0); gen_trap_check(tu); return returnValue; @@ -416,6 +416,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -425,9 +426,8 @@ private: tu.store(rd + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)imm,32))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,1); gen_trap_check(tu); return returnValue; @@ -448,6 +448,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -461,12 +462,11 @@ private: } auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)sext<21>(imm),32)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); } } - tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,2); gen_trap_check(tu); return returnValue; @@ -488,6 +488,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -502,12 +503,11 @@ private: } auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); tu.close_scope(); } - tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,3); gen_trap_check(tu); return returnValue; @@ -529,6 +529,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -540,13 +541,12 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); } tu.close_scope(); } - tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,4); gen_trap_check(tu); return returnValue; @@ -568,6 +568,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -579,13 +580,12 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); } tu.close_scope(); } - tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,5); gen_trap_check(tu); return returnValue; @@ -607,6 +607,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -618,13 +619,12 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); } tu.close_scope(); } - tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,6); gen_trap_check(tu); return returnValue; @@ -646,6 +646,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -657,13 +658,12 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); } tu.close_scope(); } - tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,7); gen_trap_check(tu); return returnValue; @@ -685,6 +685,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -696,13 +697,12 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); } tu.close_scope(); } - tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,8); gen_trap_check(tu); return returnValue; @@ -724,6 +724,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -735,13 +736,12 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); } tu.close_scope(); } - tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,9); gen_trap_check(tu); return returnValue; @@ -763,6 +763,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -774,9 +775,8 @@ private: tu.store(rd + traits::X0,tu.ext(res,32,true)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,10); gen_trap_check(tu); return returnValue; @@ -798,6 +798,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -809,9 +810,8 @@ private: tu.store(rd + traits::X0,tu.ext(res,32,true)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,11); gen_trap_check(tu); return returnValue; @@ -833,6 +833,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -844,9 +845,8 @@ private: tu.store(rd + traits::X0,tu.ext(res,32,true)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,12); gen_trap_check(tu); return returnValue; @@ -868,6 +868,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -879,9 +880,8 @@ private: tu.store(rd + traits::X0,tu.ext(res,32,true)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,13); gen_trap_check(tu); return returnValue; @@ -903,6 +903,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -914,9 +915,8 @@ private: tu.store(rd + traits::X0,tu.ext(res,32,true)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,14); gen_trap_check(tu); return returnValue; @@ -938,6 +938,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -946,9 +947,8 @@ private: auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),8,false)); } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,15); gen_trap_check(tu); return returnValue; @@ -970,6 +970,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -978,9 +979,8 @@ private: auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),16,false)); } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,16); gen_trap_check(tu); return returnValue; @@ -1002,6 +1002,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1010,9 +1011,8 @@ private: auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),32,false)); } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,17); gen_trap_check(tu); return returnValue; @@ -1034,6 +1034,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1043,9 +1044,8 @@ private: tu.store(rd + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,18); gen_trap_check(tu); return returnValue; @@ -1067,6 +1067,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1076,9 +1077,8 @@ private: tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant((int16_t)sext<12>(imm),16))), tu.constant( 1,32),tu.constant( 0,32))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,19); gen_trap_check(tu); return returnValue; @@ -1100,6 +1100,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1109,9 +1110,8 @@ private: tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))), tu.constant( 1,32),tu.constant( 0,32))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,20); gen_trap_check(tu); return returnValue; @@ -1133,6 +1133,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1142,9 +1143,8 @@ private: tu.store(rd + traits::X0,tu.bitwise_xor(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,21); gen_trap_check(tu); return returnValue; @@ -1166,6 +1166,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1175,9 +1176,8 @@ private: tu.store(rd + traits::X0,tu.bitwise_or(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,22); gen_trap_check(tu); return returnValue; @@ -1199,6 +1199,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1208,9 +1209,8 @@ private: tu.store(rd + traits::X0,tu.bitwise_and(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,23); gen_trap_check(tu); return returnValue; @@ -1232,6 +1232,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1241,9 +1242,8 @@ private: tu.store(rd + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),tu.constant(shamt,8))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,24); gen_trap_check(tu); return returnValue; @@ -1265,6 +1265,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1274,9 +1275,8 @@ private: tu.store(rd + traits::X0,tu.lshr(tu.load(rs1+ traits::X0, 0),tu.constant(shamt,8))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,25); gen_trap_check(tu); return returnValue; @@ -1298,6 +1298,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1307,9 +1308,8 @@ private: tu.store(rd + traits::X0,tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant(shamt,8))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,26); gen_trap_check(tu); return returnValue; @@ -1331,6 +1331,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1340,9 +1341,8 @@ private: tu.store(rd + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,27); gen_trap_check(tu); return returnValue; @@ -1364,6 +1364,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1373,9 +1374,8 @@ private: tu.store(rd + traits::X0,tu.sub(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,28); gen_trap_check(tu); return returnValue; @@ -1397,6 +1397,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1406,9 +1407,8 @@ private: tu.store(rd + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,29); gen_trap_check(tu); return returnValue; @@ -1430,6 +1430,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1439,9 +1440,8 @@ private: tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true)), tu.constant( 1,32),tu.constant( 0,32))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,30); gen_trap_check(tu); return returnValue; @@ -1463,6 +1463,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1472,9 +1473,8 @@ private: tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0)), tu.constant( 1,32),tu.constant( 0,32))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,31); gen_trap_check(tu); return returnValue; @@ -1496,6 +1496,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1505,9 +1506,8 @@ private: tu.store(rd + traits::X0,tu.bitwise_xor(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,32); gen_trap_check(tu); return returnValue; @@ -1529,6 +1529,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1538,9 +1539,8 @@ private: tu.store(rd + traits::X0,tu.lshr(tu.load(rs1+ traits::X0, 0),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,33); gen_trap_check(tu); return returnValue; @@ -1562,6 +1562,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1571,9 +1572,8 @@ private: tu.store(rd + traits::X0,tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,34); gen_trap_check(tu); return returnValue; @@ -1595,6 +1595,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1604,9 +1605,8 @@ private: tu.store(rd + traits::X0,tu.bitwise_or(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,35); gen_trap_check(tu); return returnValue; @@ -1628,6 +1628,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1637,9 +1638,8 @@ private: tu.store(rd + traits::X0,tu.bitwise_and(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,36); gen_trap_check(tu); return returnValue; @@ -1663,11 +1663,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.write_mem(traits::MEM, static_cast(traits:: fence), tu.constant(pred<< 4|succ,8)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,37); gen_trap_check(tu); return returnValue; @@ -1683,10 +1683,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 11); + auto returnValue = std::make_tuple(CONT); tu.close_scope(); - auto returnValue = std::make_tuple(BRANCH); vm_base::gen_sync(tu, POST_SYNC,38); gen_trap_check(tu); return returnValue; @@ -1702,10 +1703,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 3); + auto returnValue = std::make_tuple(CONT); tu.close_scope(); - auto returnValue = std::make_tuple(BRANCH); vm_base::gen_sync(tu, POST_SYNC,39); gen_trap_check(tu); return returnValue; @@ -1721,10 +1723,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_leave_trap(tu, 3); + auto returnValue = std::make_tuple(CONT); tu.close_scope(); - auto returnValue = std::make_tuple(BRANCH); vm_base::gen_sync(tu, POST_SYNC,40); gen_trap_check(tu); return returnValue; @@ -1740,11 +1743,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_wait(tu, 1); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,41); gen_trap_check(tu); return returnValue; @@ -1766,6 +1769,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1780,9 +1784,8 @@ private: tu.write_mem(traits::MEM, csr, xrs1); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,42); gen_trap_check(tu); return returnValue; @@ -1804,6 +1807,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1818,9 +1822,8 @@ private: tu.store(rd + traits::X0,xrd); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,43); gen_trap_check(tu); return returnValue; @@ -1842,6 +1845,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1856,9 +1860,8 @@ private: tu.store(rd + traits::X0,xrd); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,44); gen_trap_check(tu); return returnValue; @@ -1880,6 +1883,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1891,9 +1895,8 @@ private: tu.store(rd + traits::X0,xrd); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,45); gen_trap_check(tu); return returnValue; @@ -1915,6 +1918,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1928,9 +1932,8 @@ private: tu.store(rd + traits::X0,xrd); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,46); gen_trap_check(tu); return returnValue; @@ -1952,6 +1955,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -1965,9 +1969,8 @@ private: tu.store(rd + traits::X0,xrd); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,47); gen_trap_check(tu); return returnValue; @@ -1989,11 +1992,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.write_mem(traits::MEM, static_cast(traits:: fencei), tu.constant(imm,16)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,48); gen_trap_check(tu); return returnValue; @@ -2015,6 +2018,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2025,9 +2029,8 @@ private: tu.store(rd + traits::X0,tu.ext(res,32,true)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,49); gen_trap_check(tu); return returnValue; @@ -2049,6 +2052,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2059,9 +2063,8 @@ private: tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,50); gen_trap_check(tu); return returnValue; @@ -2083,6 +2086,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2093,9 +2097,8 @@ private: tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,51); gen_trap_check(tu); return returnValue; @@ -2117,6 +2120,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2127,9 +2131,8 @@ private: tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,52); gen_trap_check(tu); return returnValue; @@ -2151,6 +2154,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2170,9 +2174,8 @@ private: tu.close_scope(); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,53); gen_trap_check(tu); return returnValue; @@ -2194,6 +2197,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2209,9 +2213,8 @@ private: } tu.close_scope(); } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,54); gen_trap_check(tu); return returnValue; @@ -2233,6 +2236,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2255,9 +2259,8 @@ private: } tu.close_scope(); } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,55); gen_trap_check(tu); return returnValue; @@ -2279,6 +2282,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2294,9 +2298,8 @@ private: } tu.close_scope(); } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,56); gen_trap_check(tu); return returnValue; @@ -2317,6 +2320,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(imm) { tu.store(rd+ 8 + traits::X0,tu.add(tu.load(2+ traits::X0, 0),tu.constant(imm,8))); @@ -2324,9 +2328,8 @@ private: else{ this->gen_raise_trap(tu, 0, 2); } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,57); gen_trap_check(tu); return returnValue; @@ -2348,12 +2351,12 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); auto load_address = tu.assignment(tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8)),32); tu.store(rd+ 8 + traits::X0,tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,false)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,58); gen_trap_check(tu); return returnValue; @@ -2375,12 +2378,12 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); auto load_address = tu.assignment(tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8)),32); tu.write_mem(traits::MEM, load_address, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,false)); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,59); gen_trap_check(tu); return returnValue; @@ -2401,6 +2404,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2410,9 +2414,8 @@ private: tu.store(rs1 + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,60); gen_trap_check(tu); return returnValue; @@ -2429,10 +2432,10 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; - tu.open_scope(); - tu.close_scope(); gen_set_pc(tu, pc, traits::NEXT_PC); + tu.open_scope(); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,61); gen_trap_check(tu); return returnValue; @@ -2452,14 +2455,14 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); - tu.close_scope(); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,62); gen_trap_check(tu); return returnValue; @@ -2480,6 +2483,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2489,9 +2493,8 @@ private: tu.store(rd + traits::X0,tu.constant((int8_t)sext<6>(imm),8)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,63); gen_trap_check(tu); return returnValue; @@ -2512,6 +2515,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(imm== 0||rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2519,9 +2523,8 @@ private: if(rd!= 0) { tu.store(rd + traits::X0,tu.constant((int32_t)sext<18>(imm),32)); } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,64); gen_trap_check(tu); return returnValue; @@ -2541,6 +2544,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(nzimm) { tu.store(2 + traits::X0,tu.add(tu.load(2+ traits::X0, 0),tu.constant((int16_t)sext<10>(nzimm),16))); @@ -2548,9 +2552,8 @@ private: else{ this->gen_raise_trap(tu, 0, 2); } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,65); gen_trap_check(tu); return returnValue; @@ -2567,11 +2570,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 2); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,66); gen_trap_check(tu); return returnValue; @@ -2592,11 +2595,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rs1+ 8 + traits::X0,tu.lshr(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(shamt,8))); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,67); gen_trap_check(tu); return returnValue; @@ -2617,6 +2620,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(shamt){ tu.store(rs1+ 8 + traits::X0,tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant(shamt,8))); } @@ -2624,9 +2628,8 @@ private: if(static_cast(traits:: XLEN)== 128){ tu.store(rs1+ 8 + traits::X0,tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant( 64,32))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,68); gen_trap_check(tu); return returnValue; @@ -2647,11 +2650,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rs1+ 8 + traits::X0,tu.bitwise_and(tu.load(rs1+ 8+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,69); gen_trap_check(tu); return returnValue; @@ -2672,11 +2675,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.sub(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,70); gen_trap_check(tu); return returnValue; @@ -2697,11 +2700,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_xor(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,71); gen_trap_check(tu); return returnValue; @@ -2722,11 +2725,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_or(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,72); gen_trap_check(tu); return returnValue; @@ -2747,11 +2750,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_and(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,73); gen_trap_check(tu); return returnValue; @@ -2771,13 +2774,13 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); - tu.close_scope(); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,74); gen_trap_check(tu); return returnValue; @@ -2798,15 +2801,15 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); - tu.close_scope(); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,75); gen_trap_check(tu); return returnValue; @@ -2827,15 +2830,15 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); - tu.close_scope(); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,76); gen_trap_check(tu); return returnValue; @@ -2856,6 +2859,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2865,9 +2869,8 @@ private: tu.store(rs1 + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),tu.constant(nzuimm,8))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,77); gen_trap_check(tu); return returnValue; @@ -2888,6 +2891,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rd== 0) { this->gen_raise_trap(tu, 0, 2); @@ -2896,9 +2900,8 @@ private: auto res = tu.assignment(tu.read_mem(traits::MEM, tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8)), 32),32); tu.store(rd + traits::X0,tu.ext(res,32,false)); } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,78); gen_trap_check(tu); return returnValue; @@ -2919,6 +2922,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -2928,9 +2932,8 @@ private: tu.store(rd + traits::X0,tu.load(rs2+ traits::X0, 0)); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,79); gen_trap_check(tu); return returnValue; @@ -2950,18 +2953,18 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs1&&rs1(traits:: RFS)) { auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0),tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); } else{ this->gen_raise_trap(tu, 0, 2); } - tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,80); gen_trap_check(tu); return returnValue; @@ -2977,11 +2980,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 2); - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,81); gen_trap_check(tu); return returnValue; @@ -3002,6 +3005,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -3011,9 +3015,8 @@ private: tu.store(rd + traits::X0,tu.add(tu.load(rd+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); } } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,82); gen_trap_check(tu); return returnValue; @@ -3033,6 +3036,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -3042,11 +3046,10 @@ private: tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); - auto noJump = tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_NE, tu.ext(PC_val_v, 32, true), tu.constant(pc.val, 32)),tu.constant(0U, 32), tu.constant(1U, 32)); - tu.store(traits::LAST_BRANCH, noJump); + tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); } - tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,83); gen_trap_check(tu); return returnValue; @@ -3062,10 +3065,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 3); + auto returnValue = std::make_tuple(CONT); tu.close_scope(); - auto returnValue = std::make_tuple(BRANCH); vm_base::gen_sync(tu, POST_SYNC,84); gen_trap_check(tu); return returnValue; @@ -3086,6 +3090,7 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); @@ -3094,9 +3099,8 @@ private: auto offs = tu.assignment(tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8)),32); tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ traits::X0, 0),32,true)); } - tu.close_scope(); - gen_set_pc(tu, pc, traits::NEXT_PC); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,85); gen_trap_check(tu); return returnValue; @@ -3112,10 +3116,11 @@ private: } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; + gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 2); + auto returnValue = std::make_tuple(CONT); tu.close_scope(); - auto returnValue = std::make_tuple(BRANCH); vm_base::gen_sync(tu, POST_SYNC,86); gen_trap_check(tu); return returnValue; @@ -3160,20 +3165,20 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; + // const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); auto *const data = (uint8_t *)&insn; paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { +// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary +// auto res = this->core.read(paddr, 2, data); +// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); +// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction +// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); +// } +// } else { auto res = this->core.read(paddr, 4, data); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } +// } if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; From 60d07f2eb6dafd6294488f4c6b1e2dcbd6c64113 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 1 Jun 2023 06:55:21 +0200 Subject: [PATCH 101/184] changes default loglevel to info for tgc-sim --- src/main.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e2b7850..a3999ad 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) { // clang-format off desc.add_options() ("help,h", "Print help message") - ("verbose,v", po::value()->implicit_value(0), "Sets logging verbosity") + ("verbose,v", po::value()->default_value(4), "Sets logging verbosity") ("logfile,l", po::value(), "Sets default log file.") ("disass,d", po::value()->implicit_value(""), "Enables disassembly") ("gdb-port,g", po::value()->default_value(0), "enable gdb server and specify port to use") @@ -93,11 +93,9 @@ int main(int argc, char *argv[]) { LOGGER(DEFAULT)::print_time() = false; LOGGER(connection)::print_time() = false; - if (clim.count("verbose")) { - auto l = logging::as_log_level(clim["verbose"].as()); - LOGGER(DEFAULT)::reporting_level() = l; - LOGGER(connection)::reporting_level() = l; - } + auto l = logging::as_log_level(clim["verbose"].as()); + LOGGER(DEFAULT)::reporting_level() = l; + LOGGER(connection)::reporting_level() = l; if (clim.count("logfile")) { // configure the connection logger auto f = fopen(clim["logfile"].as().c_str(), "w"); From 11c481cec218246bd9a5d51919c0e236fbe4b324 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Mon, 5 Jun 2023 15:17:16 +0200 Subject: [PATCH 102/184] adds verbosity to error --- src/iss/arch/riscv_hart_m_p.h | 4 ++-- src/iss/arch/riscv_hart_msu_vp.h | 4 ++-- src/iss/arch/riscv_hart_mu_p.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 1111146..af8f835 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -619,9 +619,9 @@ template std::pair riscv_hart_m } return std::make_pair(entry, true); } - throw std::runtime_error("memory load file is not a valid elf file"); + throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file",name)); } - throw std::runtime_error("memory load file not found"); + throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); } template diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index 49d1363..ab77357 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -583,9 +583,9 @@ template std::pair riscv_hart_msu_vp::load } return std::make_pair(entry, true); } - throw std::runtime_error("memory load file is not a valid elf file"); + throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file",name)); } - throw std::runtime_error("memory load file not found"); + throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); } template diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 513ca20..3ee9cd7 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -689,9 +689,9 @@ template std::pair riscv_hart_m } return std::make_pair(entry, true); } - throw std::runtime_error("memory load file is not a valid elf file"); + throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file",name)); } - throw std::runtime_error("memory load file not found"); + throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); } template From 2281ec41440d527397541e478bee791da646f827 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Mon, 5 Jun 2023 15:18:27 +0200 Subject: [PATCH 103/184] corrects errors and adds new backend and --- src/iss/arch/tgc_c.h | 2 +- src/sysc/core_complex.cpp | 6 +- src/vm/tcc/vm_tgc_c.cpp | 202 +++++++++++++++++++------------------- 3 files changed, 105 insertions(+), 105 deletions(-) diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index 4d47835..2b0c9bc 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -53,7 +53,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; - enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; + enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, PGMASK=0b111111111111, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; constexpr static unsigned FP_REGS_SIZE = 0; diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index f3a7ae4..b135117 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -118,7 +118,7 @@ public: std::stringstream s; s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" - << this->icount + this->cycle_offset << "]"; + << this->reg.icount + this->cycle_offset << "]"; SCCDEBUG(owner->name())<<"disass: " << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) << std::setfill(' ') << std::left << instr << s.str(); @@ -178,7 +178,7 @@ public: void wait_until(uint64_t flags) override { SCCDEBUG(owner->name()) << "Sleeping until interrupt"; - while(this->pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) { + while(this->reg.pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) { sc_core::wait(wfi_evt); } PLAT::wait_until(flags); @@ -207,7 +207,7 @@ public: this->csr[arch::mip] &= ~mask; this->check_interrupt(); if(value) - SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->pending_trap; + SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap; } private: diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index f68372f..25135f5 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -380,7 +380,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -412,7 +412,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -444,7 +444,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -462,7 +462,7 @@ private: } auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)sext<21>(imm),32)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); } } auto returnValue = std::make_tuple(BRANCH); @@ -484,7 +484,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -503,7 +503,7 @@ private: } auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); @@ -525,7 +525,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -541,7 +541,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); } tu.close_scope(); } @@ -564,7 +564,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -580,7 +580,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); } tu.close_scope(); } @@ -603,7 +603,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -619,7 +619,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); } tu.close_scope(); } @@ -642,7 +642,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -658,7 +658,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); } tu.close_scope(); } @@ -681,7 +681,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -697,7 +697,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); } tu.close_scope(); } @@ -720,7 +720,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -736,7 +736,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); } tu.close_scope(); } @@ -759,7 +759,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -794,7 +794,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -829,7 +829,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -864,7 +864,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -899,7 +899,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -934,7 +934,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -966,7 +966,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -998,7 +998,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1030,7 +1030,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1063,7 +1063,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1096,7 +1096,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1129,7 +1129,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1162,7 +1162,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1195,7 +1195,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1228,7 +1228,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1261,7 +1261,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1294,7 +1294,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1327,7 +1327,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1360,7 +1360,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1393,7 +1393,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1426,7 +1426,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1459,7 +1459,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1492,7 +1492,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1525,7 +1525,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1558,7 +1558,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1591,7 +1591,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1624,7 +1624,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1659,7 +1659,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1679,7 +1679,7 @@ private: vm_base::gen_sync(tu, PRE_SYNC,38); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ecall"); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ecall"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1699,7 +1699,7 @@ private: vm_base::gen_sync(tu, PRE_SYNC,39); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ebreak"); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ebreak"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1719,7 +1719,7 @@ private: vm_base::gen_sync(tu, PRE_SYNC,40); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "mret"); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "mret"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1739,7 +1739,7 @@ private: vm_base::gen_sync(tu, PRE_SYNC,41); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "wfi"); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "wfi"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1765,7 +1765,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1803,7 +1803,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1841,7 +1841,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1879,7 +1879,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1914,7 +1914,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1951,7 +1951,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -1988,7 +1988,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2014,7 +2014,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2048,7 +2048,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2082,7 +2082,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2116,7 +2116,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2150,7 +2150,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2193,7 +2193,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2232,7 +2232,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2278,7 +2278,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2316,7 +2316,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2347,7 +2347,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2374,7 +2374,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2400,7 +2400,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2428,7 +2428,7 @@ private: uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cnop"); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "cnop"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2451,7 +2451,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2460,7 +2460,7 @@ private: tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,62); @@ -2479,7 +2479,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2511,7 +2511,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2540,7 +2540,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), fmt::arg("nzimm", nzimm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2566,7 +2566,7 @@ private: uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "__reserved_clui"); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "__reserved_clui"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2591,7 +2591,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2616,7 +2616,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2646,7 +2646,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2671,7 +2671,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2696,7 +2696,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2721,7 +2721,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2746,7 +2746,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2770,7 +2770,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2778,7 +2778,7 @@ private: tu.open_scope(); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,74); @@ -2797,7 +2797,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2806,7 +2806,7 @@ private: tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); @@ -2826,7 +2826,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2835,7 +2835,7 @@ private: tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); @@ -2855,7 +2855,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2887,7 +2887,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2918,7 +2918,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2949,7 +2949,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -2958,7 +2958,7 @@ private: if(rs1&&rs1(traits:: RFS)) { auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0),tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -2976,7 +2976,7 @@ private: vm_base::gen_sync(tu, PRE_SYNC,81); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "__reserved_cmv"); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "__reserved_cmv"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -3001,7 +3001,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -3032,7 +3032,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -3046,7 +3046,7 @@ private: tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(1U, 1)); + tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); } auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); @@ -3061,7 +3061,7 @@ private: vm_base::gen_sync(tu, PRE_SYNC,84); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cebreak"); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "cebreak"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -3086,7 +3086,7 @@ private: auto mnemonic = fmt::format( "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; @@ -3112,7 +3112,7 @@ private: vm_base::gen_sync(tu, PRE_SYNC,86); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "dii"); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "dii"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+4; From 15cd36dcd4d97df8c5d4ec10a155c0ff24628cf5 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Mon, 5 Jun 2023 17:57:38 +0200 Subject: [PATCH 104/184] adds fix for compressed instructions and reads --- gen_input/templates/tcc/CORENAME.cpp.gtl | 2 +- src/vm/tcc/vm_tgc_c.cpp | 214 +++++++++++------------ 2 files changed, 108 insertions(+), 108 deletions(-) diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index 9ce0e26..b7cec56 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -207,7 +207,7 @@ private: ${it}<%}%> } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ ${instr.length/8}; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope();<%instr.behavior.eachLine{%> ${it}<%}%> diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index 25135f5..f47fb28 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -383,7 +383,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { @@ -415,7 +415,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { @@ -447,7 +447,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { @@ -462,7 +462,7 @@ private: } auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)sext<21>(imm),32)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } } auto returnValue = std::make_tuple(BRANCH); @@ -487,7 +487,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -503,7 +503,7 @@ private: } auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); @@ -528,7 +528,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -541,7 +541,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } tu.close_scope(); } @@ -567,7 +567,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -580,7 +580,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } tu.close_scope(); } @@ -606,7 +606,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -619,7 +619,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } tu.close_scope(); } @@ -645,7 +645,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -658,7 +658,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } tu.close_scope(); } @@ -684,7 +684,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -697,7 +697,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } tu.close_scope(); } @@ -723,7 +723,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -736,7 +736,7 @@ private: else{ auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } tu.close_scope(); } @@ -762,7 +762,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -797,7 +797,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -832,7 +832,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -867,7 +867,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -902,7 +902,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -937,7 +937,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -969,7 +969,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1001,7 +1001,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1033,7 +1033,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1066,7 +1066,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1099,7 +1099,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1132,7 +1132,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1165,7 +1165,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1198,7 +1198,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1231,7 +1231,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1264,7 +1264,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1297,7 +1297,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1330,7 +1330,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -1363,7 +1363,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -1396,7 +1396,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -1429,7 +1429,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -1462,7 +1462,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -1495,7 +1495,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -1528,7 +1528,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -1561,7 +1561,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -1594,7 +1594,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -1627,7 +1627,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -1662,7 +1662,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.write_mem(traits::MEM, static_cast(traits:: fence), tu.constant(pred<< 4|succ,8)); @@ -1682,7 +1682,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ecall"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 11); @@ -1702,7 +1702,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ebreak"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 3); @@ -1722,7 +1722,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "mret"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_leave_trap(tu, 3); @@ -1742,7 +1742,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "wfi"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_wait(tu, 1); @@ -1768,7 +1768,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { @@ -1776,7 +1776,7 @@ private: } else{ auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); - if(rd!= 0){ auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + if(rd!= 0){ auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); tu.write_mem(traits::MEM, csr, xrs1); tu.store(rd + traits::X0,xrd); } @@ -1806,14 +1806,14 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); } else{ - auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); if(rs1!= 0) { tu.write_mem(traits::MEM, csr, tu.bitwise_or(xrd,xrs1)); @@ -1844,14 +1844,14 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); } else{ - auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); if(rs1!= 0) { tu.write_mem(traits::MEM, csr, tu.bitwise_and(xrd,tu.logical_neg(xrs1))); @@ -1882,14 +1882,14 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); } else{ - auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); tu.write_mem(traits::MEM, csr, tu.constant((uint32_t)zimm,32)); if(rd!= 0) { tu.store(rd + traits::X0,xrd); @@ -1917,14 +1917,14 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); } else{ - auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); if(zimm!= 0) { tu.write_mem(traits::MEM, csr, tu.bitwise_or(xrd,tu.constant((uint32_t)zimm,32))); } @@ -1954,14 +1954,14 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { this->gen_raise_trap(tu, 0, 2); } else{ - auto xrd = tu.assignment(tu.read_mem(traits::MEM, csr, 32),32); + auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); if(zimm!= 0) { tu.write_mem(traits::MEM, csr, tu.bitwise_and(xrd,tu.constant(~ ((uint32_t)zimm),32))); } @@ -1991,7 +1991,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.write_mem(traits::MEM, static_cast(traits:: fencei), tu.constant(imm,16)); @@ -2017,7 +2017,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -2051,7 +2051,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -2085,7 +2085,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -2119,7 +2119,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -2153,7 +2153,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -2196,7 +2196,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -2235,7 +2235,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -2281,7 +2281,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rs1>=static_cast(traits:: RFS)||rs2>=static_cast(traits:: RFS)) { @@ -2319,7 +2319,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(imm) { @@ -2350,7 +2350,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); auto load_address = tu.assignment(tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8)),32); @@ -2377,7 +2377,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); auto load_address = tu.assignment(tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8)),32); @@ -2403,7 +2403,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs1>=static_cast(traits:: RFS)) { @@ -2431,7 +2431,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "cnop"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); auto returnValue = std::make_tuple(CONT); @@ -2454,13 +2454,13 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,62); @@ -2482,7 +2482,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { @@ -2514,7 +2514,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(imm== 0||rd>=static_cast(traits:: RFS)) { @@ -2543,7 +2543,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(nzimm) { @@ -2569,7 +2569,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "__reserved_clui"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 2); @@ -2594,7 +2594,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rs1+ 8 + traits::X0,tu.lshr(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(shamt,8))); @@ -2619,7 +2619,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(shamt){ tu.store(rs1+ 8 + traits::X0,tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant(shamt,8))); @@ -2649,7 +2649,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rs1+ 8 + traits::X0,tu.bitwise_and(tu.load(rs1+ 8+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))); @@ -2674,7 +2674,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.sub(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); @@ -2699,7 +2699,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_xor(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); @@ -2724,7 +2724,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_or(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); @@ -2749,7 +2749,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_and(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); @@ -2773,12 +2773,12 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,74); @@ -2800,13 +2800,13 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); @@ -2829,13 +2829,13 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); @@ -2858,7 +2858,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs1>=static_cast(traits:: RFS)) { @@ -2890,7 +2890,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)||rd== 0) { @@ -2921,7 +2921,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { @@ -2952,13 +2952,13 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs1&&rs1(traits:: RFS)) { auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0),tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -2979,7 +2979,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "__reserved_cmv"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 2); @@ -3004,7 +3004,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rd>=static_cast(traits:: RFS)) { @@ -3035,7 +3035,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs1>=static_cast(traits:: RFS)) { @@ -3046,7 +3046,7 @@ private: tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(3U, 2)); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); @@ -3064,7 +3064,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "cebreak"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 3); @@ -3089,7 +3089,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs2>=static_cast(traits:: RFS)) { @@ -3115,7 +3115,7 @@ private: tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "dii"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); - pc=pc+4; + pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 2); From 0b5de90fb1f3418470204b1e25139e1325ec28da Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 11 Jun 2023 18:29:48 +0200 Subject: [PATCH 105/184] changes [m|u]cause rd/wr handling --- src/iss/arch/riscv_hart_m_p.h | 5 ++--- src/iss/arch/riscv_hart_mu_p.h | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 1111146..beb0cc2 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -419,7 +419,7 @@ protected: std::vector> memfn_write; void insert_mem_range(uint64_t, uint64_t, std::function, std::function); feature_config cfg; - unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; + uint64_t mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; inline bool debug_mode_active() {return this->reg.PRIV&0x4;} std::pair, std::function> replace_mem_access(std::function rd, std::function wr){ @@ -966,12 +966,11 @@ template iss::status riscv_hart_m_p val |= state.mstatus.MPIE<<27; val |= state.mstatus.MPP<<28; } else - val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); + val = csr[addr]; // & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); return iss::Ok; } template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { - csr[addr] = val & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); csr[addr] = (val & mask) | (csr[addr] & ~mask); diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 513ca20..0dc0de7 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -446,7 +446,7 @@ protected: std::vector> memfn_write; void insert_mem_range(uint64_t, uint64_t, std::function, std::function); feature_config cfg; - unsigned mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; + uint64_t mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; inline bool debug_mode_active() {return this->reg.PRIV&0x4;} std::pair, std::function> @@ -1148,7 +1148,7 @@ template iss::status riscv_hart_mu_p::XLEN-1)) | (mcause_max_irq-1)); + val = csr[addr];// & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); return iss::Ok; } From 99a9970ddd37cfcf4a7da8e00f4e35680bdf2a56 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 12 Jun 2023 09:58:24 +0200 Subject: [PATCH 106/184] fixes sysc compile issues --- gen_input/templates/CORENAME_instr.yaml.gtl | 6 +- src/iss/arch/riscv_hart_msu_vp.h | 73 +++++++++++---------- src/iss/arch/riscv_hart_mu_p.h | 13 ++-- src/sysc/core_complex.cpp | 6 +- 4 files changed, 50 insertions(+), 48 deletions(-) diff --git a/gen_input/templates/CORENAME_instr.yaml.gtl b/gen_input/templates/CORENAME_instr.yaml.gtl index 542fed6..eb344ff 100644 --- a/gen_input/templates/CORENAME_instr.yaml.gtl +++ b/gen_input/templates/CORENAME_instr.yaml.gtl @@ -14,7 +14,7 @@ ${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %> encoding: ${it.encoding} mask: ${it.mask}<%if(it.attributes.size) {%> attributes: ${it.attributes}<%}%> - size: ${it.length} - branch: ${it.modifiesPC} - delay: ${it.isConditional?"[1,1]":"1"}<%}}%> + size: ${it.length} + branch: ${it.modifiesPC} + delay: ${it.isConditional?"[1,1]":"1"}<%}}%> diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index 49d1363..24ce7f0 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -316,6 +316,9 @@ public: csr[addr & csr.page_addr_mask] = val; } + void set_irq_num(unsigned i) { + mcause_max_irq=1<::core_type; } - virtual uint64_t get_pc() { return arch.get_pc(); }; + uint64_t get_pc() override { return arch.reg.PC; }; - virtual uint64_t get_next_pc() { return arch.get_next_pc(); }; + uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; - uint64_t get_instr_word() override { return arch.instruction; } + uint64_t get_instr_word() override { return arch.reg.instruction; } - uint64_t get_instr_count() { return arch.icount; } + uint64_t get_instr_count() override { return arch.reg.icount; } - uint64_t get_pendig_traps() override { return arch.trap_state; } + uint64_t get_pendig_traps() override { return arch.reg.trap_state; } - uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } + uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; - bool is_branch_taken() override { return arch.last_branch; }; + bool is_branch_taken() override { return arch.reg.last_branch; }; riscv_hart_msu_vp &arch; }; @@ -381,16 +384,17 @@ protected: std::unordered_map csr_rd_cb; std::unordered_map csr_wr_cb; -private: - iss::status read_reg(unsigned addr, reg_t &val); - iss::status write_reg(unsigned addr, reg_t val); + std::vector tcm; + + iss::status read_csr_reg(unsigned addr, reg_t &val); + iss::status write_csr_reg(unsigned addr, reg_t val); iss::status read_null(unsigned addr, reg_t &val); iss::status write_null(unsigned addr, reg_t val){return iss::status::Ok;} iss::status read_cycle(unsigned addr, reg_t &val); iss::status write_cycle(unsigned addr, reg_t val); iss::status read_instret(unsigned addr, reg_t &val); iss::status write_instret(unsigned addr, reg_t val); - iss::status read_mtvec(unsigned addr, reg_t &val); + iss::status read_tvec(unsigned addr, reg_t &val); iss::status read_time(unsigned addr, reg_t &val); iss::status read_status(unsigned addr, reg_t &val); iss::status write_status(unsigned addr, reg_t val); @@ -398,6 +402,8 @@ private: 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_ideleg(unsigned addr, reg_t val); + iss::status write_edeleg(unsigned addr, reg_t val); iss::status read_hartid(unsigned addr, reg_t &val); iss::status write_epc(unsigned addr, reg_t val); iss::status read_satp(unsigned addr, reg_t &val); @@ -417,7 +423,6 @@ private: reg_t mhartid_reg{0x0}; -protected: void check_interrupt(); }; @@ -434,22 +439,22 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() uart_buf.str(""); for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } for (unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr){ csr_rd_cb[addr] = &this_class::read_null; } for (unsigned addr = cycleh; addr <= hpmcounter31h; ++addr){ csr_rd_cb[addr] = &this_class::read_null; - //csr_wr_cb[addr] = &this_class::write_reg; + //csr_wr_cb[addr] = &this_class::write_csr_reg; } // common regs const std::array addrs{{ @@ -459,25 +464,25 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() uepc, utvec, uscratch, ucause, utval, uscratch }}; for(auto addr: addrs) { - csr_rd_cb[addr] = &this_class::read_reg; - csr_wr_cb[addr] = &this_class::write_reg; + csr_rd_cb[addr] = &this_class::read_csr_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } // special handling & overrides csr_rd_cb[time] = &this_class::read_time; - csr_rd_cb[timeh] = &this_class::read_time; + if(traits::XLEN==32) csr_rd_cb[timeh] = &this_class::read_time; csr_rd_cb[cycle] = &this_class::read_cycle; - csr_rd_cb[cycleh] = &this_class::read_cycle; + if(traits::XLEN==32) csr_rd_cb[cycleh] = &this_class::read_cycle; csr_rd_cb[instret] = &this_class::read_instret; - csr_rd_cb[instreth] = &this_class::read_instret; + if(traits::XLEN==32) csr_rd_cb[instreth] = &this_class::read_instret; csr_rd_cb[mcycle] = &this_class::read_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle; - csr_rd_cb[mcycleh] = &this_class::read_cycle; - csr_wr_cb[mcycleh] = &this_class::write_cycle; + if(traits::XLEN==32) csr_rd_cb[mcycleh] = &this_class::read_cycle; + if(traits::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle; csr_rd_cb[minstret] = &this_class::read_instret; csr_wr_cb[minstret] = &this_class::write_instret; - csr_rd_cb[minstreth] = &this_class::read_instret; - csr_wr_cb[minstreth] = &this_class::write_instret; + if(traits::XLEN==32) csr_rd_cb[minstreth] = &this_class::read_instret; + if(traits::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[mstatus] = &this_class::read_status; csr_wr_cb[mstatus] = &this_class::write_status; csr_wr_cb[mcause] = &this_class::write_cause; @@ -527,10 +532,10 @@ template std::pair riscv_hart_msu_vp::load if (fp) { std::array buf; auto n = fread(buf.data(), 1, 4, fp); + fclose(fp); if (n != 4) throw std::runtime_error("input file has insufficient size"); buf[4] = 0; if (strcmp(buf.data() + 1, "ELF") == 0) { - fclose(fp); // Create elfio reader ELFIO::elfio reader; // Load ELF data @@ -549,7 +554,7 @@ template std::pair riscv_hart_msu_vp::load traits::MEM, pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); if (res != iss::Ok) - LOG(ERROR) << "problem writing " << fsize << "bytes to 0x" << std::hex + LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); } } @@ -673,7 +678,7 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ } return iss::Ok; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->reg.trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -730,12 +735,12 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access write_mem(phys_addr_t{access, space, addr}, length, data): write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); if (unlikely(res != iss::Ok)) { - this->reg.trap_state = (1 << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) + this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } return res; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->reg.trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -800,7 +805,7 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access } return iss::Ok; } catch (trap_access &ta) { - this->reg.trap_state = (1 << 31) | ta.id; + this->reg.trap_state = (1UL << 31) | ta.id; fault_data=ta.addr; return iss::Err; } @@ -858,8 +863,6 @@ template iss::status riscv_hart_msu_vp::read_cycle(unsigne template iss::status riscv_hart_msu_vp::write_cycle(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { - if (addr == mcycleh) - return iss::Err; mcycle_csr = static_cast(val); } else { if (addr == mcycle) { @@ -876,7 +879,6 @@ template iss::status riscv_hart_msu_vp::read_instret(unsig if ((addr&0xff) == (minstret&0xff)) { val = static_cast(this->reg.instret); } else if ((addr&0xff) == (minstreth&0xff)) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; val = static_cast(this->reg.instret >> 32); } return iss::Ok; @@ -884,8 +886,6 @@ template iss::status riscv_hart_msu_vp::read_instret(unsig template iss::status riscv_hart_msu_vp::write_instret(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { - if ((addr&0xff) == (minstreth&0xff)) - return iss::Err; this->reg.instret = static_cast(val); } else { if ((addr&0xff) == (minstret&0xff)) { @@ -1234,6 +1234,7 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f auto cur_priv = this->reg.PRIV; // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val + if(flags==std::numeric_limits::max()) flags=this->reg.trap_state; auto trap_id = bit_sub<0, 16>(flags); auto cause = bit_sub<16, 15>(flags); if (trap_id == 0 && cause == 11) cause = 0x8 + cur_priv; // adjust environment call cause diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 0dc0de7..9650ee5 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -284,6 +284,7 @@ public: } riscv_hart_mu_p(feature_config cfg = feature_config{}); + virtual ~riscv_hart_mu_p() = default; void reset(uint64_t address) override; @@ -332,17 +333,17 @@ protected: uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; - uint64_t get_instr_word() override { return arch.instruction; } + uint64_t get_instr_word() override { return arch.reg.instruction; } - uint64_t get_instr_count() override { return arch.icount; } + uint64_t get_instr_count() override { return arch.reg.icount; } - uint64_t get_pendig_traps() override { return arch.trap_state; } + uint64_t get_pendig_traps() override { return arch.reg.trap_state; } - uint64_t get_total_cycles() override { return arch.icount + arch.cycle_offset; } + uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; - bool is_branch_taken() override { return arch.last_branch; }; + bool is_branch_taken() override { return arch.reg.last_branch; }; riscv_hart_mu_p &arch; }; @@ -949,7 +950,7 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac res = hart_mem_wr_delegate( phys_addr, length, data); } if (unlikely(res != iss::Ok)) { - this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) + this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } return res; diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index f3a7ae4..b135117 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -118,7 +118,7 @@ public: std::stringstream s; s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" - << this->icount + this->cycle_offset << "]"; + << this->reg.icount + this->cycle_offset << "]"; SCCDEBUG(owner->name())<<"disass: " << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) << std::setfill(' ') << std::left << instr << s.str(); @@ -178,7 +178,7 @@ public: void wait_until(uint64_t flags) override { SCCDEBUG(owner->name()) << "Sleeping until interrupt"; - while(this->pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) { + while(this->reg.pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) { sc_core::wait(wfi_evt); } PLAT::wait_until(flags); @@ -207,7 +207,7 @@ public: this->csr[arch::mip] &= ~mask; this->check_interrupt(); if(value) - SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->pending_trap; + SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap; } private: From 4dbc7433a5ce58e367d2e740e191929df50e39ef Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 12 Jun 2023 17:38:56 +0200 Subject: [PATCH 107/184] fixes cause CSR handling --- src/iss/arch/riscv_hart_m_p.h | 3 +-- src/iss/arch/riscv_hart_mu_p.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index beb0cc2..40e0ab8 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -959,14 +959,13 @@ template iss::status riscv_hart_m_p } template iss::status riscv_hart_m_p::read_cause(unsigned addr, reg_t &val) { - auto res = csr[addr]; if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); val |= clic_mprev_lvl<<16; val |= state.mstatus.MPIE<<27; val |= state.mstatus.MPP<<28; } else - val = csr[addr]; // & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); + val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); return iss::Ok; } diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 9650ee5..1d65c68 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -1149,7 +1149,7 @@ template iss::status riscv_hart_mu_p::XLEN-1)) | (mcause_max_irq-1)); + val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); return iss::Ok; } From 7e45a252184c5abf0e7e66812bd8b22fa36feece Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 5 Jul 2023 08:28:42 +0200 Subject: [PATCH 108/184] adds a instr yaml for TGC --- TGC_C_instr.yaml | 537 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 537 insertions(+) create mode 100644 TGC_C_instr.yaml diff --git a/TGC_C_instr.yaml b/TGC_C_instr.yaml new file mode 100644 index 0000000..c82876f --- /dev/null +++ b/TGC_C_instr.yaml @@ -0,0 +1,537 @@ + +RV32I: + - LUI: + encoding: 0b00000000000000000000000000110111 + mask: 0b00000000000000000000000001111111 + size: 32 + branch: false + delay: 1 + - AUIPC: + encoding: 0b00000000000000000000000000010111 + mask: 0b00000000000000000000000001111111 + size: 32 + branch: false + delay: 1 + - JAL: + encoding: 0b00000000000000000000000001101111 + mask: 0b00000000000000000000000001111111 + attributes: [[name:no_cont]] + size: 32 + branch: true + delay: 1 + - JALR: + encoding: 0b00000000000000000000000001100111 + mask: 0b00000000000000000111000001111111 + attributes: [[name:no_cont]] + size: 32 + branch: true + delay: 1 + - BEQ: + encoding: 0b00000000000000000000000001100011 + mask: 0b00000000000000000111000001111111 + attributes: [[name:no_cont], [name:cond]] + size: 32 + branch: true + delay: [1,1] + - BNE: + encoding: 0b00000000000000000001000001100011 + mask: 0b00000000000000000111000001111111 + attributes: [[name:no_cont], [name:cond]] + size: 32 + branch: true + delay: [1,1] + - BLT: + encoding: 0b00000000000000000100000001100011 + mask: 0b00000000000000000111000001111111 + attributes: [[name:no_cont], [name:cond]] + size: 32 + branch: true + delay: [1,1] + - BGE: + encoding: 0b00000000000000000101000001100011 + mask: 0b00000000000000000111000001111111 + attributes: [[name:no_cont], [name:cond]] + size: 32 + branch: true + delay: [1,1] + - BLTU: + encoding: 0b00000000000000000110000001100011 + mask: 0b00000000000000000111000001111111 + attributes: [[name:no_cont], [name:cond]] + size: 32 + branch: true + delay: [1,1] + - BGEU: + encoding: 0b00000000000000000111000001100011 + mask: 0b00000000000000000111000001111111 + attributes: [[name:no_cont], [name:cond]] + size: 32 + branch: true + delay: [1,1] + - LB: + encoding: 0b00000000000000000000000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - LH: + encoding: 0b00000000000000000001000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - LW: + encoding: 0b00000000000000000010000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - LBU: + encoding: 0b00000000000000000100000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - LHU: + encoding: 0b00000000000000000101000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SB: + encoding: 0b00000000000000000000000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SH: + encoding: 0b00000000000000000001000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SW: + encoding: 0b00000000000000000010000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - ADDI: + encoding: 0b00000000000000000000000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SLTI: + encoding: 0b00000000000000000010000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SLTIU: + encoding: 0b00000000000000000011000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - XORI: + encoding: 0b00000000000000000100000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - ORI: + encoding: 0b00000000000000000110000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - ANDI: + encoding: 0b00000000000000000111000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SLLI: + encoding: 0b00000000000000000001000000010011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SRLI: + encoding: 0b00000000000000000101000000010011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SRAI: + encoding: 0b01000000000000000101000000010011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - ADD: + encoding: 0b00000000000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SUB: + encoding: 0b01000000000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SLL: + encoding: 0b00000000000000000001000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SLT: + encoding: 0b00000000000000000010000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SLTU: + encoding: 0b00000000000000000011000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - XOR: + encoding: 0b00000000000000000100000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SRL: + encoding: 0b00000000000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - SRA: + encoding: 0b01000000000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - OR: + encoding: 0b00000000000000000110000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - AND: + encoding: 0b00000000000000000111000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - FENCE: + encoding: 0b00000000000000000000000000001111 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - ECALL: + encoding: 0b00000000000000000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + - EBREAK: + encoding: 0b00000000000100000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + - MRET: + encoding: 0b00110000001000000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + - WFI: + encoding: 0b00010000010100000000000001110011 + mask: 0b11111111111111111111111111111111 + size: 32 + branch: false + delay: 1 +Zicsr: + - CSRRW: + encoding: 0b00000000000000000001000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - CSRRS: + encoding: 0b00000000000000000010000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - CSRRC: + encoding: 0b00000000000000000011000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - CSRRWI: + encoding: 0b00000000000000000101000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - CSRRSI: + encoding: 0b00000000000000000110000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + - CSRRCI: + encoding: 0b00000000000000000111000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 +Zifencei: + - FENCE_I: + encoding: 0b00000000000000000001000000001111 + mask: 0b00000000000000000111000001111111 + attributes: [[name:flush]] + size: 32 + branch: false + delay: 1 +RV32M: + - MUL: + encoding: 0b00000010000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - MULH: + encoding: 0b00000010000000000001000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - MULHSU: + encoding: 0b00000010000000000010000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - MULHU: + encoding: 0b00000010000000000011000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - DIV: + encoding: 0b00000010000000000100000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - DIVU: + encoding: 0b00000010000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - REM: + encoding: 0b00000010000000000110000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + - REMU: + encoding: 0b00000010000000000111000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 +RV32IC: + - CADDI4SPN: + encoding: 0b0000000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + - CLW: + encoding: 0b0100000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + - CSW: + encoding: 0b1100000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + - CADDI: + encoding: 0b0000000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + - CNOP: + encoding: 0b0000000000000001 + mask: 0b1110111110000011 + size: 16 + branch: false + delay: 1 + - CJAL: + encoding: 0b0010000000000001 + mask: 0b1110000000000011 + attributes: [[name:no_cont]] + size: 16 + branch: true + delay: 1 + - CLI: + encoding: 0b0100000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + - CLUI: + encoding: 0b0110000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + - CADDI16SP: + encoding: 0b0110000100000001 + mask: 0b1110111110000011 + size: 16 + branch: false + delay: 1 + - CSRLI: + encoding: 0b1000000000000001 + mask: 0b1111110000000011 + size: 16 + branch: false + delay: 1 + - CSRAI: + encoding: 0b1000010000000001 + mask: 0b1111110000000011 + size: 16 + branch: false + delay: 1 + - CANDI: + encoding: 0b1000100000000001 + mask: 0b1110110000000011 + size: 16 + branch: false + delay: 1 + - CSUB: + encoding: 0b1000110000000001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + - CXOR: + encoding: 0b1000110000100001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + - COR: + encoding: 0b1000110001000001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + - CAND: + encoding: 0b1000110001100001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + - CJ: + encoding: 0b1010000000000001 + mask: 0b1110000000000011 + attributes: [[name:no_cont]] + size: 16 + branch: true + delay: 1 + - CBEQZ: + encoding: 0b1100000000000001 + mask: 0b1110000000000011 + attributes: [[name:no_cont], [name:cond]] + size: 16 + branch: true + delay: [1,1] + - CBNEZ: + encoding: 0b1110000000000001 + mask: 0b1110000000000011 + attributes: [[name:no_cont], [name:cond]] + size: 16 + branch: true + delay: [1,1] + - CSLLI: + encoding: 0b0000000000000010 + mask: 0b1111000000000011 + size: 16 + branch: false + delay: 1 + - CLWSP: + encoding: 0b0100000000000010 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + - CMV: + encoding: 0b1000000000000010 + mask: 0b1111000000000011 + size: 16 + branch: false + delay: 1 + - CJR: + encoding: 0b1000000000000010 + mask: 0b1111000001111111 + attributes: [[name:no_cont]] + size: 16 + branch: true + delay: 1 + - CADD: + encoding: 0b1001000000000010 + mask: 0b1111000000000011 + size: 16 + branch: false + delay: 1 + - CJALR: + encoding: 0b1001000000000010 + mask: 0b1111000001111111 + attributes: [[name:no_cont]] + size: 16 + branch: true + delay: 1 + - CEBREAK: + encoding: 0b1001000000000010 + mask: 0b1111111111111111 + attributes: [[name:no_cont]] + size: 16 + branch: false + delay: 1 + - CSWSP: + encoding: 0b1100000000000010 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + - DII: + encoding: 0b0000000000000000 + mask: 0b1111111111111111 + attributes: [[name:no_cont]] + size: 16 + branch: false + delay: 1 + From a32c83e1be3e65d73e2b8a346db721a891401acf Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 5 Jul 2023 08:32:05 +0200 Subject: [PATCH 109/184] fixes CLI handling of plugin paramters in ISS --- CMakeLists.txt | 14 +++++++++----- src/main.cpp | 16 ++++++++++------ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c5d2d5..2a36dad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,11 +40,15 @@ set(LIB_SOURCES if(TARGET ${CORE_NAME}_cpp) list(APPEND LIB_SOURCES ${${CORE_NAME}_OUTPUT_FILES}) else() - FILE(GLOB GEN_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp - ) - list(APPEND LIB_SOURCES ${GEN_SOURCES}) + FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp) + FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp) + list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES}) + foreach(FILEPATH ${GEN_ISS_SOURCES}) + get_filename_component(CORE ${FILEPATH} NAME_WE) + string(TOUPPER ${CORE} CORE) + list(APPEND LIB_DEFINES CORE_${CORE}) + endforeach() + message("Defines are ${LIB_DEFINES}") endif() if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON) diff --git a/src/main.cpp b/src/main.cpp index a3999ad..5aeb3f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,6 +31,8 @@ *******************************************************************************/ #include +#include +#include #include "iss/factory.h" #include @@ -170,27 +172,29 @@ int main(int argc, char *argv[]) { if (clim.count("plugin")) { for (std::string const& opt_val : clim["plugin"].as>()) { std::string plugin_name=opt_val; - std::string filename{"cycles.txt"}; + std::string arg{""}; std::size_t found = opt_val.find('='); if (found != std::string::npos) { plugin_name = opt_val.substr(0, found); - filename = opt_val.substr(found + 1, opt_val.size()); + arg = opt_val.substr(found + 1, opt_val.size()); } if (plugin_name == "ic") { - auto *ic_plugin = new iss::plugin::instruction_count(filename); + auto *ic_plugin = new iss::plugin::instruction_count(arg); vm->register_plugin(*ic_plugin); plugin_list.push_back(ic_plugin); } else if (plugin_name == "ce") { - auto *ce_plugin = new iss::plugin::cycle_estimate(filename); + auto *ce_plugin = new iss::plugin::cycle_estimate(arg); vm->register_plugin(*ce_plugin); plugin_list.push_back(ce_plugin); } else if (plugin_name == "pctrace") { - auto *plugin = new iss::plugin::pctrace(filename); + auto *plugin = new iss::plugin::pctrace(arg); vm->register_plugin(*plugin); plugin_list.push_back(plugin); } else { #ifndef WIN32 - std::array a{{filename.c_str()}}; + std::vector a{}; + if(arg.length()) + a.push_back({arg.c_str()}); iss::plugin::loader l(plugin_name, {{"initPlugin"}}); auto* plugin = l.call_function("initPlugin", a.size(), a.data()); if(plugin){ From 2b094c31620e5108a35e45d81582d56e8f2c9153 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 6 Jul 2023 10:39:59 +0200 Subject: [PATCH 110/184] removes trace compass nature --- .project | 1 - 1 file changed, 1 deletion(-) diff --git a/.project b/.project index 84a8200..395ef36 100644 --- a/.project +++ b/.project @@ -23,6 +23,5 @@ org.eclipse.cdt.core.ccnature org.eclipse.cdt.managedbuilder.core.managedBuildNature org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - org.eclipse.linuxtools.tmf.project.nature From 21d3250e1a138f8da55a22e9065643e2c3a7628d Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sun, 9 Jul 2023 16:53:59 +0200 Subject: [PATCH 111/184] changes templates --- gen_input/templates/CORENAME.h.gtl | 7 +------ gen_input/templates/interp/CORENAME.cpp.gtl | 2 -- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 9c8082e..83fb8e1 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -30,8 +30,6 @@ * *******************************************************************************/ <% -import com.minres.coredsl.util.BigIntegerWithRadix - def nativeTypeSize(int size){ if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; } @@ -57,10 +55,7 @@ def byteSize(int size){ return 128; } def getCString(def val){ - if(val instanceof BigIntegerWithRadix) - return ((BigIntegerWithRadix)val).toCString() - else - return val.toString() + return val.toString() } %> #ifndef _${coreDef.name.toUpperCase()}_H_ diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index ef645bf..acf7afd 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -30,8 +30,6 @@ * *******************************************************************************/ <% -import com.minres.coredsl.util.BigIntegerWithRadix - def nativeTypeSize(int size){ if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; } From 7b31b8ca8ef48a7614eb21008d764e3003c82795 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sun, 9 Jul 2023 16:58:47 +0200 Subject: [PATCH 112/184] adds updated generated files --- src/iss/arch/tgc_c.h | 2 +- src/vm/interp/vm_tgc_c.cpp | 131 ++++++++++++++-------------- src/vm/tcc/vm_tgc_c.cpp | 171 +++++++++++++++++++------------------ 3 files changed, 153 insertions(+), 151 deletions(-) diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index 2b0c9bc..f0d53f3 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -53,7 +53,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; - enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, PGMASK=0b111111111111, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; + enum constants {MISA_VAL=1073746180, MARCHID_VAL=2147483651, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; constexpr static unsigned FP_REGS_SIZE = 0; diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index e59d80d..c94b716 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -389,7 +389,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *PC + (int32_t)imm; + *(X+rd) = (uint32_t)(*PC + (int32_t)imm); } } } @@ -419,9 +419,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *PC + 4; + *(X+rd) = (uint32_t)(*PC + 4); } - *NEXT_PC = *PC + (int32_t)sext<21>(imm); + *NEXT_PC = (uint32_t)(*PC + (int32_t)sext<21>(imm)); this->core.reg.last_branch = 1; } } @@ -448,13 +448,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t new_pc = (*(X+rs1) + (int16_t)sext<12>(imm)) & ~ 0x1; + uint32_t new_pc = (uint32_t)((*(X+rs1) + (int16_t)sext<12>(imm)) & ~ 0x1); if(new_pc % traits::INSTR_ALIGNMENT) { raise(0, 0); } else { if(rd != 0) { - *(X+rd) = *PC + 4; + *(X+rd) = (uint32_t)(*PC + 4); } *NEXT_PC = new_pc & ~ 0x1; this->core.reg.last_branch = 1; @@ -488,7 +488,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 0); } else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); this->core.reg.last_branch = 1; } } @@ -521,7 +521,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 0); } else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); this->core.reg.last_branch = 1; } } @@ -554,7 +554,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 0); } else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); this->core.reg.last_branch = 1; } } @@ -587,7 +587,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 0); } else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); this->core.reg.last_branch = 1; } } @@ -620,7 +620,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 0); } else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); this->core.reg.last_branch = 1; } } @@ -653,7 +653,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 0); } else { - *NEXT_PC = *PC + (int16_t)sext<13>(imm); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); this->core.reg.last_branch = 1; } } @@ -681,7 +681,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); int8_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LB; int8_t res = (int8_t)read_res; @@ -712,7 +712,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); int16_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LH; int16_t res = (int16_t)read_res; @@ -743,7 +743,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); int32_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LW; int32_t res = (int32_t)read_res; @@ -774,10 +774,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); uint8_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LBU; - uint8_t res = (uint8_t)read_res; + uint8_t res = read_res; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -805,10 +805,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t load_address = *(X+rs1) + (int16_t)sext<12>(imm); + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); uint16_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LHU; - uint16_t res = (uint16_t)read_res; + uint16_t res = read_res; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -836,8 +836,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, (int8_t)*(X+rs2)); + uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + super::template write_mem(traits::MEM, store_address, (uint8_t)*(X+rs2)); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SB; } } @@ -863,8 +863,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, (int16_t)*(X+rs2)); + uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + super::template write_mem(traits::MEM, store_address, (uint16_t)*(X+rs2)); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SH; } } @@ -890,8 +890,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t store_address = *(X+rs1) + (int16_t)sext<12>(imm); - super::template write_mem(traits::MEM, store_address, (int32_t)*(X+rs2)); + uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + super::template write_mem(traits::MEM, store_address, (uint32_t)*(X+rs2)); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SW; } } @@ -918,7 +918,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1) + (int16_t)sext<12>(imm); + *(X+rd) = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); } } } @@ -1134,7 +1134,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = (int32_t)*(X+rs1) >> shamt; + *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> shamt); } } } @@ -1161,7 +1161,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1) + *(X+rs2); + *(X+rd) = (uint32_t)(*(X+rs1) + *(X+rs2)); } } } @@ -1188,7 +1188,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rs1) - *(X+rs2); + *(X+rd) = (uint32_t)(*(X+rs1) - *(X+rs2)); } } } @@ -1350,7 +1350,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = (int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); + *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1))); } } } @@ -1427,7 +1427,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - super::template write_mem(traits::FENCE, traits::fence, pred << 4 | succ); + super::template write_mem(traits::FENCE, traits::fence, (uint8_t)pred << 4 | succ); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE; } TRAP_FENCE:break; @@ -1706,7 +1706,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 4; // execute instruction { - super::template write_mem(traits::FENCE, traits::fencei, imm); + super::template write_mem(traits::FENCE, traits::fencei, imm); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE_I; } TRAP_FENCE_I:break; @@ -1731,7 +1731,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - int64_t res = (int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2); + int64_t res = (int32_t)*(X+rs1) * (int32_t)*(X+rs2); if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -1759,7 +1759,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - int64_t res = (int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2); + int64_t res = (int32_t)*(X+rs1) * (int32_t)*(X+rs2); if(rd != 0) { *(X+rd) = (uint32_t)(res >> traits::XLEN); } @@ -1787,7 +1787,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - int64_t res = (int64_t)(int32_t)*(X+rs1) * (uint64_t)*(X+rs2); + int64_t res = (int32_t)*(X+rs1) * *(X+rs2); if(rd != 0) { *(X+rd) = (uint32_t)(res >> traits::XLEN); } @@ -1815,7 +1815,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint64_t res = (uint64_t)*(X+rs1) * (uint64_t)*(X+rs2); + uint64_t res = *(X+rs1) * *(X+rs2); if(rd != 0) { *(X+rd) = (uint32_t)(res >> traits::XLEN); } @@ -1852,11 +1852,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *(X+rd) = MMIN; } else { - *(X+rd) = dividend / divisor; + *(X+rd) = (uint32_t)(dividend / divisor); } } else { - *(X+rd) = (int32_t)- 1; + *(X+rd) = (uint32_t)- 1; } } } @@ -1885,12 +1885,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { if(*(X+rs2) != 0) { if(rd != 0) { - *(X+rd) = *(X+rs1) / *(X+rs2); + *(X+rd) = (uint32_t)(*(X+rs1) / *(X+rs2)); } } else { if(rd != 0) { - *(X+rd) = (int32_t)- 1; + *(X+rd) = (uint32_t)- 1; } } } @@ -1926,7 +1926,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = (int32_t)*(X+rs1) % (int32_t)*(X+rs2); + *(X+rd) = (uint32_t)((int32_t)*(X+rs1) % (int32_t)*(X+rs2)); } } } @@ -1980,7 +1980,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } // used registers @@ -1989,7 +1989,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if(imm) { - *(X+rd + 8) = *(X+2) + imm; + *(X+rd + 8) = (uint32_t)(*(X+2) + imm); } else { raise(0, 2); @@ -2013,10 +2013,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint32_t load_address = *(X+rs1 + 8) + uimm; + uint32_t load_address = (uint32_t)(*(X+rs1 + 8) + uimm); int32_t read_res = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLW; - *(X+rd + 8) = (int32_t)read_res; + *(X+rd + 8) = (uint32_t)(int32_t)read_res; } TRAP_CLW:break; }// @suppress("No break at end of case") @@ -2036,8 +2036,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint32_t load_address = *(X+rs1 + 8) + uimm; - super::template write_mem(traits::MEM, load_address, (int32_t)*(X+rs2 + 8)); + uint32_t load_address = (uint32_t)(*(X+rs1 + 8) + uimm); + super::template write_mem(traits::MEM, load_address, (uint32_t)*(X+rs2 + 8)); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSW; } TRAP_CSW:break; @@ -2062,7 +2062,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rs1 != 0) { - *(X+rs1) = *(X+rs1) + (int8_t)sext<6>(imm); + *(X+rs1) = (uint32_t)(*(X+rs1) + (int8_t)sext<6>(imm)); } } } @@ -2095,8 +2095,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - *(X+1) = *PC + 2; - *NEXT_PC = *PC + (int16_t)sext<12>(imm); + *(X+1) = (uint32_t)(*PC + 2); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); this->core.reg.last_branch = 1; } TRAP_CJAL:break; @@ -2121,7 +2121,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = (int8_t)sext<6>(imm); + *(X+rd) = (uint32_t)((int8_t)sext<6>(imm)); } } } @@ -2146,7 +2146,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } if(rd != 0) { - *(X+rd) = (int32_t)sext<18>(imm); + *(X+rd) = (uint32_t)((int32_t)sext<18>(imm)); } } TRAP_CLUI:break; @@ -2166,7 +2166,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if(nzimm) { - *(X+2) = *(X+2) + (int16_t)sext<10>(nzimm); + *(X+2) = (uint32_t)(*(X+2) + (int16_t)sext<10>(nzimm)); } else { raise(0, 2); @@ -2223,11 +2223,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if(shamt) { - *(X+rs1 + 8) = ((int32_t)*(X+rs1 + 8)) >> shamt; + *(X+rs1 + 8) = (uint32_t)(((int32_t)*(X+rs1 + 8)) >> shamt); } else { if(traits::XLEN == 128) { - *(X+rs1 + 8) = ((int32_t)*(X+rs1 + 8)) >> 64; + *(X+rs1 + 8) = (uint32_t)(((int32_t)*(X+rs1 + 8)) >> 64); } } } @@ -2248,7 +2248,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - *(X+rs1 + 8) = *(X+rs1 + 8) & (int8_t)sext<6>(imm); + *(X+rs1 + 8) = (uint32_t)(*(X+rs1 + 8) & (int8_t)sext<6>(imm)); } TRAP_CANDI:break; }// @suppress("No break at end of case") @@ -2267,7 +2267,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - *(X+rd + 8) = *(X+rd + 8) - *(X+rs2 + 8); + *(X+rd + 8) = (uint32_t)(*(X+rd + 8) - *(X+rs2 + 8)); } TRAP_CSUB:break; }// @suppress("No break at end of case") @@ -2341,7 +2341,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - *NEXT_PC = *PC + (int16_t)sext<12>(imm); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); this->core.reg.last_branch = 1; } TRAP_CJ:break; @@ -2362,7 +2362,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if(*(X+rs1 + 8) == 0) { - *NEXT_PC = *PC + (int16_t)sext<9>(imm); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); this->core.reg.last_branch = 1; } } @@ -2384,7 +2384,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if(*(X+rs1 + 8) != 0) { - *NEXT_PC = *PC + (int16_t)sext<9>(imm); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); this->core.reg.last_branch = 1; } } @@ -2435,10 +2435,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - int32_t read_res = super::template read_mem(traits::MEM, *(X+2) + uimm); + uint32_t offs = (uint32_t)(*(X+2) + uimm); + int32_t read_res = super::template read_mem(traits::MEM, offs); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLWSP; - int32_t res = read_res; - *(X+rd) = (int32_t)res; + int32_t res = (int32_t)read_res; + *(X+rd) = (uint32_t)res; } } TRAP_CLWSP:break; @@ -2526,7 +2527,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(rd != 0) { - *(X+rd) = *(X+rd) + *(X+rs2); + *(X+rd) = (uint32_t)(*(X+rd) + *(X+rs2)); } } } @@ -2551,7 +2552,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t new_pc = *(X+rs1); - *(X+1) = *PC + 2; + *(X+1) = (uint32_t)(*PC + 2); *NEXT_PC = new_pc & ~ 0x1; this->core.reg.last_branch = 1; } @@ -2590,7 +2591,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t offs = *(X+2) + uimm; + uint32_t offs = (uint32_t)(*(X+2) + uimm); super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2)); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSWSP; } diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index f47fb28..495d97e 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -423,7 +423,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)imm,32))); + tu.store(rd + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)imm,32))),32,true)); } } auto returnValue = std::make_tuple(CONT); @@ -458,9 +458,9 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 4,32))); + tu.store(rd + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 4,8))),32,true)); } - auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)sext<21>(imm),32)),32); + auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)sext<21>(imm),32))),32,true),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -494,12 +494,12 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto new_pc = tu.assignment(tu.bitwise_and((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),tu.constant(~ 0x1,8)),32); + auto new_pc = tu.assignment(tu.ext((tu.bitwise_and((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),tu.constant(~ 0x1,8))),32,true),32); tu.open_if(tu.srem(new_pc,tu.constant(static_cast(traits:: INSTR_ALIGNMENT),32))); this->gen_raise_trap(tu, 0, 0); tu.open_else(); if(rd!= 0) { - tu.store(rd + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 4,32))); + tu.store(rd + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 4,8))),32,true)); } auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); @@ -539,7 +539,7 @@ private: if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -578,7 +578,7 @@ private: if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -617,7 +617,7 @@ private: if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -656,7 +656,7 @@ private: if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -695,7 +695,7 @@ private: if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -734,7 +734,7 @@ private: if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16)),32); + auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -769,7 +769,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 8),8,false),8); if(rd!= 0) { tu.store(rd + traits::X0,tu.ext(res,32,true)); @@ -804,7 +804,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 16),16,false),16); if(rd!= 0) { tu.store(rd + traits::X0,tu.ext(res,32,true)); @@ -839,7 +839,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,false),32); if(rd!= 0) { tu.store(rd + traits::X0,tu.ext(res,32,true)); @@ -874,8 +874,8 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); - auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 8),8,true),8); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); + auto res = tu.assignment(tu.read_mem(traits::MEM, load_address, 8),8); if(rd!= 0) { tu.store(rd + traits::X0,tu.ext(res,32,true)); } @@ -909,8 +909,8 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); - auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 16),16,true),16); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); + auto res = tu.assignment(tu.read_mem(traits::MEM, load_address, 16),16); if(rd!= 0) { tu.store(rd + traits::X0,tu.ext(res,32,true)); } @@ -944,8 +944,8 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); - tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),8,false)); + auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),8,true)); } auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -976,8 +976,8 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); - tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),16,false)); + auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),16,true)); } auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -1008,8 +1008,8 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto store_address = tu.assignment(tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16)),32); - tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),32,false)); + auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),32,true)); } auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -1041,7 +1041,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))); + tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true)); } } auto returnValue = std::make_tuple(CONT); @@ -1074,7 +1074,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant((int16_t)sext<12>(imm),16))), tu.constant( 1,32),tu.constant( 0,32))); + tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant((int16_t)sext<12>(imm),16))), tu.constant( 1,8),tu.constant( 0,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1107,7 +1107,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))), tu.constant( 1,32),tu.constant( 0,32))); + tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))), tu.constant( 1,8),tu.constant( 0,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1305,7 +1305,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant(shamt,8))); + tu.store(rd + traits::X0,tu.ext((tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant(shamt,8))),32,true)); } } auto returnValue = std::make_tuple(CONT); @@ -1338,7 +1338,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,true)); } } auto returnValue = std::make_tuple(CONT); @@ -1371,7 +1371,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.sub(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.store(rd + traits::X0,tu.ext((tu.sub(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,true)); } } auto returnValue = std::make_tuple(CONT); @@ -1437,7 +1437,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true)), tu.constant( 1,32),tu.constant( 0,32))); + tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true)), tu.constant( 1,8),tu.constant( 0,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1470,7 +1470,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0)), tu.constant( 1,32),tu.constant( 0,32))); + tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0)), tu.constant( 1,8),tu.constant( 0,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1569,7 +1569,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); + tu.store(rd + traits::X0,tu.ext((tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))),32,true)); } } auto returnValue = std::make_tuple(CONT); @@ -1665,7 +1665,7 @@ private: pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.write_mem(traits::MEM, static_cast(traits:: fence), tu.constant(pred<< 4|succ,8)); + tu.write_mem(traits::FENCE, static_cast(traits:: fence), tu.constant((uint8_t)pred<< 4|succ,8)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,37); @@ -1777,11 +1777,11 @@ private: else{ auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); if(rd!= 0){ auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); - tu.write_mem(traits::MEM, csr, xrs1); + tu.write_mem(traits::CSR, csr, xrs1); tu.store(rd + traits::X0,xrd); } else{ - tu.write_mem(traits::MEM, csr, xrs1); + tu.write_mem(traits::CSR, csr, xrs1); } } auto returnValue = std::make_tuple(CONT); @@ -1816,7 +1816,7 @@ private: auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); if(rs1!= 0) { - tu.write_mem(traits::MEM, csr, tu.bitwise_or(xrd,xrs1)); + tu.write_mem(traits::CSR, csr, tu.bitwise_or(xrd,xrs1)); } if(rd!= 0) { tu.store(rd + traits::X0,xrd); @@ -1854,7 +1854,7 @@ private: auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); if(rs1!= 0) { - tu.write_mem(traits::MEM, csr, tu.bitwise_and(xrd,tu.logical_neg(xrs1))); + tu.write_mem(traits::CSR, csr, tu.bitwise_and(xrd,tu.logical_neg(xrs1))); } if(rd!= 0) { tu.store(rd + traits::X0,xrd); @@ -1890,7 +1890,7 @@ private: } else{ auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); - tu.write_mem(traits::MEM, csr, tu.constant((uint32_t)zimm,32)); + tu.write_mem(traits::CSR, csr, tu.constant((uint32_t)zimm,32)); if(rd!= 0) { tu.store(rd + traits::X0,xrd); } @@ -1926,7 +1926,7 @@ private: else{ auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); if(zimm!= 0) { - tu.write_mem(traits::MEM, csr, tu.bitwise_or(xrd,tu.constant((uint32_t)zimm,32))); + tu.write_mem(traits::CSR, csr, tu.bitwise_or(xrd,tu.constant((uint32_t)zimm,32))); } if(rd!= 0) { tu.store(rd + traits::X0,xrd); @@ -1963,7 +1963,7 @@ private: else{ auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); if(zimm!= 0) { - tu.write_mem(traits::MEM, csr, tu.bitwise_and(xrd,tu.constant(~ ((uint32_t)zimm),32))); + tu.write_mem(traits::CSR, csr, tu.bitwise_and(xrd,tu.constant(~ ((uint32_t)zimm),32))); } if(rd!= 0) { tu.store(rd + traits::X0,xrd); @@ -1994,7 +1994,7 @@ private: pc=pc+ 4; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.write_mem(traits::MEM, static_cast(traits:: fencei), tu.constant(imm,16)); + tu.write_mem(traits::FENCE, static_cast(traits:: fencei), tu.constant(imm,16)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,48); @@ -2024,7 +2024,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false)),64); + auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false)),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext(res,32,true)); } @@ -2058,7 +2058,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false)),64); + auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false)),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } @@ -2092,7 +2092,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.load(rs2+ traits::X0, 0),64,true)),64); + auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.load(rs2+ traits::X0, 0)),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } @@ -2126,7 +2126,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),64,true),tu.ext(tu.load(rs2+ traits::X0, 0),64,true)),64); + auto res = tu.assignment(tu.mul(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0)),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } @@ -2162,15 +2162,15 @@ private: else{ auto dividend = tu.assignment(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),32); auto divisor = tu.assignment(tu.ext(tu.load(rs2+ traits::X0, 0),32,false),32); - if(rd!= 0){ tu.open_if(tu.icmp(ICmpInst::ICMP_NE,divisor,tu.constant( 0,32))); + if(rd!= 0){ tu.open_if(tu.icmp(ICmpInst::ICMP_NE,divisor,tu.constant( 0,8))); auto MMIN = tu.assignment(tu.constant(((uint32_t)1)<<(static_cast(traits:: XLEN)-1),32),32); - tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,divisor,tu.constant(- 1,32)))); + tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,divisor,tu.constant(- 1,8)))); tu.store(rd + traits::X0,MMIN); tu.open_else(); - tu.store(rd + traits::X0,tu.sdiv(dividend,divisor)); + tu.store(rd + traits::X0,tu.ext((tu.sdiv(dividend,divisor)),32,true)); tu.close_scope(); tu.open_else(); - tu.store(rd + traits::X0,tu.constant((int32_t)- 1,32)); + tu.store(rd + traits::X0,tu.constant((uint32_t)- 1,32)); tu.close_scope(); } } @@ -2203,13 +2203,13 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,32))); + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,8))); if(rd!=0) { - tu.store(rd + traits::X0,tu.sdiv(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.store(rd + traits::X0,tu.ext((tu.sdiv(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,true)); } tu.open_else(); if(rd!=0) { - tu.store(rd + traits::X0,tu.constant((int32_t)- 1,32)); + tu.store(rd + traits::X0,tu.constant((uint32_t)- 1,32)); } tu.close_scope(); } @@ -2242,15 +2242,15 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,32))); - auto MMIN = tu.assignment(tu.constant( 1<<(static_cast(traits:: XLEN)-1),32),32); - tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,tu.ext(tu.load(rs2+ traits::X0, 0),32,false),tu.constant(- 1,32)))); + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,8))); + auto MMIN = tu.assignment(tu.constant( 1<<(static_cast(traits:: XLEN)-1),8),32); + tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,tu.ext(tu.load(rs2+ traits::X0, 0),32,false),tu.constant(- 1,8)))); if(rd!=0) { - tu.store(rd + traits::X0,tu.constant( 0,32)); + tu.store(rd + traits::X0,tu.constant( 0,8)); } tu.open_else(); if(rd!=0) { - tu.store(rd + traits::X0,tu.srem(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false))); + tu.store(rd + traits::X0,tu.ext((tu.srem(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false))),32,true)); } tu.close_scope(); tu.open_else(); @@ -2288,7 +2288,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,32))); + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,8))); if(rd!=0) { tu.store(rd + traits::X0,tu.srem(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); } @@ -2315,7 +2315,7 @@ private: /* generate console output when executing the command */ auto mnemonic = fmt::format( "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); @@ -2323,7 +2323,7 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(imm) { - tu.store(rd+ 8 + traits::X0,tu.add(tu.load(2+ traits::X0, 0),tu.constant(imm,8))); + tu.store(rd+ 8 + traits::X0,tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(imm,8))),32,true)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -2353,8 +2353,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto load_address = tu.assignment(tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8)),32); - tu.store(rd+ 8 + traits::X0,tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,false)); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); + tu.store(rd+ 8 + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,false),32,true)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,58); @@ -2380,8 +2380,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto load_address = tu.assignment(tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8)),32); - tu.write_mem(traits::MEM, load_address, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,false)); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); + tu.write_mem(traits::MEM, load_address, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,true)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,59); @@ -2411,7 +2411,7 @@ private: } else{ if(rs1!= 0) { - tu.store(rs1 + traits::X0,tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))); + tu.store(rs1 + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))),32,true)); } } auto returnValue = std::make_tuple(CONT); @@ -2457,8 +2457,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); - auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); + tu.store(1 + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,8))),32,true)); + auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); auto returnValue = std::make_tuple(BRANCH); @@ -2490,7 +2490,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.constant((int8_t)sext<6>(imm),8)); + tu.store(rd + traits::X0,tu.constant((uint32_t)((int8_t)sext<6>(imm)),32)); } } auto returnValue = std::make_tuple(CONT); @@ -2521,7 +2521,7 @@ private: this->gen_raise_trap(tu, 0, 2); } if(rd!= 0) { - tu.store(rd + traits::X0,tu.constant((int32_t)sext<18>(imm),32)); + tu.store(rd + traits::X0,tu.constant((uint32_t)((int32_t)sext<18>(imm)),32)); } auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2547,7 +2547,7 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(nzimm) { - tu.store(2 + traits::X0,tu.add(tu.load(2+ traits::X0, 0),tu.constant((int16_t)sext<10>(nzimm),16))); + tu.store(2 + traits::X0,tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant((int16_t)sext<10>(nzimm),16))),32,true)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -2622,10 +2622,10 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - if(shamt){ tu.store(rs1+ 8 + traits::X0,tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant(shamt,8))); + if(shamt){ tu.store(rs1+ 8 + traits::X0,tu.ext((tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant(shamt,8))),32,true)); } else{ - if(static_cast(traits:: XLEN)== 128){ tu.store(rs1+ 8 + traits::X0,tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant( 64,32))); + if(static_cast(traits:: XLEN)== 128){ tu.store(rs1+ 8 + traits::X0,tu.ext((tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant( 64,8))),32,true)); } } auto returnValue = std::make_tuple(CONT); @@ -2652,7 +2652,7 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(rs1+ 8 + traits::X0,tu.bitwise_and(tu.load(rs1+ 8+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))); + tu.store(rs1+ 8 + traits::X0,tu.ext((tu.bitwise_and(tu.load(rs1+ 8+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))),32,true)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,69); @@ -2677,7 +2677,7 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(rd+ 8 + traits::X0,tu.sub(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); + tu.store(rd+ 8 + traits::X0,tu.ext((tu.sub(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))),32,true)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,70); @@ -2776,7 +2776,7 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16)),32); + auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); auto returnValue = std::make_tuple(BRANCH); @@ -2803,8 +2803,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); - auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); + tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,8))); + auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16))),32,true),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); @@ -2832,8 +2832,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,32))); - auto PC_val_v = tu.assignment("PC_val", tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16)),32); + tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,8))); + auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16))),32,true),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); @@ -2897,8 +2897,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.read_mem(traits::MEM, tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8)), 32),32); - tu.store(rd + traits::X0,tu.ext(res,32,false)); + auto offs = tu.assignment(tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32); + tu.store(rd + traits::X0,tu.ext(res,32,true)); } auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -3012,7 +3013,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.add(tu.load(rd+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rd+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,true)); } } auto returnValue = std::make_tuple(CONT); @@ -3043,7 +3044,7 @@ private: } else{ auto new_pc = tu.assignment(tu.load(rs1+ traits::X0, 0),32); - tu.store(1 + traits::X0,tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,32))); + tu.store(1 + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,8))),32,true)); auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); @@ -3096,7 +3097,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto offs = tu.assignment(tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8)),32); + auto offs = tu.assignment(tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ traits::X0, 0),32,true)); } auto returnValue = std::make_tuple(CONT); From 250ea3c980772ae7dd33c9082575c5d32a38f6fa Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 6 Jul 2023 08:02:48 +0200 Subject: [PATCH 113/184] extends factory to support SystemC core wrapper --- CMakeLists.txt | 5 +- gen_input/templates/CORENAME.h.gtl | 2 +- gen_input/templates/interp/CORENAME.cpp.gtl | 30 +++- gen_input/templates/tcc/CORENAME.cpp.gtl | 30 +++- src/iss/arch/tgc_c.h | 2 +- src/iss/factory.h | 48 +++++++ src/main.cpp | 59 ++------ src/sysc/register_tgc_c.cpp | 33 +++++ src/sysc/sc_core_adapter.h | 148 ++++++++++++++++++++ src/vm/interp/vm_tgc_c.cpp | 49 +++++-- src/vm/tcc/vm_tgc_c.cpp | 49 +++++-- 11 files changed, 380 insertions(+), 75 deletions(-) create mode 100644 src/sysc/register_tgc_c.cpp create mode 100644 src/sysc/sc_core_adapter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a36dad..c79d882 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,7 +186,10 @@ install(TARGETS tgc-sim ############################################################################### if(TARGET scc-sysc) project(dbt-rise-tgc_sc VERSION 1.0.0) - add_library(${PROJECT_NAME} src/sysc/core_complex.cpp) + add_library(${PROJECT_NAME} + src/sysc/core_complex.cpp + src/sysc/register_tgc_c.cpp + ) target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC) target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) foreach(F IN LISTS TGC_SOURCES) diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 83fb8e1..45a3ed7 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -111,7 +111,7 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { enum mem_type_e { ${spaces.collect{it.name}.join(', ')} }; - enum class opcode_e : unsigned short {<%instructions.eachWithIndex{instr, index -> %> + enum class opcode_e {<%instructions.eachWithIndex{instr, index -> %> ${instr.instruction.name} = ${index},<%}%> MAX_OPCODE }; diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index acf7afd..cc864d8 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -34,10 +34,9 @@ def nativeTypeSize(int size){ if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; } %> +#include #include #include -#include -#include #include #include #include @@ -315,3 +314,30 @@ std::unique_ptr create(arch::${coreD } } // namespace interp } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +std::array dummy = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} +extern "C" { + bool* get_${coreDef.name.toLowerCase()}_interp_creators() { + return iss::dummy.data(); + } +} \ No newline at end of file diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index b7cec56..afb3e38 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -31,7 +31,6 @@ *******************************************************************************/ #include -#include #include #include #include @@ -310,5 +309,32 @@ std::unique_ptr create(arch::${coreD if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } -} +} // namesapce tcc } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +std::array dummy = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} +extern "C" { + bool* get_${coreDef.name.toLowerCase()}_tcc_creators() { + return iss::dummy.data(); + } +} \ No newline at end of file diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index f0d53f3..611ef79 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -83,7 +83,7 @@ template <> struct traits { enum mem_type_e { MEM, FENCE, RES, CSR }; - enum class opcode_e : unsigned short { + enum class opcode_e { LUI = 0, AUIPC = 1, JAL = 2, diff --git a/src/iss/factory.h b/src/iss/factory.h index 0d43538..7e45838 100644 --- a/src/iss/factory.h +++ b/src/iss/factory.h @@ -34,6 +34,12 @@ #define _ISS_FACTORY_H_ #include +#include +#include +#include +#include +#include +#include namespace iss { @@ -57,6 +63,48 @@ std::tuple create_cpu(std::string const& backend, unsigned gdb_ return {nullptr, nullptr}; } + +class core_factory { + using cpu_ptr = std::unique_ptr; + using vm_ptr= std::unique_ptr; + using base_t = std::tuple; + using create_fn = std::function; + using registry_t = std::unordered_map ; + + registry_t registry; + + core_factory() = default; + core_factory(const core_factory &) = delete; + core_factory & operator=(const core_factory &) = delete; + +public: + static core_factory & instance() { static core_factory bf; return bf; } + + bool register_creator(const std::string &, create_fn const&); + + base_t create(const std::string &, unsigned gdb_port=0, void* init_data=nullptr) const; + + std::vector get_names() { + std::vector keys{registry.size()}; + std::transform(std::begin(registry), std::end(registry), std::begin(keys), [](std::pair const& p){ + return p.first; + }); + return keys; + } +}; + +inline bool core_factory::register_creator(const std::string & className, create_fn const& fn) { + registry[className] = fn; + return true; +} + +inline core_factory::base_t core_factory::create(const std::string &className, unsigned gdb_port, void* data) const { + registry_t::const_iterator regEntry = registry.find(className); + if (regEntry != registry.end()) + return regEntry->second(gdb_port, data); + return {nullptr, nullptr}; +} + } #endif /* _ISS_FACTORY_H_ */ diff --git a/src/main.cpp b/src/main.cpp index 5aeb3f8..02ec210 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,7 +33,7 @@ #include #include #include -#include "iss/factory.h" +#include #include #include @@ -113,53 +113,24 @@ int main(int argc, char *argv[]) { iss::init_jit_debug(argc, argv); #endif bool dump = clim.count("dump-ir"); + auto & f = iss::core_factory::instance(); // instantiate the simulator iss::vm_ptr vm{nullptr}; iss::cpu_ptr cpu{nullptr}; std::string isa_opt(clim["isa"].as()); - if (isa_opt == "tgc_c") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#ifdef CORE_TGC_B - if (isa_opt == "tgc_b") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_C_XRB_NN - if (isa_opt == "tgc_c_xrb_nn") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D - if (isa_opt == "tgc_d") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D_XRB_MAC - if (isa_opt == "tgc_d_xrb_mac") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_D_XRB_NN - if (isa_opt == "tgc_d_xrb_nn") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif -#ifdef CORE_TGC_E - if (isa_opt == "tgc_e") { - std::tie(cpu, vm) = - iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); - } else -#endif - { - LOG(ERR) << "Illegal argument value for '--isa': " << isa_opt << std::endl; - return 127; + if(isa_opt.size()==0 || isa_opt == "?") { + std::cout<<"Available cores: "<(), clim["gdb-port"].as()); + } else { + auto base_isa = isa_opt.substr(0, 5); + if(base_isa=="tgc_d" || base_isa=="tgc_e") { + isa_opt += "|mu_p_clic_pmp|"+clim["backend"].as(); + } else { + isa_opt += "|m_p|"+clim["backend"].as(); + } + std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as()); } if(!cpu ){ LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " <()<< std::endl; diff --git a/src/sysc/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp new file mode 100644 index 0000000..2394afe --- /dev/null +++ b/src/sysc/register_tgc_c.cpp @@ -0,0 +1,33 @@ +/* + * register_tgc_c.cpp + * + * Created on: Jul 5, 2023 + * Author: eyck + */ + + + + +#include +#include +#include +#include +#include "sc_core_adapter.h" +#include "core_complex.h" + +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ + auto cc = reinterpret_cast(data); + arch::tgc_c* lcpu = new sc_core_adapter>(cc); + return {cpu_ptr{lcpu}, vm_ptr{interp::create(lcpu, gdb_port)}}; + }), + core_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ + auto cc = reinterpret_cast(data); + arch::tgc_c* lcpu = new sc_core_adapter>(cc); + return {cpu_ptr{lcpu}, vm_ptr{interp::create(lcpu, gdb_port)}}; + }) +}; +} +} diff --git a/src/sysc/sc_core_adapter.h b/src/sysc/sc_core_adapter.h new file mode 100644 index 0000000..baaa43b --- /dev/null +++ b/src/sysc/sc_core_adapter.h @@ -0,0 +1,148 @@ +/* + * sc_core_adapter.h + * + * Created on: Jul 5, 2023 + * Author: eyck + */ + +#ifndef _SYSC_SC_CORE_ADAPTER_H_ +#define _SYSC_SC_CORE_ADAPTER_H_ + + +#include +#include +#include "core_complex.h" +#include +#include +#include + + +template +class sc_core_adapter : public PLAT { +public: + using reg_t = typename iss::arch::traits::reg_t; + using phys_addr_t = typename iss::arch::traits::phys_addr_t; + using heart_state_t = typename PLAT::hart_state_type; + sc_core_adapter(sysc::tgfs::core_complex *owner) + : owner(owner) { } + + uint32_t get_mode() { return this->reg.PRIV; } + + inline void set_interrupt_execution(bool v) { this->interrupt_sim = v?1:0; } + + inline bool get_interrupt_execution() { return this->interrupt_sim; } + + heart_state_t &get_state() { return this->state; } + + void notify_phase(iss::arch_if::exec_phase p) override { + if (p == iss::arch_if::ISTART) + owner->sync(this->instr_if.get_total_cycles()); + } + + iss::sync_type needed_sync() const override { return iss::PRE_SYNC; } + + void disass_output(uint64_t pc, const std::string instr) override { + static constexpr std::array lvl = {{'U', 'S', 'H', 'M'}}; + if (!owner->disass_output(pc, instr)) { + std::stringstream s; + s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') + << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" + << this->reg.icount + this->cycle_offset << "]"; + SCCDEBUG(owner->name())<<"disass: " + << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) + << std::setfill(' ') << std::left << instr << s.str(); + } + }; + + iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) override { + if (addr.access && iss::access_type::DEBUG) + return owner->read_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; + else { + return owner->read_mem(addr.val, length, data, is_fetch(addr.access)) ? iss::Ok : iss::Err; + } + } + + iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) override { + if (addr.access && iss::access_type::DEBUG) + return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; + else { + auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err; + // clear MTIP on mtimecmp write + if (addr.val == 0x2004000) { + reg_t val; + this->read_csr(iss::arch::mip, val); + if (val & (1ULL << 7)) this->write_csr(iss::arch::mip, val & ~(1ULL << 7)); + } + return res; + } + } + + iss::status read_csr(unsigned addr, reg_t &val) override { +#ifndef CWR_SYSTEMC + if((addr==iss::arch::time || addr==iss::arch::timeh) && owner->mtime_o.get_interface(0)){ + uint64_t time_val; + bool ret = owner->mtime_o->nb_peek(time_val); + if (addr == iss::arch::time) { + val = static_cast(time_val); + } else if (addr == iss::arch::timeh) { + if (sizeof(reg_t) != 4) return iss::Err; + val = static_cast(time_val >> 32); + } + return ret?Ok:Err; +#else + if((addr==iss::arch::time || addr==iss::arch::timeh)){ + uint64_t time_val = owner->mtime_i.read(); + if (addr == iss::arch::time) { + val = static_cast(time_val); + } else if (addr == iss::arch::timeh) { + if (sizeof(reg_t) != 4) return iss::Err; + val = static_cast(time_val >> 32); + } + return iss::Ok; +#endif + } else { + return PLAT::read_csr(addr, val); + } + } + + void wait_until(uint64_t flags) override { + SCCDEBUG(owner->name()) << "Sleeping until interrupt"; + while(this->reg.pending_trap == 0 && (this->csr[iss::arch::mip] & this->csr[iss::arch::mie]) == 0) { + sc_core::wait(wfi_evt); + } + PLAT::wait_until(flags); + } + + void local_irq(short id, bool value) { + reg_t mask = 0; + switch (id) { + case 3: // SW + mask = 1 << 3; + break; + case 7: // timer + mask = 1 << 7; + break; + case 11: // external + mask = 1 << 11; + break; + default: + if(id>15) mask = 1 << id; + break; + } + if (value) { + this->csr[iss::arch::mip] |= mask; + wfi_evt.notify(); + } else + this->csr[iss::arch::mip] &= ~mask; + this->check_interrupt(); + if(value) + SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap; + } + +private: + sysc::tgfs::core_complex *const owner; + sc_event wfi_evt; +}; + + +#endif /* _SYSC_SC_CORE_ADAPTER_H_ */ diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index c94b716..cfda6fe 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -30,10 +30,9 @@ * *******************************************************************************/ +#include #include #include -#include -#include #include #include #include @@ -1731,7 +1730,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - int64_t res = (int32_t)*(X+rs1) * (int32_t)*(X+rs2); + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -1759,7 +1758,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - int64_t res = (int32_t)*(X+rs1) * (int32_t)*(X+rs2); + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); if(rd != 0) { *(X+rd) = (uint32_t)(res >> traits::XLEN); } @@ -1787,7 +1786,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - int64_t res = (int32_t)*(X+rs1) * *(X+rs2); + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (uint64_t)*(X+rs2)); if(rd != 0) { *(X+rd) = (uint32_t)(res >> traits::XLEN); } @@ -1815,7 +1814,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint64_t res = *(X+rs1) * *(X+rs2); + uint64_t res = (uint64_t)((uint64_t)*(X+rs1) * (uint64_t)*(X+rs2)); if(rd != 0) { *(X+rd) = (uint32_t)(res >> traits::XLEN); } @@ -2013,8 +2012,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint32_t load_address = (uint32_t)(*(X+rs1 + 8) + uimm); - int32_t read_res = super::template read_mem(traits::MEM, load_address); + uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); + int32_t read_res = super::template read_mem(traits::MEM, offs); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLW; *(X+rd + 8) = (uint32_t)(int32_t)read_res; } @@ -2036,8 +2035,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co *NEXT_PC = *PC + 2; // execute instruction { - uint32_t load_address = (uint32_t)(*(X+rs1 + 8) + uimm); - super::template write_mem(traits::MEM, load_address, (uint32_t)*(X+rs2 + 8)); + uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 + 8)); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSW; } TRAP_CSW:break; @@ -2438,8 +2437,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co uint32_t offs = (uint32_t)(*(X+2) + uimm); int32_t read_res = super::template read_mem(traits::MEM, offs); if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLWSP; - int32_t res = (int32_t)read_res; - *(X+rd) = (uint32_t)res; + *(X+rd) = (uint32_t)(int32_t)read_res; } } TRAP_CLWSP:break; @@ -2647,3 +2645,30 @@ std::unique_ptr create(arch::tgc_c *core, unsigned short por } } // namespace interp } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +std::array dummy = { + core_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new interp::tgc_c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new interp::tgc_c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} +extern "C" { + bool* get_tgc_c_interp_creators() { + return iss::dummy.data(); + } +} \ No newline at end of file diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index 495d97e..b760efa 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -31,7 +31,6 @@ *******************************************************************************/ #include -#include #include #include #include @@ -2024,7 +2023,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false)),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false))),64,false),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext(res,32,true)); } @@ -2058,7 +2057,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false)),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false))),64,false),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } @@ -2092,7 +2091,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.load(rs2+ traits::X0, 0)),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.load(rs2+ traits::X0, 0),64,true))),64,false),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } @@ -2126,7 +2125,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0)),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),64,true),tu.ext(tu.load(rs2+ traits::X0, 0),64,true))),64,true),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } @@ -2353,8 +2352,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); - tu.store(rd+ 8 + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,false),32,true)); + auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); + tu.store(rd+ 8 + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32,true)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,58); @@ -2380,8 +2379,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); - tu.write_mem(traits::MEM, load_address, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,true)); + auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); + tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,true)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,59); @@ -2898,8 +2897,7 @@ private: } else{ auto offs = tu.assignment(tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); - auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32); - tu.store(rd + traits::X0,tu.ext(res,32,true)); + tu.store(rd + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32,true)); } auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -3220,5 +3218,32 @@ std::unique_ptr create(arch::tgc_c *core, unsigned short por if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } -} +} // namesapce tcc } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +std::array dummy = { + core_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new tcc::tgc_c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("tgc_c|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new tcc::tgc_c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} +extern "C" { + bool* get_tgc_c_tcc_creators() { + return iss::dummy.data(); + } +} \ No newline at end of file From e95f422aabf33b15ae5ff569711f057a115ba9bd Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 9 Jul 2023 20:13:26 +0200 Subject: [PATCH 114/184] cleans vm implementation up --- gen_input/templates/interp/CORENAME.cpp.gtl | 7 +------ gen_input/templates/tcc/CORENAME.cpp.gtl | 7 +------ src/vm/interp/vm_tgc_c.cpp | 8 ++------ src/vm/tcc/vm_tgc_c.cpp | 7 +------ 4 files changed, 5 insertions(+), 24 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index cc864d8..cd84028 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -320,7 +320,7 @@ std::unique_ptr create(arch::${coreD #include namespace iss { namespace { -std::array dummy = { +volatile std::array dummy = { core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_m_p(); auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); @@ -336,8 +336,3 @@ std::array dummy = { }; } } -extern "C" { - bool* get_${coreDef.name.toLowerCase()}_interp_creators() { - return iss::dummy.data(); - } -} \ No newline at end of file diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index afb3e38..f7a2baf 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -317,7 +317,7 @@ std::unique_ptr create(arch::${coreD #include namespace iss { namespace { -std::array dummy = { +volatile std::array dummy = { core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_m_p(); auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); @@ -333,8 +333,3 @@ std::array dummy = { }; } } -extern "C" { - bool* get_${coreDef.name.toLowerCase()}_tcc_creators() { - return iss::dummy.data(); - } -} \ No newline at end of file diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index cfda6fe..d1e6596 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -2651,7 +2651,7 @@ std::unique_ptr create(arch::tgc_c *core, unsigned short por #include namespace iss { namespace { -std::array dummy = { +volatile std::array dummy = { core_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_m_p(); auto vm = new interp::tgc_c::vm_impl(*cpu, false); @@ -2667,8 +2667,4 @@ std::array dummy = { }; } } -extern "C" { - bool* get_tgc_c_interp_creators() { - return iss::dummy.data(); - } -} \ No newline at end of file + diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index b760efa..8027571 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -3226,7 +3226,7 @@ std::unique_ptr create(arch::tgc_c *core, unsigned short por #include namespace iss { namespace { -std::array dummy = { +volatile std::array dummy = { core_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_m_p(); auto vm = new tcc::tgc_c::vm_impl(*cpu, false); @@ -3242,8 +3242,3 @@ std::array dummy = { }; } } -extern "C" { - bool* get_tgc_c_tcc_creators() { - return iss::dummy.data(); - } -} \ No newline at end of file From 1cef7de8c7f61331f4456f468d1cb7469bff813b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 9 Jul 2023 20:15:12 +0200 Subject: [PATCH 115/184] fixes missing namespaces --- src/sysc/sc_core_adapter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sysc/sc_core_adapter.h b/src/sysc/sc_core_adapter.h index baaa43b..9544765 100644 --- a/src/sysc/sc_core_adapter.h +++ b/src/sysc/sc_core_adapter.h @@ -88,7 +88,7 @@ public: if (sizeof(reg_t) != 4) return iss::Err; val = static_cast(time_val >> 32); } - return ret?Ok:Err; + return ret?iss::Ok:iss::Err; #else if((addr==iss::arch::time || addr==iss::arch::timeh)){ uint64_t time_val = owner->mtime_i.read(); @@ -141,7 +141,7 @@ public: private: sysc::tgfs::core_complex *const owner; - sc_event wfi_evt; + sc_core::sc_event wfi_evt; }; From 145a0cf68b848b32a2916ea295a461e9ceb7daaf Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 9 Jul 2023 20:24:45 +0200 Subject: [PATCH 116/184] updates registration of cores for sysc --- CMakeLists.txt | 2 +- src/sysc/register_tgc_c.cpp | 58 ++++++++++++++++++++++++++++--------- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c79d882..b269918 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,7 +48,7 @@ else() string(TOUPPER ${CORE} CORE) list(APPEND LIB_DEFINES CORE_${CORE}) endforeach() - message("Defines are ${LIB_DEFINES}") + message("Core defines are ${LIB_DEFINES}") endif() if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON) diff --git a/src/sysc/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp index 2394afe..8d86788 100644 --- a/src/sysc/register_tgc_c.cpp +++ b/src/sysc/register_tgc_c.cpp @@ -1,12 +1,34 @@ -/* - * register_tgc_c.cpp +/******************************************************************************* + * Copyright (C) 2023 MINRES Technologies GmbH + * All rights reserved. * - * Created on: Jul 5, 2023 - * Author: eyck - */ - - - + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ #include #include @@ -17,16 +39,26 @@ namespace iss { namespace { -volatile std::array dummy = { +volatile std::array dummy = { core_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); - arch::tgc_c* lcpu = new sc_core_adapter>(cc); - return {cpu_ptr{lcpu}, vm_ptr{interp::create(lcpu, gdb_port)}}; + arch::tgc_c* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{interp::create(cpu, gdb_port)}}; }), core_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); - arch::tgc_c* lcpu = new sc_core_adapter>(cc); - return {cpu_ptr{lcpu}, vm_ptr{interp::create(lcpu, gdb_port)}}; + arch::tgc_c* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{interp::create(cpu, gdb_port)}}; + }), + core_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + auto cc = reinterpret_cast(data); + arch::tgc_c* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{tcc::create(cpu, gdb_port)}}; + }), + core_factory::instance().register_creator("tgc_c|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + auto cc = reinterpret_cast(data); + arch::tgc_c* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{tcc::create(cpu, gdb_port)}}; }) }; } From b4b03f7850331e03331c3bc3dee2672524eb8208 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 9 Jul 2023 22:20:50 +0200 Subject: [PATCH 117/184] fixes build system to handle TCC properly --- CMakeLists.txt | 69 +++---- gen_input/templates/interp/CORENAME.cpp.gtl | 2 +- gen_input/templates/tcc/CORENAME.cpp.gtl | 2 +- src/sysc/core_complex.cpp | 195 +++----------------- src/sysc/register_tgc_c.cpp | 20 +- src/sysc/sc_core_adapter.h | 17 +- src/sysc/sc_core_adapter_if.h | 30 +++ src/vm/tcc/vm_tgc_c.cpp | 4 +- 8 files changed, 123 insertions(+), 216 deletions(-) create mode 100644 src/sysc/sc_core_adapter_if.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b269918..f8480fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,49 +32,41 @@ add_subdirectory(softfloat) set(LIB_SOURCES src/iss/plugin/instruction_count.cpp src/iss/arch/tgc_c.cpp + src/vm/tcc/vm_tgc_c.cpp src/vm/interp/vm_tgc_c.cpp src/vm/fp_functions.cpp ) +if(WITH_TCC) + list(APPEND LIB_SOURCES src/vm/tcc/vm_tgc_c.cpp) +endif() # library files -if(TARGET ${CORE_NAME}_cpp) - list(APPEND LIB_SOURCES ${${CORE_NAME}_OUTPUT_FILES}) -else() - FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp) - FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp) - list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES}) - foreach(FILEPATH ${GEN_ISS_SOURCES}) - get_filename_component(CORE ${FILEPATH} NAME_WE) - string(TOUPPER ${CORE} CORE) - list(APPEND LIB_DEFINES CORE_${CORE}) - endforeach() - message("Core defines are ${LIB_DEFINES}") +FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp) +FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp) +list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES}) +foreach(FILEPATH ${GEN_ISS_SOURCES}) + get_filename_component(CORE ${FILEPATH} NAME_WE) + string(TOUPPER ${CORE} CORE) + list(APPEND LIB_DEFINES CORE_${CORE}) +endforeach() +message("Core defines are ${LIB_DEFINES}") + +if(WITH_LLVM) + FILE(GLOB LLVM_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp) + list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES}) +endif() + +if(WITH_TCC) + FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/tcc/vm_*.cpp) + list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) endif() if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON) list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp src/iss/plugin/pctrace.cpp) endif() -if(WITH_LLVM) - FILE(GLOB LLVM_GEN_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp - ) - list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES}) -endif() - -if(WITH_TCC) - FILE(GLOB TCC_GEN_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/tcc/vm_*.cpp - ) - list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) -endif() - # Define the library add_library(${PROJECT_NAME} ${LIB_SOURCES}) -# list code gen dependencies -if(TARGET ${CORE_NAME}_cpp) - add_dependencies(${PROJECT_NAME} ${CORE_NAME}_cpp) -endif() if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow) @@ -185,11 +177,17 @@ install(TARGETS tgc-sim # ############################################################################### if(TARGET scc-sysc) - project(dbt-rise-tgc_sc VERSION 1.0.0) + if(BUILD_SHARED_LIBS) + set(THIS_PROJECT_NAME dbt-rise-tgc_sc) + else() + set(THIS_PROJECT_NAME dbt-rise-tgc_sc_lib) + endif() + project(${THIS_PROJECT_NAME} VERSION 1.0.0) add_library(${PROJECT_NAME} src/sysc/core_complex.cpp src/sysc/register_tgc_c.cpp ) + target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC) target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) foreach(F IN LISTS TGC_SOURCES) @@ -219,5 +217,14 @@ if(TARGET scc-sysc) PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sysc # headers for mac (note the different component -> different package) INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers ) + if(NOT BUILD_SHARED_LIBS) + add_library(dbt-rise-tgc_sc INTERFACE) + target_include_directories(dbt-rise-tgc_sc INTERFACE $) + target_include_directories(dbt-rise-tgc_sc INTERFACE $) + target_link_libraries(dbt-rise-tgc_sc INTERFACE + -Wl,--whole-archive,$,--no-whole-archive + $ + scc-sysc) + endif() endif() diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index cd84028..5d6cc35 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -304,7 +304,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co return pc; } -} +} // namespace ${coreDef.name.toLowerCase()} template <> std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index f7a2baf..1b000ea 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -301,7 +301,7 @@ template void vm_impl::gen_trap_behavior(tu_builder& tu) { tu("return *next_pc;"); } -} // namespace mnrv32 +} // namespace ${coreDef.name.toLowerCase()} template <> std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index b135117..e3b0433 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -37,10 +37,11 @@ #include #include #include +#include #ifndef WIN32 #include #endif -#include "core_complex.h" +#include "sc_core_adapter_if.h" #include #include #include @@ -85,136 +86,9 @@ using namespace sc_core; namespace { iss::debugger::encoder_decoder encdec; - std::array lvl = {{'U', 'S', 'H', 'M'}}; } -template -class core_wrapper_t : public PLAT { -public: - using reg_t = typename arch::traits::reg_t; - using phys_addr_t = typename arch::traits::phys_addr_t; - using heart_state_t = typename PLAT::hart_state_type; - core_wrapper_t(core_complex *owner) - : owner(owner) { } - - uint32_t get_mode() { return this->reg.PRIV; } - - inline void set_interrupt_execution(bool v) { this->interrupt_sim = v?1:0; } - - inline bool get_interrupt_execution() { return this->interrupt_sim; } - - heart_state_t &get_state() { return this->state; } - - void notify_phase(iss::arch_if::exec_phase p) override { - if (p == iss::arch_if::ISTART) - owner->sync(this->instr_if.get_total_cycles()); - } - - sync_type needed_sync() const override { return PRE_SYNC; } - - void disass_output(uint64_t pc, const std::string instr) override { - if (!owner->disass_output(pc, instr)) { - std::stringstream s; - s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0') - << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" - << this->reg.icount + this->cycle_offset << "]"; - SCCDEBUG(owner->name())<<"disass: " - << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40) - << std::setfill(' ') << std::left << instr << s.str(); - } - }; - - status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data) override { - if (addr.access && access_type::DEBUG) - return owner->read_mem_dbg(addr.val, length, data) ? Ok : Err; - else { - return owner->read_mem(addr.val, length, data, is_fetch(addr.access)) ? Ok : Err; - } - } - - status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data) override { - if (addr.access && access_type::DEBUG) - return owner->write_mem_dbg(addr.val, length, data) ? Ok : Err; - else { - auto res = owner->write_mem(addr.val, length, data) ? Ok : Err; - // clear MTIP on mtimecmp write - if (addr.val == 0x2004000) { - reg_t val; - this->read_csr(arch::mip, val); - if (val & (1ULL << 7)) this->write_csr(arch::mip, val & ~(1ULL << 7)); - } - return res; - } - } - - status read_csr(unsigned addr, reg_t &val) override { -#ifndef CWR_SYSTEMC - if((addr==arch::time || addr==arch::timeh) && owner->mtime_o.get_interface(0)){ - uint64_t time_val; - bool ret = owner->mtime_o->nb_peek(time_val); - if (addr == iss::arch::time) { - val = static_cast(time_val); - } else if (addr == iss::arch::timeh) { - if (sizeof(reg_t) != 4) return iss::Err; - val = static_cast(time_val >> 32); - } - return ret?Ok:Err; -#else - if((addr==arch::time || addr==arch::timeh)){ - uint64_t time_val = owner->mtime_i.read(); - if (addr == iss::arch::time) { - val = static_cast(time_val); - } else if (addr == iss::arch::timeh) { - if (sizeof(reg_t) != 4) return iss::Err; - val = static_cast(time_val >> 32); - } - return Ok; -#endif - } else { - return PLAT::read_csr(addr, val); - } - } - - void wait_until(uint64_t flags) override { - SCCDEBUG(owner->name()) << "Sleeping until interrupt"; - while(this->reg.pending_trap == 0 && (this->csr[arch::mip] & this->csr[arch::mie]) == 0) { - sc_core::wait(wfi_evt); - } - PLAT::wait_until(flags); - } - - void local_irq(short id, bool value) { - reg_t mask = 0; - switch (id) { - case 3: // SW - mask = 1 << 3; - break; - case 7: // timer - mask = 1 << 7; - break; - case 11: // external - mask = 1 << 11; - break; - default: - if(id>15) mask = 1 << id; - break; - } - if (value) { - this->csr[arch::mip] |= mask; - wfi_evt.notify(); - } else - this->csr[arch::mip] &= ~mask; - this->check_interrupt(); - if(value) - SCCTRACE(owner->name()) << "Triggering interrupt " << id << " Pending trap: " << this->reg.pending_trap; - } - -private: - core_complex *const owner; - sc_event wfi_evt; -}; - int cmd_sysc(int argc, char *argv[], debugger::out_func of, debugger::data_func df, debugger::target_adapter_if *tgt_adapter) { if (argc > 1) { @@ -262,45 +136,34 @@ public: std::function set_interrupt_execution; std::function local_irq; - template - std::tuple create_core(std::string const& backend, unsigned gdb_port, uint32_t hart_id){ - auto* lcpu = new core_wrapper_t(owner); - lcpu->set_mhartid(hart_id); - get_mode = [lcpu]() { return lcpu->get_mode(); }; - get_state = [lcpu]() { return lcpu->get_state().mstatus.backing.val; }; - get_interrupt_execution = [lcpu]() { return lcpu->get_interrupt_execution(); }; - set_interrupt_execution = [lcpu](bool b) { return lcpu->set_interrupt_execution(b); }; - local_irq = [lcpu](short s, bool b) { return lcpu->local_irq(s, b); }; - if(backend == "interp") - return {cpu_ptr{lcpu}, vm_ptr{iss::interp::create(static_cast(lcpu), gdb_port)}}; -#ifdef WITH_LLVM - if(backend == "llvm") - return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}}; -#endif -#ifdef WITH_TCC - if(backend == "tcc") - s return {cpu_ptr{lcpu}, vm_ptr{iss::tcc::create(lcpu, gdb_port)}}; -#endif - return {nullptr, nullptr}; - } - void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id){ - CREATE_CORE(tgc_c) -#ifdef CORE_TGC_B - CREATE_CORE(tgc_b) -#endif -#ifdef CORE_TGC_D - CREATE_CORE(tgc_d) -#endif -#ifdef CORE_TGC_D_XRB_MAC - CREATE_CORE(tgc_d_xrb_mac) -#endif -#ifdef CORE_TGC_D_XRB_NN - CREATE_CORE(tgc_d_xrb_nn) -#endif - { - LOG(ERR) << "Illegal argument value for core type: " << type << std::endl; + auto & f = iss::core_factory::instance(); + if(type.size()==0 || type == "?") { + std::cout<<"Available cores: "<(*cpu).set_mhartid(hart_id); + get_mode = [this]() { return reinterpret_cast(*cpu).get_mode(); }; + get_state = [this]() { return reinterpret_cast(*cpu).get_state(); }; + get_interrupt_execution = [this]() { return reinterpret_cast(*cpu).get_interrupt_execution(); }; + set_interrupt_execution = [this](bool b) { return reinterpret_cast(*cpu).set_interrupt_execution(b); }; + local_irq = [this](short s, bool b) { return reinterpret_cast(*cpu).local_irq(s, b); }; + auto *srv = debugger::server::get(); if (srv) tgt_adapter = srv->get_target(); if (tgt_adapter) @@ -634,5 +497,5 @@ bool core_complex::write_mem_dbg(uint64_t addr, unsigned length, const uint8_t * gp.set_streaming_width(length); return dbus->transport_dbg(gp) == length; } -} /* namespace SiFive */ +} /* namespace tgfs */ } /* namespace sysc */ diff --git a/src/sysc/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp index 8d86788..1fe4194 100644 --- a/src/sysc/register_tgc_c.cpp +++ b/src/sysc/register_tgc_c.cpp @@ -38,28 +38,34 @@ #include "core_complex.h" namespace iss { -namespace { -volatile std::array dummy = { +namespace interp { +volatile std::array tgc_init = { core_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{interp::create(cpu, gdb_port)}}; + return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; }), core_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{interp::create(cpu, gdb_port)}}; - }), + return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; + }) +}; +} +#if defined(WITH_TCC) +namespace tcc { +volatile std::array tgc_init = { core_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{tcc::create(cpu, gdb_port)}}; + return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; }), core_factory::instance().register_creator("tgc_c|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{tcc::create(cpu, gdb_port)}}; + return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; }) }; } +#endif } diff --git a/src/sysc/sc_core_adapter.h b/src/sysc/sc_core_adapter.h index 9544765..77c293f 100644 --- a/src/sysc/sc_core_adapter.h +++ b/src/sysc/sc_core_adapter.h @@ -11,14 +11,13 @@ #include #include -#include "core_complex.h" +#include "sc_core_adapter_if.h" #include #include #include - template -class sc_core_adapter : public PLAT { +class sc_core_adapter : public PLAT, public sc_core_adapter_if { public: using reg_t = typename iss::arch::traits::reg_t; using phys_addr_t = typename iss::arch::traits::phys_addr_t; @@ -26,13 +25,15 @@ public: sc_core_adapter(sysc::tgfs::core_complex *owner) : owner(owner) { } - uint32_t get_mode() { return this->reg.PRIV; } + void set_mhartid(unsigned id) override { PLAT::set_mhartid(id); } - inline void set_interrupt_execution(bool v) { this->interrupt_sim = v?1:0; } + uint32_t get_mode() override { return this->reg.PRIV; } - inline bool get_interrupt_execution() { return this->interrupt_sim; } + void set_interrupt_execution(bool v) override { this->interrupt_sim = v?1:0; } - heart_state_t &get_state() { return this->state; } + bool get_interrupt_execution() override { return this->interrupt_sim; } + + uint64_t get_state() override { return this->state.mstatus.backing.val; } void notify_phase(iss::arch_if::exec_phase p) override { if (p == iss::arch_if::ISTART) @@ -113,7 +114,7 @@ public: PLAT::wait_until(flags); } - void local_irq(short id, bool value) { + void local_irq(short id, bool value) override { reg_t mask = 0; switch (id) { case 3: // SW diff --git a/src/sysc/sc_core_adapter_if.h b/src/sysc/sc_core_adapter_if.h new file mode 100644 index 0000000..5445ee0 --- /dev/null +++ b/src/sysc/sc_core_adapter_if.h @@ -0,0 +1,30 @@ +/* + * sc_core_adapter.h + * + * Created on: Jul 5, 2023 + * Author: eyck + */ + +#ifndef _SYSC_SC_CORE_ADAPTER_IF_H_ +#define _SYSC_SC_CORE_ADAPTER_IF_H_ + + +#include +#include +#include "core_complex.h" +#include +#include +#include + +struct sc_core_adapter_if { + virtual void set_mhartid(unsigned) = 0; + virtual uint32_t get_mode() = 0; + virtual uint64_t get_state() = 0; + virtual bool get_interrupt_execution() = 0; + virtual void set_interrupt_execution(bool v) = 0; + virtual void local_irq(short id, bool value) = 0; + virtual ~sc_core_adapter_if() = default; +}; + + +#endif /* _SYSC_SC_CORE_ADAPTER_IF_H_ */ diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index 8027571..371aa95 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -3210,7 +3210,7 @@ template void vm_impl::gen_trap_behavior(tu_builder& tu) { tu("return *next_pc;"); } -} // namespace mnrv32 +} // namespace tgc_c template <> std::unique_ptr create(arch::tgc_c *core, unsigned short port, bool dump) { @@ -3218,7 +3218,7 @@ std::unique_ptr create(arch::tgc_c *core, unsigned short por if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } -} // namesapce tcc +} // namespace tcc } // namespace iss #include From 57da07eb17c2cfcdca2a4a62c674173b0ec1897e Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 10 Jul 2023 12:52:48 +0200 Subject: [PATCH 118/184] rework sc wrapper build --- CMakeLists.txt | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f8480fb..d7977b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,37 +178,39 @@ install(TARGETS tgc-sim ############################################################################### if(TARGET scc-sysc) if(BUILD_SHARED_LIBS) - set(THIS_PROJECT_NAME dbt-rise-tgc_sc) + set(DBT_RISE_SC_LIB_NAME dbt-rise-tgc_sc) else() - set(THIS_PROJECT_NAME dbt-rise-tgc_sc_lib) + set(DBT_RISE_SC_LIB_NAME dbt-rise-tgc_sc_lib) + set(CREATE_INTERFACE_LIB ON) endif() - project(${THIS_PROJECT_NAME} VERSION 1.0.0) - add_library(${PROJECT_NAME} + project(dbt-rise-tgc_sc VERSION 1.0.0) + + add_library(${DBT_RISE_SC_LIB_NAME} src/sysc/core_complex.cpp src/sysc/register_tgc_c.cpp ) - target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC) - target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) + target_include_directories(${DBT_RISE_SC_LIB_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) + target_compile_definitions(${DBT_RISE_SC_LIB_NAME} PUBLIC WITH_SYSTEMC) + target_compile_definitions(${DBT_RISE_SC_LIB_NAME} PRIVATE CORE_${CORE_NAME}) foreach(F IN LISTS TGC_SOURCES) if (${F} MATCHES ".*/arch/([^/]*)\.cpp") string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) string(TOUPPER ${CORE_NAME_LC} CORE_NAME) - target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) + target_compile_definitions(${DBT_RISE_SC_LIB_NAME} PRIVATE CORE_${CORE_NAME}) endif() endforeach() - target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc) + target_link_libraries(${DBT_RISE_SC_LIB_NAME} PUBLIC dbt-rise-tgc scc-sysc) if(WITH_LLVM) - target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) + target_link_libraries(${DBT_RISE_SC_LIB_NAME} PUBLIC ${llvm_libs}) endif() set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h) - set_target_properties(${PROJECT_NAME} PROPERTIES + set_target_properties(${DBT_RISE_SC_LIB_NAME} PROPERTIES VERSION ${PROJECT_VERSION} FRAMEWORK FALSE PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers ) - install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME} + install(TARGETS ${DBT_RISE_SC_LIB_NAME} COMPONENT ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets # for downstream dependencies ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries @@ -217,13 +219,13 @@ if(TARGET scc-sysc) PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sysc # headers for mac (note the different component -> different package) INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers ) - if(NOT BUILD_SHARED_LIBS) + if(CREATE_INTERFACE_LIB) add_library(dbt-rise-tgc_sc INTERFACE) - target_include_directories(dbt-rise-tgc_sc INTERFACE $) - target_include_directories(dbt-rise-tgc_sc INTERFACE $) + target_include_directories(dbt-rise-tgc_sc INTERFACE + $) target_link_libraries(dbt-rise-tgc_sc INTERFACE - -Wl,--whole-archive,$,--no-whole-archive - $ + -Wl,--whole-archive,$,--no-whole-archive + $ scc-sysc) endif() endif() From 0b719a4b576a3ea1520193ab5a28442a939a5e4b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 10 Jul 2023 20:39:02 +0200 Subject: [PATCH 119/184] fixes literal type --- gen_input/templates/CORENAME.h.gtl | 2 +- src/iss/arch/tgc_c.h | 2 +- src/vm/interp/vm_tgc_c.cpp | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 45a3ed7..2debd97 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -55,7 +55,7 @@ def byteSize(int size){ return 128; } def getCString(def val){ - return val.toString() + return val.toString()+'ULL' } %> #ifndef _${coreDef.name.toUpperCase()}_H_ diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index 611ef79..2f33ca5 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -53,7 +53,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; - enum constants {MISA_VAL=1073746180, MARCHID_VAL=2147483651, XLEN=32, INSTR_ALIGNMENT=2, RFS=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, CSR_SIZE=4096, MUL_LEN=64}; + enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL}; constexpr static unsigned FP_REGS_SIZE = 0; diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index d1e6596..3b409df 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -2635,7 +2635,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co return pc; } -} +} // namespace tgc_c template <> std::unique_ptr create(arch::tgc_c *core, unsigned short port, bool dump) { @@ -2667,4 +2667,3 @@ volatile std::array dummy = { }; } } - From 957145ca84a08c957950a7ff832182862e9a0728 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 14 Jul 2023 11:11:03 +0200 Subject: [PATCH 120/184] add SystemC ISS factory --- CMakeLists.txt | 33 ++------ gen_input/templates/interp/CORENAME.cpp.gtl | 4 +- gen_input/templates/tcc/CORENAME.cpp.gtl | 4 +- src/iss/factory.h | 24 +++--- src/sysc/core_complex.cpp | 27 ++++--- src/sysc/iss_factory.h | 88 +++++++++++++++++++++ src/sysc/register_tgc_c.cpp | 19 ++--- src/sysc/sc_core_adapter.h | 6 +- src/sysc/sc_core_adapter_if.h | 5 +- src/vm/tcc/vm_tgc_c.cpp | 4 +- 10 files changed, 144 insertions(+), 70 deletions(-) create mode 100644 src/sysc/iss_factory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d7977b3..a2a546f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,40 +177,32 @@ install(TARGETS tgc-sim # ############################################################################### if(TARGET scc-sysc) - if(BUILD_SHARED_LIBS) - set(DBT_RISE_SC_LIB_NAME dbt-rise-tgc_sc) - else() - set(DBT_RISE_SC_LIB_NAME dbt-rise-tgc_sc_lib) - set(CREATE_INTERFACE_LIB ON) - endif() project(dbt-rise-tgc_sc VERSION 1.0.0) - - add_library(${DBT_RISE_SC_LIB_NAME} + add_library(${PROJECT_NAME} src/sysc/core_complex.cpp src/sysc/register_tgc_c.cpp ) - target_include_directories(${DBT_RISE_SC_LIB_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_compile_definitions(${DBT_RISE_SC_LIB_NAME} PUBLIC WITH_SYSTEMC) - target_compile_definitions(${DBT_RISE_SC_LIB_NAME} PRIVATE CORE_${CORE_NAME}) + target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC) + target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) foreach(F IN LISTS TGC_SOURCES) if (${F} MATCHES ".*/arch/([^/]*)\.cpp") string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F}) string(TOUPPER ${CORE_NAME_LC} CORE_NAME) - target_compile_definitions(${DBT_RISE_SC_LIB_NAME} PRIVATE CORE_${CORE_NAME}) + target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) endif() endforeach() - target_link_libraries(${DBT_RISE_SC_LIB_NAME} PUBLIC dbt-rise-tgc scc-sysc) + target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc) if(WITH_LLVM) - target_link_libraries(${DBT_RISE_SC_LIB_NAME} PUBLIC ${llvm_libs}) + target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) endif() set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h) - set_target_properties(${DBT_RISE_SC_LIB_NAME} PROPERTIES + set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} FRAMEWORK FALSE PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers ) - install(TARGETS ${DBT_RISE_SC_LIB_NAME} COMPONENT ${PROJECT_NAME} + install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets # for downstream dependencies ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries @@ -219,14 +211,5 @@ if(TARGET scc-sysc) PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sysc # headers for mac (note the different component -> different package) INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers ) - if(CREATE_INTERFACE_LIB) - add_library(dbt-rise-tgc_sc INTERFACE) - target_include_directories(dbt-rise-tgc_sc INTERFACE - $) - target_link_libraries(dbt-rise-tgc_sc INTERFACE - -Wl,--whole-archive,$,--no-whole-archive - $ - scc-sysc) - endif() endif() diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 5d6cc35..5629249 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -321,13 +321,13 @@ std::unique_ptr create(arch::${coreD namespace iss { namespace { volatile std::array dummy = { - core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void*) -> std::tuple{ + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_m_p(); auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; }), - core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned port, void*) -> std::tuple{ + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_mu_p(); auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index 1b000ea..2121964 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -318,13 +318,13 @@ std::unique_ptr create(arch::${coreD namespace iss { namespace { volatile std::array dummy = { - core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> std::tuple{ + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_m_p(); auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; }), - core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_mu_p(); auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); diff --git a/src/iss/factory.h b/src/iss/factory.h index 7e45838..c24fefb 100644 --- a/src/iss/factory.h +++ b/src/iss/factory.h @@ -80,9 +80,17 @@ class core_factory { public: static core_factory & instance() { static core_factory bf; return bf; } - bool register_creator(const std::string &, create_fn const&); + bool register_creator(const std::string & className, create_fn const& fn) { + registry[className] = fn; + return true; + } - base_t create(const std::string &, unsigned gdb_port=0, void* init_data=nullptr) const; + base_t create(std::string const& className, unsigned gdb_port=0, void* init_data=nullptr) const { + registry_t::const_iterator regEntry = registry.find(className); + if (regEntry != registry.end()) + return regEntry->second(gdb_port, init_data); + return {nullptr, nullptr}; + } std::vector get_names() { std::vector keys{registry.size()}; @@ -93,18 +101,6 @@ public: } }; -inline bool core_factory::register_creator(const std::string & className, create_fn const& fn) { - registry[className] = fn; - return true; -} - -inline core_factory::base_t core_factory::create(const std::string &className, unsigned gdb_port, void* data) const { - registry_t::const_iterator regEntry = registry.find(className); - if (regEntry != registry.end()) - return regEntry->second(gdb_port, data); - return {nullptr, nullptr}; -} - } #endif /* _ISS_FACTORY_H_ */ diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index e3b0433..be25f53 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include "iss_factory.h" #ifndef WIN32 #include #endif @@ -128,7 +128,9 @@ public: void reset(uint64_t addr){vm->reset(addr);} inline void start(){vm->start();} - inline std::pair load_file(std::string const& name){ return cpu->load_file(name);}; + inline std::pair load_file(std::string const& name){ + iss::arch_if* cc = cpu->get_arch_if(); + return cc->load_file(name);}; std::function get_mode; std::function get_state; @@ -137,7 +139,7 @@ public: std::function local_irq; void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id){ - auto & f = iss::core_factory::instance(); + auto & f = sysc::iss_factory::instance(); if(type.size()==0 || type == "?") { std::cout<<"Available cores: "<(*cpu).set_mhartid(hart_id); - get_mode = [this]() { return reinterpret_cast(*cpu).get_mode(); }; - get_state = [this]() { return reinterpret_cast(*cpu).get_state(); }; - get_interrupt_execution = [this]() { return reinterpret_cast(*cpu).get_interrupt_execution(); }; - set_interrupt_execution = [this](bool b) { return reinterpret_cast(*cpu).set_interrupt_execution(b); }; - local_irq = [this](short s, bool b) { return reinterpret_cast(*cpu).local_irq(s, b); }; + auto* sc_cpu_if = reinterpret_cast(cpu.get()); + sc_cpu_if->set_mhartid(hart_id); + get_mode = [sc_cpu_if]() { return sc_cpu_if->get_mode(); }; + get_state = [sc_cpu_if]() { return sc_cpu_if->get_state(); }; + get_interrupt_execution = [sc_cpu_if]() { return sc_cpu_if->get_interrupt_execution(); }; + set_interrupt_execution = [sc_cpu_if](bool b) { return sc_cpu_if->set_interrupt_execution(b); }; + local_irq = [sc_cpu_if](short s, bool b) { return sc_cpu_if->local_irq(s, b); }; auto *srv = debugger::server::get(); if (srv) tgt_adapter = srv->get_target(); @@ -176,7 +179,7 @@ public: core_complex * const owner; vm_ptr vm{nullptr}; - cpu_ptr cpu{nullptr}; + sc_cpu_ptr cpu{nullptr}; iss::debugger::target_adapter_if *tgt_adapter{nullptr}; }; diff --git a/src/sysc/iss_factory.h b/src/sysc/iss_factory.h new file mode 100644 index 0000000..f29a5b0 --- /dev/null +++ b/src/sysc/iss_factory.h @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (C) 2021 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#ifndef _ISS_FACTORY_H_ +#define _ISS_FACTORY_H_ + +#include +#include "sc_core_adapter_if.h" +#include +#include +#include +#include +#include +#include + +namespace sysc { + +using sc_cpu_ptr = std::unique_ptr; +using vm_ptr= std::unique_ptr; + +class iss_factory { +public: + using base_t = std::tuple; + using create_fn = std::function; + using registry_t = std::unordered_map ; + + iss_factory() = default; + iss_factory(const iss_factory &) = delete; + iss_factory & operator=(const iss_factory &) = delete; + + static iss_factory & instance() { static iss_factory bf; return bf; } + + bool register_creator(const std::string & className, create_fn const& fn) { + registry[className] = fn; + return true; + } + + base_t create(std::string const& className, unsigned gdb_port=0, void* init_data=nullptr) const { + registry_t::const_iterator regEntry = registry.find(className); + if (regEntry != registry.end()) + return regEntry->second(gdb_port, init_data); + return {nullptr, nullptr}; + } + + std::vector get_names() { + std::vector keys{registry.size()}; + std::transform(std::begin(registry), std::end(registry), std::begin(keys), [](std::pair const& p){ + return p.first; + }); + return keys; + } +private: + registry_t registry; + +}; + +} + +#endif /* _ISS_FACTORY_H_ */ diff --git a/src/sysc/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp index 1fe4194..efd46b0 100644 --- a/src/sysc/register_tgc_c.cpp +++ b/src/sysc/register_tgc_c.cpp @@ -30,7 +30,7 @@ * *******************************************************************************/ -#include +#include "iss_factory.h" #include #include #include @@ -39,16 +39,17 @@ namespace iss { namespace interp { +using namespace sysc; volatile std::array tgc_init = { - core_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ - auto cc = reinterpret_cast(data); - arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; + iss_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }), - core_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ - auto cc = reinterpret_cast(data); - arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; + iss_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }) }; } diff --git a/src/sysc/sc_core_adapter.h b/src/sysc/sc_core_adapter.h index 77c293f..bbd1465 100644 --- a/src/sysc/sc_core_adapter.h +++ b/src/sysc/sc_core_adapter.h @@ -16,6 +16,7 @@ #include #include +namespace sysc { template class sc_core_adapter : public PLAT, public sc_core_adapter_if { public: @@ -25,6 +26,8 @@ public: sc_core_adapter(sysc::tgfs::core_complex *owner) : owner(owner) { } + iss::arch_if* get_arch_if() override { return this;} + void set_mhartid(unsigned id) override { PLAT::set_mhartid(id); } uint32_t get_mode() override { return this->reg.PRIV; } @@ -144,6 +147,5 @@ private: sysc::tgfs::core_complex *const owner; sc_core::sc_event wfi_evt; }; - - +} #endif /* _SYSC_SC_CORE_ADAPTER_H_ */ diff --git a/src/sysc/sc_core_adapter_if.h b/src/sysc/sc_core_adapter_if.h index 5445ee0..05a2c61 100644 --- a/src/sysc/sc_core_adapter_if.h +++ b/src/sysc/sc_core_adapter_if.h @@ -16,7 +16,9 @@ #include #include +namespace sysc { struct sc_core_adapter_if { + virtual iss::arch_if* get_arch_if() = 0; virtual void set_mhartid(unsigned) = 0; virtual uint32_t get_mode() = 0; virtual uint64_t get_state() = 0; @@ -25,6 +27,5 @@ struct sc_core_adapter_if { virtual void local_irq(short id, bool value) = 0; virtual ~sc_core_adapter_if() = default; }; - - +} #endif /* _SYSC_SC_CORE_ADAPTER_IF_H_ */ diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index 371aa95..fee3a87 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -3229,13 +3229,13 @@ namespace { volatile std::array dummy = { core_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_m_p(); - auto vm = new tcc::tgc_c::vm_impl(*cpu, false); + auto* vm = new tcc::tgc_c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; }), core_factory::instance().register_creator("tgc_c|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_mu_p(); - auto vm = new tcc::tgc_c::vm_impl(*cpu, false); + auto* vm = new tcc::tgc_c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; }) From 720236ec3faf87246d15252278532a054c042875 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 14 Jul 2023 12:51:51 +0200 Subject: [PATCH 121/184] add generated core registration --- CMakeLists.txt | 11 +++- gen_input/templates/CORENAME_sysc.cpp.gtl | 72 +++++++++++++++++++++++ src-gen/.gitignore | 3 +- src/sysc/register_tgc_c.cpp | 8 +-- 4 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 gen_input/templates/CORENAME_sysc.cpp.gtl diff --git a/CMakeLists.txt b/CMakeLists.txt index a2a546f..0f07fd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,10 @@ find_package(elfio QUIET) find_package(Boost COMPONENTS coroutine) find_package(jsoncpp) +if(TARGET tcc::tcc) + set(WITH_TCC ON) +endif() + if(WITH_LLVM) if(DEFINED ENV{LLVM_HOME}) find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm) @@ -178,10 +182,13 @@ install(TARGETS tgc-sim ############################################################################### if(TARGET scc-sysc) project(dbt-rise-tgc_sc VERSION 1.0.0) - add_library(${PROJECT_NAME} + set(LIB_SOURCES src/sysc/core_complex.cpp src/sysc/register_tgc_c.cpp - ) + ) + FILE(GLOB GEN_SC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/sysc/register_*.cpp) + list(APPEND LIB_SOURCES ${GEN_SC_SOURCES}) + add_library(${PROJECT_NAME} ${LIB_SOURCES}) target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC) target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME}) foreach(F IN LISTS TGC_SOURCES) diff --git a/gen_input/templates/CORENAME_sysc.cpp.gtl b/gen_input/templates/CORENAME_sysc.cpp.gtl new file mode 100644 index 0000000..e56e7db --- /dev/null +++ b/gen_input/templates/CORENAME_sysc.cpp.gtl @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (C) 2023 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#include "iss_factory.h" +#include +#include +#include +#include "sc_core_adapter.h" +#include "core_complex.h" + +namespace iss { +namespace interp { +using namespace sysc; +volatile std::array ${coreDef.name.toLowerCase()}_init = { + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }) +}; +} +#if defined(WITH_TCC) +namespace tcc { +volatile std::array ${coreDef.name.toLowerCase()}_init = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + auto cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + auto cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }) +}; +} +#endif +} diff --git a/src-gen/.gitignore b/src-gen/.gitignore index d3fcb35..454f93f 100644 --- a/src-gen/.gitignore +++ b/src-gen/.gitignore @@ -1,2 +1,3 @@ /iss -/vm \ No newline at end of file +/vm +/sysc \ No newline at end of file diff --git a/src/sysc/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp index efd46b0..31a99a5 100644 --- a/src/sysc/register_tgc_c.cpp +++ b/src/sysc/register_tgc_c.cpp @@ -58,13 +58,13 @@ namespace tcc { volatile std::array tgc_init = { core_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); - arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; + auto* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }), core_factory::instance().register_creator("tgc_c|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); - arch::tgc_c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; + auto* cpu = new sc_core_adapter>(cc); + return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }) }; } From a0ca3cdfa53bea29a20e6abf532afb7980f5bdb2 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 13 Jul 2023 09:42:39 +0200 Subject: [PATCH 122/184] revive LLVM support (WIP) --- CMakeLists.txt | 18 +++++++++++------- src/main.cpp | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f07fd8..bc11091 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,13 +15,17 @@ if(TARGET tcc::tcc) endif() if(WITH_LLVM) - if(DEFINED ENV{LLVM_HOME}) - find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm) - endif(DEFINED ENV{LLVM_HOME}) - find_package(LLVM REQUIRED CONFIG) - message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") - message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") - llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser) + if(FALSE) + if(DEFINED ENV{LLVM_HOME}) + find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm) + endif(DEFINED ENV{LLVM_HOME}) + find_package(LLVM REQUIRED CONFIG) + message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") + message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser) + else() + find_package(LLVM REQUIRED LLVMSupport LLVMCore LLVMMCJIT LLVMX86CodeGen LLVMX86AsmParser) + endif() endif() #Mac needed variables (adapt for your needs - http://www.cmake.org/Wiki/CMake_RPATH_handling#Mac_OS_X_and_the_RPATH) diff --git a/src/main.cpp b/src/main.cpp index 02ec210..0452578 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,7 +39,7 @@ #include #include "iss/arch/tgc_mapper.h" #ifdef WITH_LLVM -#include +#include #endif #include #include "iss/plugin/cycle_estimate.h" From 9459632f6cdc01a8e5bc323eb3ca457733d7d66b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 17 Jul 2023 19:52:50 +0200 Subject: [PATCH 123/184] adds llvm build support incl. conan --- CMakeLists.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc11091..c8fe6a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,14 +15,14 @@ if(TARGET tcc::tcc) endif() if(WITH_LLVM) - if(FALSE) - if(DEFINED ENV{LLVM_HOME}) - find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm) - endif(DEFINED ENV{LLVM_HOME}) - find_package(LLVM REQUIRED CONFIG) - message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") - message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") - llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser) + if(DEFINED ENV{LLVM_HOME}) + find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm) + endif(DEFINED ENV{LLVM_HOME}) + find_package(LLVM QUIET CONFIG) + if(LLVM_FOUND) + message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") + message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser) else() find_package(LLVM REQUIRED LLVMSupport LLVMCore LLVMMCJIT LLVMX86CodeGen LLVMX86AsmParser) endif() From 94e46b996884f9836f8b2adbe13f7e5c2671faa6 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 17 Jul 2023 19:57:09 +0200 Subject: [PATCH 124/184] adds some cleanup --- CMakeLists.txt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c8fe6a4..5ad2123 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ endif() if(WITH_LLVM) if(DEFINED ENV{LLVM_HOME}) find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm) - endif(DEFINED ENV{LLVM_HOME}) + endif() find_package(LLVM QUIET CONFIG) if(LLVM_FOUND) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") @@ -28,13 +28,6 @@ if(WITH_LLVM) endif() endif() -#Mac needed variables (adapt for your needs - http://www.cmake.org/Wiki/CMake_RPATH_handling#Mac_OS_X_and_the_RPATH) -#set(CMAKE_MACOSX_RPATH ON) -#set(CMAKE_SKIP_BUILD_RPATH FALSE) -#set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) -#set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -#set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) - add_subdirectory(softfloat) set(LIB_SOURCES From edba497fa16ae0f56a5a9e043af62d09484c0e33 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 19 Jul 2023 08:19:38 +0200 Subject: [PATCH 125/184] fixes linker isseu using whole-archive --- CMakeLists.txt | 8 +++++--- cmake/flink.cmake | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 cmake/flink.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ad2123..8559904 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,12 @@ cmake_minimum_required(VERSION 3.12) +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) ############################################################################### # ############################################################################### project(dbt-rise-tgc VERSION 1.0.0) include(GNUInstallDirs) +include(flink) find_package(elfio QUIET) find_package(Boost COMPONENTS coroutine) @@ -82,8 +84,8 @@ if(TARGET jsoncpp::jsoncpp) else() target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp) endif() -if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND BUILD_SHARED_LIBS) - target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-rise-core -Wl,--no-whole-archive) +if(BUILD_SHARED_LIBS) + target_force_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core) else() target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core) endif() @@ -154,7 +156,7 @@ if(WITH_TCC) target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC) endif() # Links the target exe against the libraries -target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc) +target_force_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc) if(TARGET Boost::program_options) target_link_libraries(${PROJECT_NAME} PUBLIC Boost::program_options) else() diff --git a/cmake/flink.cmake b/cmake/flink.cmake new file mode 100644 index 0000000..69b5c9f --- /dev/null +++ b/cmake/flink.cmake @@ -0,0 +1,35 @@ +# according to https://github.com/horance-liu/flink.cmake/tree/master +# SPDX-License-Identifier: Apache-2.0 + +include(CMakeParseArguments) + +function(target_do_force_link_libraries target visibility lib) + if(MSVC) + target_link_libraries(${target} ${visibility} "/WHOLEARCHIVE:${lib}") + elseif(APPLE) + target_link_libraries(${target} ${visibility} -Wl,-force_load ${lib}) + else() + target_link_libraries(${target} ${visibility} -Wl,--whole-archive ${lib} -Wl,--no-whole-archive) + endif() +endfunction() + +function(target_force_link_libraries target) + cmake_parse_arguments(FLINK + "" + "" + "PUBLIC;INTERFACE;PRIVATE" + ${ARGN} + ) + + foreach(lib IN LISTS FLINK_PUBLIC) + target_do_force_link_libraries(${target} PUBLIC ${lib}) + endforeach() + + foreach(lib IN LISTS FLINK_INTERFACE) + target_do_force_link_libraries(${target} INTERFACE ${lib}) + endforeach() + + foreach(lib IN LISTS FLINK_PRIVATE) + target_do_force_link_libraries(${target} PRIVATE ${lib}) + endforeach() +endfunction() \ No newline at end of file From c78026b720d2fa548c502a8b77d5fe9a6534e382 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sun, 23 Jul 2023 08:05:15 +0200 Subject: [PATCH 126/184] adds faster instruction decoding --- src/vm/interp/vm_tgc_c.cpp | 93 +++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index c94b716..2525a37 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -153,14 +153,22 @@ private: /**************************************************************************** * start opcode definitions ****************************************************************************/ - struct InstructionDesriptor { + struct instruction_descriptor { size_t length; uint32_t value; uint32_t mask; typename arch::traits::opcode_e op; }; - - const std::array instr_descr = {{ + struct decoding_tree_node{ + std::vector instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; + + decoding_tree_node* root {nullptr}; + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits::opcode_e::LUI}, {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, arch::traits::opcode_e::AUIPC}, @@ -251,18 +259,61 @@ private: {16, 0b0000000000000000, 0b1111111111111111, arch::traits::opcode_e::DII}, }}; - //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ auto phys_pc = this->core.v2p(pc); - //if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - // if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; - // if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction - // if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) return iss::Err; - //} else { if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err; - //} return iss::Ok; } + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + typename arch::traits::opcode_e decodeInstr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decodeInstr(child, word); + } + } + } + return arch::traits::opcode_e::MAX_OPCODE; + } }; template void debug_fn(CODE_WORD insn) { @@ -290,15 +341,11 @@ template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { unsigned id=0; - for (auto instr : instr_descr) { - auto quadrant = instr.value & 0x3; - qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); - } - for(auto& lut: qlut){ - std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ - return bit_count(a.mask) > bit_count(b.mask); - }); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } inline bool is_count_limit_enabled(finish_cond_e cond){ @@ -309,14 +356,6 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){ return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; } -template -typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t instr){ - for(auto& e: qlut[instr&0x3]){ - if(!((instr&e.mask) ^ e.value )) return e.id; - } - return arch::traits::opcode_e::MAX_OPCODE; -} - template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ auto pc=start; @@ -338,7 +377,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if (is_jump_to_self_enabled(cond) && (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = decode_inst_id(instr); + auto inst_id = decodeInstr(root, instr); // pre execution stuff this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); From bd0d15f3a2e8c751d78d61acd18f869ddec3b2d5 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sun, 23 Jul 2023 08:10:57 +0200 Subject: [PATCH 127/184] updates template for faster instruction decoding --- gen_input/templates/interp/CORENAME.cpp.gtl | 91 +++++++++++++++------ src/vm/interp/vm_tgc_c.cpp | 2 +- 2 files changed, 66 insertions(+), 27 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index acf7afd..7a7707e 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -159,30 +159,81 @@ private: /**************************************************************************** * start opcode definitions ****************************************************************************/ - struct InstructionDesriptor { + struct instruction_descriptor { size_t length; uint32_t value; uint32_t mask; typename arch::traits::opcode_e op; }; + struct decoding_tree_node{ + std::vector instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> {${instr.length}, ${instr.encoding}, ${instr.mask}, arch::traits::opcode_e::${instr.instruction.name}},<%}%> }}; - //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ auto phys_pc = this->core.v2p(pc); - //if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - // if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; - // if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction - // if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) return iss::Err; - //} else { if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err; - //} return iss::Ok; } + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + typename arch::traits::opcode_e decodeInstr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decodeInstr(child, word); + } + } + } + return arch::traits::opcode_e::MAX_OPCODE; + } }; template void debug_fn(CODE_WORD insn) { @@ -210,15 +261,11 @@ template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { unsigned id=0; - for (auto instr : instr_descr) { - auto quadrant = instr.value & 0x3; - qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); - } - for(auto& lut: qlut){ - std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ - return bit_count(a.mask) > bit_count(b.mask); - }); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } inline bool is_count_limit_enabled(finish_cond_e cond){ @@ -229,14 +276,6 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){ return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; } -template -typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t instr){ - for(auto& e: qlut[instr&0x3]){ - if(!((instr&e.mask) ^ e.value )) return e.id; - } - return arch::traits::opcode_e::MAX_OPCODE; -} - template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ auto pc=start; @@ -258,7 +297,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if (is_jump_to_self_enabled(cond) && (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = decode_inst_id(instr); + auto inst_id = decodeInstr(root, instr); // pre execution stuff this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 2525a37..d5817ed 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -166,7 +166,7 @@ private: uint32_t value; decoding_tree_node(uint32_t value) : value(value){} }; - + decoding_tree_node* root {nullptr}; const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ From 6e52af168bb7984c28e4ed0208aa38720875dde7 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sat, 29 Jul 2023 11:42:46 +0200 Subject: [PATCH 128/184] adds faster decoding to tcc and cleans up others --- gen_input/templates/interp/CORENAME.cpp.gtl | 7 +- gen_input/templates/tcc/CORENAME.cpp.gtl | 158 ++++++++-------- src/vm/interp/vm_tgc_c.cpp | 7 +- src/vm/tcc/vm_tgc_c.cpp | 195 ++++++++++---------- 4 files changed, 180 insertions(+), 187 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 7a7707e..9585627 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -218,7 +218,7 @@ private: }); } } - typename arch::traits::opcode_e decodeInstr(decoding_tree_node* node, code_word_t word){ + typename arch::traits::opcode_e decode_instr(decoding_tree_node* node, code_word_t word){ if(!node->children.size()){ if(node->instrs.size() == 1) return node->instrs[0].op; for(auto instr : node->instrs){ @@ -228,7 +228,7 @@ private: else{ for(auto child : node->children){ if (child->value == (node->submask&word)){ - return decodeInstr(child, word); + return decode_instr(child, word); } } } @@ -260,7 +260,6 @@ constexpr size_t bit_count(uint32_t u) { template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - unsigned id=0; root = new decoding_tree_node(std::numeric_limits::max()); for(auto instr:instr_descr){ root->instrs.push_back(instr); @@ -297,7 +296,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if (is_jump_to_self_enabled(cond) && (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = decodeInstr(root, instr); + auto inst_id = decode_instr(root, instr); // pre execution stuff this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index b7cec56..809ae00 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -121,57 +121,7 @@ protected: } } - // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } + template::type> inline S sext(U from) { auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> /* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */ {${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> @@ -228,11 +187,64 @@ private: vm_impl::gen_trap_check(tu); return BRANCH; } + + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; + } }; -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; } template vm_impl::vm_impl() { this(new ARCH()); } @@ -240,14 +252,11 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } template @@ -255,30 +264,19 @@ std::tuple vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - // const typename traits::addr_t upper_bits = ~traits::PGMASK; + code_word_t instr = 0; phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; paddr = this->core.v2p(pc); -// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary -// auto res = this->core.read(paddr, 2, data); -// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction -// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); -// } -// } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + auto res = this->core.read(paddr, 4, reinterpret_cast(&instr)); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; + auto f = decode_instr(root, instr); if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, tu); + return (this->*f)(pc, instr, tu); } template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index d5817ed..55c75d5 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -298,7 +298,7 @@ private: }); } } - typename arch::traits::opcode_e decodeInstr(decoding_tree_node* node, code_word_t word){ + typename arch::traits::opcode_e decode_instr(decoding_tree_node* node, code_word_t word){ if(!node->children.size()){ if(node->instrs.size() == 1) return node->instrs[0].op; for(auto instr : node->instrs){ @@ -308,7 +308,7 @@ private: else{ for(auto child : node->children){ if (child->value == (node->submask&word)){ - return decodeInstr(child, word); + return decode_instr(child, word); } } } @@ -340,7 +340,6 @@ constexpr size_t bit_count(uint32_t u) { template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - unsigned id=0; root = new decoding_tree_node(std::numeric_limits::max()); for(auto instr:instr_descr){ root->instrs.push_back(instr); @@ -377,7 +376,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if (is_jump_to_self_enabled(cond) && (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = decodeInstr(root, instr); + auto inst_id = decode_instr(root, instr); // pre execution stuff this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index 495d97e..fde3ec3 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -121,57 +121,7 @@ protected: } } - // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } + template::type> inline S sext(U from) { auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI, encoding '0b00000000000000000000000000110111' */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, @@ -494,14 +453,14 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto new_pc = tu.assignment(tu.ext((tu.bitwise_and((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),tu.constant(~ 0x1,8))),32,true),32); + auto new_pc = tu.assignment(tu.ext((tu.bitwise_and((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),tu.constant(~0x1,8))),32,true),32); tu.open_if(tu.srem(new_pc,tu.constant(static_cast(traits:: INSTR_ALIGNMENT),32))); this->gen_raise_trap(tu, 0, 0); tu.open_else(); if(rd!= 0) { tu.store(rd + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 4,8))),32,true)); } - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); @@ -1963,7 +1922,7 @@ private: else{ auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); if(zimm!= 0) { - tu.write_mem(traits::CSR, csr, tu.bitwise_and(xrd,tu.constant(~ ((uint32_t)zimm),32))); + tu.write_mem(traits::CSR, csr, tu.bitwise_and(xrd,tu.constant(~((uint32_t)zimm),32))); } if(rd!= 0) { tu.store(rd + traits::X0,xrd); @@ -2024,7 +1983,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false)),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false))),64,false),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext(res,32,true)); } @@ -2058,7 +2017,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false)),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false))),64,false),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } @@ -2092,7 +2051,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.load(rs2+ traits::X0, 0)),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.load(rs2+ traits::X0, 0),64,true))),64,false),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } @@ -2126,7 +2085,7 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.mul(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0)),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),64,true),tu.ext(tu.load(rs2+ traits::X0, 0),64,true))),64,true),64); if(rd!=0) { tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); } @@ -2164,13 +2123,13 @@ private: auto divisor = tu.assignment(tu.ext(tu.load(rs2+ traits::X0, 0),32,false),32); if(rd!= 0){ tu.open_if(tu.icmp(ICmpInst::ICMP_NE,divisor,tu.constant( 0,8))); auto MMIN = tu.assignment(tu.constant(((uint32_t)1)<<(static_cast(traits:: XLEN)-1),32),32); - tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,divisor,tu.constant(- 1,8)))); + tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,divisor,tu.constant(-1,8)))); tu.store(rd + traits::X0,MMIN); tu.open_else(); tu.store(rd + traits::X0,tu.ext((tu.sdiv(dividend,divisor)),32,true)); tu.close_scope(); tu.open_else(); - tu.store(rd + traits::X0,tu.constant((uint32_t)- 1,32)); + tu.store(rd + traits::X0,tu.constant((uint32_t)-1,32)); tu.close_scope(); } } @@ -2209,7 +2168,7 @@ private: } tu.open_else(); if(rd!=0) { - tu.store(rd + traits::X0,tu.constant((uint32_t)- 1,32)); + tu.store(rd + traits::X0,tu.constant((uint32_t)-1,32)); } tu.close_scope(); } @@ -2244,7 +2203,7 @@ private: else{ tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,8))); auto MMIN = tu.assignment(tu.constant( 1<<(static_cast(traits:: XLEN)-1),8),32); - tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,tu.ext(tu.load(rs2+ traits::X0, 0),32,false),tu.constant(- 1,8)))); + tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,tu.ext(tu.load(rs2+ traits::X0, 0),32,false),tu.constant(-1,8)))); if(rd!=0) { tu.store(rd + traits::X0,tu.constant( 0,8)); } @@ -2353,8 +2312,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); - tu.store(rd+ 8 + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,false),32,true)); + auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); + tu.store(rd+ 8 + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32,true)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,58); @@ -2380,8 +2339,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); - tu.write_mem(traits::MEM, load_address, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,true)); + auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); + tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,true)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,59); @@ -2898,8 +2857,7 @@ private: } else{ auto offs = tu.assignment(tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); - auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32); - tu.store(rd + traits::X0,tu.ext(res,32,true)); + tu.store(rd + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32,true)); } auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2957,7 +2915,7 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs1&&rs1(traits:: RFS)) { - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0),tu.constant(~ 0x1,8)),32); + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0),tu.constant(~0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -3045,7 +3003,7 @@ private: else{ auto new_pc = tu.assignment(tu.load(rs1+ traits::X0, 0),32); tu.store(1 + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,8))),32,true)); - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -3138,11 +3096,64 @@ private: vm_impl::gen_trap_check(tu); return BRANCH; } + + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; + } }; -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; } template vm_impl::vm_impl() { this(new ARCH()); } @@ -3150,14 +3161,11 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } template @@ -3165,30 +3173,19 @@ std::tuple vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - // const typename traits::addr_t upper_bits = ~traits::PGMASK; + code_word_t instr = 0; phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; paddr = this->core.v2p(pc); -// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary -// auto res = this->core.read(paddr, 2, data); -// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction -// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); -// } -// } else { - auto res = this->core.read(paddr, 4, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + auto res = this->core.read(paddr, 4, reinterpret_cast(&instr)); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; + auto f = decode_instr(root, instr); if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, tu); + return (this->*f)(pc, instr, tu); } template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { From f38cc7d8b9c84daeb95b2304e9e1947f581c2a70 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 29 Jul 2023 17:55:37 +0200 Subject: [PATCH 129/184] updates LLVM build --- CMakeLists.txt | 12 +- ...m-vm_CORENAME.cpp.gtl => CORENAME.cpp.gtl} | 62 +++-- .../templates/llvm/CORENAME_cyles.txt.gtl | 9 - gen_input/templates/llvm/incl-CORENAME.h.gtl | 223 ------------------ gen_input/templates/llvm/src-CORENAME.cpp.gtl | 107 --------- src/vm/interp/vm_tgc_c.cpp | 1 + src/vm/llvm/vm_tgc_c.cpp | 59 +++-- src/vm/tcc/vm_tgc_c.cpp | 1 + 8 files changed, 96 insertions(+), 378 deletions(-) rename gen_input/templates/llvm/{vm-vm_CORENAME.cpp.gtl => CORENAME.cpp.gtl} (82%) delete mode 100644 gen_input/templates/llvm/CORENAME_cyles.txt.gtl delete mode 100644 gen_input/templates/llvm/incl-CORENAME.h.gtl delete mode 100644 gen_input/templates/llvm/src-CORENAME.cpp.gtl diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ad2123..64cd15b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,9 @@ set(LIB_SOURCES if(WITH_TCC) list(APPEND LIB_SOURCES src/vm/tcc/vm_tgc_c.cpp) endif() +if(WITH_LLVM) + list(APPEND LIB_SOURCES src/vm/llvm/vm_tgc_c.cpp src/vm/llvm/fp_impl.cpp) +endif() # library files FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp) @@ -70,7 +73,7 @@ endif() add_library(${PROJECT_NAME} ${LIB_SOURCES}) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow) + target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow) elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") target_compile_options(${PROJECT_NAME} PRIVATE /wd4293) endif() @@ -101,6 +104,13 @@ if(TARGET RapidJSON::RapidJSON) elseif(TARGET RapidJSON) target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON) endif() +if(WITH_LLVM) + target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS}) + target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS}) + if(BUILD_SHARED_LIBS) + target_link_libraries( ${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES}) + endif() +endif() set_target_properties(${PROJECT_NAME} PROPERTIES diff --git a/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl b/gen_input/templates/llvm/CORENAME.cpp.gtl similarity index 82% rename from gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl rename to gen_input/templates/llvm/CORENAME.cpp.gtl index d0a8067..5eb61cf 100644 --- a/gen_input/templates/llvm/vm-vm_CORENAME.cpp.gtl +++ b/gen_input/templates/llvm/CORENAME.cpp.gtl @@ -30,10 +30,9 @@ * *******************************************************************************/ +#include #include #include -#include -#include #include #include #include @@ -111,7 +110,7 @@ protected: void gen_trap_check(BasicBlock *bb); inline Value *gen_reg_load(unsigned i, unsigned level = 0) { - return this->builder.CreateLoad(get_reg_ptr(i), false); + return this->builder.CreateLoad(this->get_typeptr(i), get_reg_ptr(i), false); } inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { @@ -124,7 +123,7 @@ protected: // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; using this_class = vm_impl; using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, @@ -204,10 +203,10 @@ private: ****************************************************************************/ std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), + this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), 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->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true), this->gen_const(64U, 1)), get_reg_ptr(traits::ICOUNT), true); pc = pc + ((instr & 3) == 3 ? 4 : 2); @@ -244,20 +243,21 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; + // const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); auto *const data = (uint8_t *)&insn; paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { + //TODO: re-add page handling +// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary +// auto res = this->core.read(paddr, 2, data); +// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); +// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction +// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); +// } +// } else { auto res = this->core.read(paddr, 4, data); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } +// } if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; @@ -271,7 +271,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); + this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(arch::traits::NEXT_PC), get_reg_ptr(arch::traits::NEXT_PC), false)); } template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { @@ -295,18 +295,18 @@ template void vm_impl::gen_wait(unsigned type) { template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); + auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(arch::traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); std::vector args{this->core_ptr, this->adj_to64(trap_state_val), - this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; + this->adj_to64(this->builder.CreateLoad(this->get_typeptr(arch::traits::PC), get_reg_ptr(traits::PC), false))}; this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); - auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); + auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(arch::traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false); this->builder.CreateRet(trap_addr_val); } template inline void vm_impl::gen_trap_check(BasicBlock *bb) { - auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); + auto *v = this->builder.CreateLoad(this->get_typeptr(arch::traits::TRAP_STATE), get_reg_ptr(arch::traits::TRAP_STATE), true); this->gen_cond_branch(this->builder.CreateICmp( ICmpInst::ICMP_EQ, v, ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), @@ -323,3 +323,25 @@ std::unique_ptr create(arch::${coreD } } // namespace llvm } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto* vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto* vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} diff --git a/gen_input/templates/llvm/CORENAME_cyles.txt.gtl b/gen_input/templates/llvm/CORENAME_cyles.txt.gtl deleted file mode 100644 index 3a1ad8e..0000000 --- a/gen_input/templates/llvm/CORENAME_cyles.txt.gtl +++ /dev/null @@ -1,9 +0,0 @@ -{ - "${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","} - { - "name" : "${instr.name}", - "size" : ${instr.length}, - "delay" : ${generator.hasAttribute(instr.instruction, com.minres.coredsl.coreDsl.InstrAttribute.COND)?[1,1]:1} - }<%}%> - ] -} \ No newline at end of file diff --git a/gen_input/templates/llvm/incl-CORENAME.h.gtl b/gen_input/templates/llvm/incl-CORENAME.h.gtl deleted file mode 100644 index 0a5b99f..0000000 --- a/gen_input/templates/llvm/incl-CORENAME.h.gtl +++ /dev/null @@ -1,223 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -<% -import com.minres.coredsl.coreDsl.Register -import com.minres.coredsl.coreDsl.RegisterFile -import com.minres.coredsl.coreDsl.RegisterAlias -def getTypeSize(size){ - if(size > 32) 64 else if(size > 16) 32 else if(size > 8) 16 else 8 -} -def getOriginalName(reg){ - if( reg.original instanceof RegisterFile) { - if( reg.index != null ) { - return reg.original.name+generator.generateHostCode(reg.index) - } else { - return reg.original.name - } - } else if(reg.original instanceof Register){ - return reg.original.name - } -} -def getRegisterNames(){ - def regNames = [] - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{ - regNames+=reg.name.toLowerCase()+it - } - } else if(reg instanceof Register){ - regNames+=reg.name.toLowerCase() - } - } - return regNames -} -def getRegisterAliasNames(){ - def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]} - return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg -> - if( reg instanceof RegisterFile) { - return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() } - } else if(reg instanceof Register){ - regMap[reg.name]?:reg.name.toLowerCase() - } - }.flatten() -} -%> -#ifndef _${coreDef.name.toUpperCase()}_H_ -#define _${coreDef.name.toUpperCase()}_H_ - -#include -#include -#include -#include - -namespace iss { -namespace arch { - -struct ${coreDef.name.toLowerCase()}; - -template <> struct traits<${coreDef.name.toLowerCase()}> { - - constexpr static char const* const core_type = "${coreDef.name}"; - - static constexpr std::array reg_names{ - {"${getRegisterNames().join("\", \"")}"}}; - - static constexpr std::array reg_aliases{ - {"${getRegisterAliasNames().join("\", \"")}"}}; - - enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}}; - - constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0}; - - enum reg_e {<% - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{%> - ${reg.name}${it},<% - } - } else if(reg instanceof Register){ %> - ${reg.name},<% - } - }%> - NUM_REGS, - NEXT_${pc.name}=NUM_REGS, - TRAP_STATE, - PENDING_TRAP, - MACHINE_STATE, - LAST_BRANCH, - ICOUNT<% - allRegs.each { reg -> - if(reg instanceof RegisterAlias){ def aliasname=getOriginalName(reg)%>, - ${reg.name} = ${aliasname}<% - } - }%> - }; - - using reg_t = uint${regDataWidth}_t; - - using addr_t = uint${addrDataWidth}_t; - - using code_word_t = uint${addrDataWidth}_t; //TODO: check removal - - using virt_addr_t = iss::typed_addr_t; - - using phys_addr_t = iss::typed_addr_t; - - static constexpr std::array reg_bit_widths{ - {${regSizes.join(",")}}}; - - static constexpr std::array reg_byte_offsets{ - {${regOffsets.join(",")}}}; - - static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); - - enum sreg_flag_e { FLAGS }; - - enum mem_type_e { ${allSpaces.collect{s -> s.name}.join(', ')} }; -}; - -struct ${coreDef.name.toLowerCase()}: public arch_if { - - using virt_addr_t = typename traits<${coreDef.name.toLowerCase()}>::virt_addr_t; - using phys_addr_t = typename traits<${coreDef.name.toLowerCase()}>::phys_addr_t; - using reg_t = typename traits<${coreDef.name.toLowerCase()}>::reg_t; - using addr_t = typename traits<${coreDef.name.toLowerCase()}>::addr_t; - - ${coreDef.name.toLowerCase()}(); - ~${coreDef.name.toLowerCase()}(); - - void reset(uint64_t address=0) override; - - uint8_t* get_regs_base_ptr() override; - /// deprecated - void get_reg(short idx, std::vector& value) override {} - void set_reg(short idx, const std::vector& value) override {} - /// deprecated - bool get_flag(int flag) override {return false;} - void set_flag(int, bool value) override {}; - /// deprecated - void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; - - inline uint64_t get_icount() { return reg.icount; } - - inline bool should_stop() { return interrupt_sim; } - - inline uint64_t stop_code() { return interrupt_sim; } - - inline phys_addr_t v2p(const iss::addr_t& addr){ - if (addr.space != traits<${coreDef.name.toLowerCase()}>::MEM || addr.type == iss::address_type::PHYSICAL || - addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { - return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask); - } else - return virt2phys(addr); - } - - virtual phys_addr_t virt2phys(const iss::addr_t& addr); - - virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } - - inline uint32_t get_last_branch() { return reg.last_branch; } - -protected: - struct ${coreDef.name}_regs {<% - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{%> - uint${generator.getSize(reg)}_t ${reg.name}${it} = 0;<% - } - } else if(reg instanceof Register){ %> - uint${generator.getSize(reg)}_t ${reg.name} = 0;<% - } - }%> - uint${generator.getSize(pc)}_t NEXT_${pc.name} = 0; - uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; - uint64_t icount = 0; - } reg; - - std::array addr_mode; - - uint64_t interrupt_sim=0; -<% -def fcsr = allRegs.find {it.name=='FCSR'} -if(fcsr != null) {%> - uint${generator.getSize(fcsr)}_t get_fcsr(){return reg.FCSR;} - void set_fcsr(uint${generator.getSize(fcsr)}_t val){reg.FCSR = val;} -<%} else { %> - uint32_t get_fcsr(){return 0;} - void set_fcsr(uint32_t val){} -<%}%> -}; - -} -} -#endif /* _${coreDef.name.toUpperCase()}_H_ */ diff --git a/gen_input/templates/llvm/src-CORENAME.cpp.gtl b/gen_input/templates/llvm/src-CORENAME.cpp.gtl deleted file mode 100644 index 8ed478f..0000000 --- a/gen_input/templates/llvm/src-CORENAME.cpp.gtl +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - <% -import com.minres.coredsl.coreDsl.Register -import com.minres.coredsl.coreDsl.RegisterFile -import com.minres.coredsl.coreDsl.RegisterAlias -def getOriginalName(reg){ - if( reg.original instanceof RegisterFile) { - if( reg.index != null ) { - return reg.original.name+generator.generateHostCode(reg.index) - } else { - return reg.original.name - } - } else if(reg.original instanceof Register){ - return reg.original.name - } -} -def getRegisterNames(){ - def regNames = [] - allRegs.each { reg -> - if( reg instanceof RegisterFile) { - (reg.range.right..reg.range.left).each{ - regNames+=reg.name.toLowerCase()+it - } - } else if(reg instanceof Register){ - regNames+=reg.name.toLowerCase() - } - } - return regNames -} -def getRegisterAliasNames(){ - def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]} - return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg -> - if( reg instanceof RegisterFile) { - return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() } - } else if(reg instanceof Register){ - regMap[reg.name]?:reg.name.toLowerCase() - } - }.flatten() -} -%> -#include "util/ities.h" -#include -#include -#include -#include -#include - -using namespace iss::arch; - -constexpr std::array iss::arch::traits::reg_names; -constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; - -${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { - reg.icount = 0; -} - -${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default; - -void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { - for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits<${coreDef.name.toLowerCase()}>::reg_t),0)); - reg.PC=address; - reg.NEXT_PC=reg.PC; - reg.trap_state=0; - reg.machine_state=0x3; - reg.icount=0; -} - -uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { - return reinterpret_cast(®); -} - -${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address -} - diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index 3b409df..2d48193 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -253,6 +253,7 @@ private: //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ auto phys_pc = this->core.v2p(pc); + //TODO: re-add page handling //if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; // if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction diff --git a/src/vm/llvm/vm_tgc_c.cpp b/src/vm/llvm/vm_tgc_c.cpp index e712445..f289f0c 100644 --- a/src/vm/llvm/vm_tgc_c.cpp +++ b/src/vm/llvm/vm_tgc_c.cpp @@ -111,7 +111,7 @@ protected: void gen_trap_check(BasicBlock *bb); inline Value *gen_reg_load(unsigned i, unsigned level = 0) { - return this->builder.CreateLoad(get_reg_ptr(i), false); + return this->builder.CreateLoad(this->get_typeptr(i), get_reg_ptr(i), false); } inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { @@ -124,7 +124,7 @@ protected: // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; using this_class = vm_impl; using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, @@ -4042,10 +4042,10 @@ private: ****************************************************************************/ std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), + this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), 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->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true), this->gen_const(64U, 1)), get_reg_ptr(traits::ICOUNT), true); pc = pc + ((instr & 3) == 3 ? 4 : 2); @@ -4082,20 +4082,21 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; + // const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); auto *const data = (uint8_t *)&insn; paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { + //TODO: re-add page handling +// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary +// auto res = this->core.read(paddr, 2, data); +// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); +// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction +// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); +// } +// } else { auto res = this->core.read(paddr, 4, data); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } +// } if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; @@ -4109,7 +4110,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); + this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(arch::traits::NEXT_PC), get_reg_ptr(arch::traits::NEXT_PC), false)); } template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { @@ -4133,18 +4134,18 @@ template void vm_impl::gen_wait(unsigned type) { template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); + auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(arch::traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); std::vector args{this->core_ptr, this->adj_to64(trap_state_val), - this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; + this->adj_to64(this->builder.CreateLoad(this->get_typeptr(arch::traits::PC), get_reg_ptr(traits::PC), false))}; this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); - auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); + auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(arch::traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false); this->builder.CreateRet(trap_addr_val); } template inline void vm_impl::gen_trap_check(BasicBlock *bb) { - auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); + auto *v = this->builder.CreateLoad(this->get_typeptr(arch::traits::TRAP_STATE), get_reg_ptr(arch::traits::TRAP_STATE), true); this->gen_cond_branch(this->builder.CreateICmp( ICmpInst::ICMP_EQ, v, ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), @@ -4161,3 +4162,25 @@ std::unique_ptr create(arch::tgc_c *core, unsigned short por } } // namespace llvm } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("tgc_c|m_p|llvm", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto* vm = new llvm::tgc_c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("tgc_c|mu_p|llvm", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto* vm = new llvm::tgc_c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index fee3a87..43c22bb 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -3168,6 +3168,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, phys_addr_t paddr(pc); auto *const data = (uint8_t *)&insn; paddr = this->core.v2p(pc); + //TODO: re-add page handling // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // auto res = this->core.read(paddr, 2, data); // if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); From 24de2bbdf5fa0b3514a715078a00995a91eb33ae Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 30 Jul 2023 13:55:57 +0200 Subject: [PATCH 130/184] purge build system --- CMakeLists.txt | 116 +++++++++++++++++++-------------------- src/iss/plugin/pctrace.h | 1 - 2 files changed, 56 insertions(+), 61 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 750c35e..b21636c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,41 +9,27 @@ include(GNUInstallDirs) include(flink) find_package(elfio QUIET) -find_package(Boost COMPONENTS coroutine) find_package(jsoncpp) - -if(TARGET tcc::tcc) - set(WITH_TCC ON) -endif() - -if(WITH_LLVM) - if(DEFINED ENV{LLVM_HOME}) - find_path (LLVM_DIR LLVM-Config.cmake $ENV{LLVM_HOME}/lib/cmake/llvm) - endif() - find_package(LLVM QUIET CONFIG) - if(LLVM_FOUND) - message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") - message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") - llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser) - else() - find_package(LLVM REQUIRED LLVMSupport LLVMCore LLVMMCJIT LLVMX86CodeGen LLVMX86AsmParser) - endif() -endif() +find_package(Boost COMPONENTS coroutine REQUIRED) add_subdirectory(softfloat) set(LIB_SOURCES - src/iss/plugin/instruction_count.cpp src/iss/arch/tgc_c.cpp src/vm/tcc/vm_tgc_c.cpp src/vm/interp/vm_tgc_c.cpp src/vm/fp_functions.cpp ) if(WITH_TCC) - list(APPEND LIB_SOURCES src/vm/tcc/vm_tgc_c.cpp) + list(APPEND LIB_SOURCES + src/vm/tcc/vm_tgc_c.cpp + ) endif() if(WITH_LLVM) - list(APPEND LIB_SOURCES src/vm/llvm/vm_tgc_c.cpp src/vm/llvm/fp_impl.cpp) + list(APPEND LIB_SOURCES + src/vm/llvm/vm_tgc_c.cpp + src/vm/llvm/fp_impl.cpp + ) endif() # library files @@ -55,7 +41,7 @@ foreach(FILEPATH ${GEN_ISS_SOURCES}) string(TOUPPER ${CORE} CORE) list(APPEND LIB_DEFINES CORE_${CORE}) endforeach() -message("Core defines are ${LIB_DEFINES}") +message(STATUS "Core defines are ${LIB_DEFINES}") if(WITH_LLVM) FILE(GLOB LLVM_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp) @@ -67,10 +53,17 @@ if(WITH_TCC) list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) endif() -if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON) - list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp src/iss/plugin/pctrace.cpp) +if(TARGET RapidJSON) + list(APPEND LIB_SOURCES + src/iss/plugin/cycle_estimate.cpp + src/iss/plugin/pctrace.cpp + ) +endif() +if(TARGET jsoncpp::jsoncpp) + list(APPEND LIB_SOURCES + src/iss/plugin/instruction_count.cpp + ) endif() - # Define the library add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES}) @@ -81,37 +74,25 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") endif() target_include_directories(${PROJECT_NAME} PUBLIC src) target_include_directories(${PROJECT_NAME} PUBLIC src-gen) -target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util Boost::coroutine) + +target_force_link_libraries(${PROJECT_NAME} PRIVATE dbt-rise-core) +# only re-export the include paths +get_target_property(DBT_CORE_INCL dbt-rise-core INTERFACE_INCLUDE_DIRECTORIES) +target_include_directories(${PROJECT_NAME} INTERFACE ${DBT_CORE_INCL}) +get_target_property(DBT_CORE_DEFS dbt-rise-core INTERFACE_COMPILE_DEFINITIONS) +target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS}) + +target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine) if(TARGET jsoncpp::jsoncpp) target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp::jsoncpp) -else() - target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp) -endif() - -target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-core) - -if(TARGET elfio::elfio) - target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio) -else() - message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing") endif() if(TARGET lz4::lz4) target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_LZ4) target_link_libraries(${PROJECT_NAME} PUBLIC lz4::lz4) endif() -if(TARGET RapidJSON::RapidJSON) - target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON::RapidJSON) -elseif(TARGET RapidJSON) +if(TARGET RapidJSON) target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON) endif() -if(WITH_LLVM) - target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS}) - target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS}) - if(BUILD_SHARED_LIBS) - target_link_libraries( ${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES}) - endif() -endif() - set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} @@ -156,15 +137,16 @@ foreach(F IN LISTS TGC_SOURCES) endif() endforeach() -if(WITH_LLVM) - target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM) - target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) -endif() -if(WITH_TCC) - target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC) -endif() -# Links the target exe against the libraries -target_force_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc) +#if(WITH_LLVM) +# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM) +# #target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) +#endif() +#if(WITH_TCC) +# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC) +#endif() + +target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc fmt::fmt) + if(TARGET Boost::program_options) target_link_libraries(${PROJECT_NAME} PUBLIC Boost::program_options) else() @@ -184,6 +166,20 @@ install(TARGETS tgc-sim PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package) INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers ) + +if(BUILD_TESTING) + # ... CMake code to create tests ... + add_test(NAME tgc-sim-interp + COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend interp) + if(WITH_TCC) + add_test(NAME tgc-sim-tcc + COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend tcc) + endif() + if(WITH_LLVM) + add_test(NAME tgc-sim-llvm + COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm) + endif() +endif() ############################################################################### # ############################################################################### @@ -206,9 +202,9 @@ if(TARGET scc-sysc) endif() endforeach() target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc) - if(WITH_LLVM) - target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) - endif() +# if(WITH_LLVM) +# target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) +# endif() set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h) set_target_properties(${PROJECT_NAME} PROPERTIES diff --git a/src/iss/plugin/pctrace.h b/src/iss/plugin/pctrace.h index 092719d..0e89110 100644 --- a/src/iss/plugin/pctrace.h +++ b/src/iss/plugin/pctrace.h @@ -37,7 +37,6 @@ #include #include "iss/instrumentation_if.h" -#include #include #include From e151416f5878ccc2bfca00e7e7c86084c46e40bd Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 31 Jul 2023 12:55:09 +0200 Subject: [PATCH 131/184] fixes systemc factory registration --- gen_input/templates/CORENAME_sysc.cpp.gtl | 14 ++++++++------ src/sysc/register_tgc_c.cpp | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/gen_input/templates/CORENAME_sysc.cpp.gtl b/gen_input/templates/CORENAME_sysc.cpp.gtl index e56e7db..3ef2df9 100644 --- a/gen_input/templates/CORENAME_sysc.cpp.gtl +++ b/gen_input/templates/CORENAME_sysc.cpp.gtl @@ -36,6 +36,7 @@ #include #include "sc_core_adapter.h" #include "core_complex.h" +#include namespace iss { namespace interp { @@ -55,16 +56,17 @@ volatile std::array ${coreDef.name.toLowerCase()}_init = { } #if defined(WITH_TCC) namespace tcc { +using namespace sysc; volatile std::array ${coreDef.name.toLowerCase()}_init = { - core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ - auto cc = reinterpret_cast(data); + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }), - core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ - auto cc = reinterpret_cast(data); + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }) }; } diff --git a/src/sysc/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp index 31a99a5..4fd8eac 100644 --- a/src/sysc/register_tgc_c.cpp +++ b/src/sysc/register_tgc_c.cpp @@ -36,6 +36,7 @@ #include #include "sc_core_adapter.h" #include "core_complex.h" +#include namespace iss { namespace interp { @@ -55,16 +56,17 @@ volatile std::array tgc_init = { } #if defined(WITH_TCC) namespace tcc { +using namespace sysc; volatile std::array tgc_init = { - core_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ - auto cc = reinterpret_cast(data); + iss_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }), - core_factory::instance().register_creator("tgc_c|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ - auto cc = reinterpret_cast(data); + iss_factory::instance().register_creator("tgc_c|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }) }; } From 20e920338c43c7e8960c158877904b6ab9abb1a3 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 4 Aug 2023 13:08:10 +0200 Subject: [PATCH 132/184] removes v2p function --- gen_input/templates/CORENAME.cpp.gtl | 4 ++-- gen_input/templates/CORENAME.h.gtl | 8 -------- src/iss/arch/riscv_hart_m_p.h | 17 ++++++++--------- src/iss/arch/riscv_hart_msu_vp.h | 11 ++++------- src/iss/arch/riscv_hart_mu_p.h | 19 +++++++++---------- src/iss/arch/tgc_c.cpp | 4 ++-- src/iss/arch/tgc_c.h | 9 --------- src/vm/interp/vm_tgc_c.cpp | 25 ++++++++++++++++--------- src/vm/llvm/vm_tgc_c.cpp | 3 ++- src/vm/tcc/vm_tgc_c.cpp | 3 ++- 10 files changed, 45 insertions(+), 58 deletions(-) diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl index b7468c7..ebdff65 100644 --- a/gen_input/templates/CORENAME.cpp.gtl +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -70,7 +70,7 @@ uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { return reinterpret_cast(®); } -${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address +${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &addr) { + return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask); } diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 2debd97..96ba762 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -137,14 +137,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { inline uint64_t stop_code() { return interrupt_sim; } - inline phys_addr_t v2p(const iss::addr_t& addr){ - if (addr.space != traits<${coreDef.name.toLowerCase()}>::MEM || addr.type == iss::address_type::PHYSICAL || - addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { - return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask); - } else - return virt2phys(addr); - } - virtual phys_addr_t virt2phys(const iss::addr_t& addr); virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 5df25e2..632bdd2 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -666,7 +666,7 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce fault_data=addr; return iss::Err; } - auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); + phys_addr_t phys_addr{access, space, addr}; auto res = iss::Err; if(access != access_type::FETCH && memfn_range.size()){ auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ @@ -759,7 +759,7 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc fault_data=addr; return iss::Err; } - auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); + phys_addr_t phys_addr{access, space, addr}; auto res = iss::Err; if(access != access_type::FETCH && memfn_range.size()){ auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ @@ -784,9 +784,8 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc return iss::Err; } - phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr}); - if ((paddr.val + length) > mem.size()) return iss::Err; - switch (paddr.val) { + if ((addr + length) > mem.size()) return iss::Err; + switch (addr) { case 0x10013000: // UART0 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg uart_buf << (char)data[0]; @@ -798,16 +797,16 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc } return iss::Ok; case 0x10008000: { // HFROSC base, hfrosccfg reg - auto &p = mem(paddr.val / mem.page_size); - auto offs = paddr.val & mem.page_addr_mask; + auto &p = mem(addr / mem.page_size); + auto offs = addr & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); auto &x = *(p.data() + offs + 3); if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 return iss::Ok; } case 0x10008008: { // HFROSC base, pllcfg reg - auto &p = mem(paddr.val / mem.page_size); - auto offs = paddr.val & mem.page_addr_mask; + auto &p = mem(addr / mem.page_size); + auto offs = addr & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); auto &x = *(p.data() + offs + 3); x |= 0x80; // set pll lock upon writing diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index b107aac..23a805b 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -430,6 +430,7 @@ template riscv_hart_msu_vp::riscv_hart_msu_vp() : state() , instr_if(*this) { + this->_has_mmu = true; // reset values csr[misa] = traits::MISA_VAL; csr[mvendorid] = 0x669; @@ -632,9 +633,7 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ return res; } } - auto res = type==iss::address_type::PHYSICAL? - read_mem( BASE::v2p(phys_addr_t{access, space, addr}), length, data): - read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); + auto res = read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); if (unlikely(res != iss::Ok)){ this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; @@ -719,6 +718,7 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access this->reg.trap_state = (1 << 31); // issue trap 0 return iss::Err; } + phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr}); try { if (unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary vm_info vm = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp); @@ -731,9 +731,7 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access return res; } } - auto res = type==iss::address_type::PHYSICAL? - write_mem(phys_addr_t{access, space, addr}, length, data): - write_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); + auto res = write_mem(paddr, length, data); if (unlikely(res != iss::Ok)) { this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; @@ -745,7 +743,6 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access return iss::Err; } - phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr}); if ((paddr.val + length) > mem.size()) return iss::Err; switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 6ac7d9b..da30b21 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -834,7 +834,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc fault_data=addr; return iss::Err; } - auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); + phys_addr_t phys_addr{access, space, addr}; auto res = iss::Err; if(!is_fetch(access) && memfn_range.size()){ auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ @@ -935,7 +935,7 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac fault_data=addr; return iss::Err; } - auto phys_addr = type==iss::address_type::PHYSICAL?phys_addr_t{access, space, addr}:BASE::v2p(iss::addr_t{access, type, space, addr}); + phys_addr_t phys_addr{access, space, addr}; auto res = iss::Err; if(!is_fetch(access) && memfn_range.size()){ auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ @@ -960,30 +960,29 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac return iss::Err; } - phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr}); - if ((paddr.val + length) > mem.size()) return iss::Err; - switch (paddr.val) { + if ((addr + length) > mem.size()) return iss::Err; + switch (addr) { 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 + // LOG(INFO)<<"UART"<<((addr>>16)&0x3)<<" send // '"<(®); } -tgc_c::phys_addr_t tgc_c::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address +tgc_c::phys_addr_t tgc_c::virt2phys(const iss::addr_t &addr) { + return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); } diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc_c.h index 2f33ca5..af3b3ba 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc_c.h @@ -195,14 +195,6 @@ struct tgc_c: public arch_if { inline uint64_t stop_code() { return interrupt_sim; } - inline phys_addr_t v2p(const iss::addr_t& addr){ - if (addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || - addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { - return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); - } else - return virt2phys(addr); - } - virtual phys_addr_t virt2phys(const iss::addr_t& addr); virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } @@ -262,7 +254,6 @@ struct tgc_c: public arch_if { uint32_t get_fcsr(){return 0;} void set_fcsr(uint32_t val){} - }; } diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index e070215..8ad108e 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -259,15 +259,22 @@ private: }}; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ - auto phys_pc = this->core.v2p(pc); - //TODO: re-add page handling - //if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - // if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; - // if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction - // if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) return iss::Err; - //} else { - if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err; - //} + if(this->core.has_mmu()) { + auto phys_pc = this->core.virt2phys(pc); +// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary +// if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; +// if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction +// if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) +// return iss::Err; +// } else { + if (this->core.read(phys_pc, 4, data) != iss::Ok) + return iss::Err; +// } + } else { + if (this->core.read(phys_addr_t(pc.access, pc.space, pc.val), 4, data) != iss::Ok) + return iss::Err; + + } return iss::Ok; } void populate_decoding_tree(decoding_tree_node* root){ diff --git a/src/vm/llvm/vm_tgc_c.cpp b/src/vm/llvm/vm_tgc_c.cpp index f289f0c..d256089 100644 --- a/src/vm/llvm/vm_tgc_c.cpp +++ b/src/vm/llvm/vm_tgc_c.cpp @@ -4085,7 +4085,8 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); + if(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); //TODO: re-add page handling // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // auto res = this->core.read(paddr, 2, data); diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc_c.cpp index eeca8ec..1be78b8 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc_c.cpp @@ -3174,7 +3174,8 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, enum {TRAP_ID=1<<16}; code_word_t instr = 0; phys_addr_t paddr(pc); - paddr = this->core.v2p(pc); + if(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); //TODO: re-add page handling // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // auto res = this->core.read(paddr, 2, data); From 18e08cfc50c91ac68bd9cfb3aa5cfe92b1f0777c Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 8 Aug 2023 06:23:38 +0200 Subject: [PATCH 133/184] fixes missing template updates --- gen_input/templates/interp/CORENAME.cpp.gtl | 23 +++++++++++++++++---- gen_input/templates/tcc/CORENAME.cpp.gtl | 20 +++++++++++++----- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 333a9eb..7645bdc 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -179,10 +179,25 @@ private: }}; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ - auto phys_pc = this->core.v2p(pc); - if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err; + if(this->core.has_mmu()) { + auto phys_pc = this->core.virt2phys(pc); +// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary +// if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; +// if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction +// if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) +// return iss::Err; +// } else { + if (this->core.read(phys_pc, 4, data) != iss::Ok) + return iss::Err; +// } + } else { + if (this->core.read(phys_addr_t(pc.access, pc.space, pc.val), 4, data) != iss::Ok) + return iss::Err; + + } return iss::Ok; } + void populate_decoding_tree(decoding_tree_node* root){ //create submask for(auto instr: root->instrs){ @@ -359,13 +374,13 @@ std::unique_ptr create(arch::${coreD namespace iss { namespace { volatile std::array dummy = { - core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void*) -> std::tuple{ + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_m_p(); auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; }), - core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned port, void*) -> std::tuple{ + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_mu_p(); auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index 832422a..fb912cd 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -265,9 +265,19 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, enum {TRAP_ID=1<<16}; code_word_t instr = 0; phys_addr_t paddr(pc); - paddr = this->core.v2p(pc); - auto res = this->core.read(paddr, 4, reinterpret_cast(&instr)); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); + if(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); + //TODO: re-add page handling +// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary +// auto res = this->core.read(paddr, 2, data); +// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); +// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction +// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); +// } +// } else { + auto res = this->core.read(paddr, 4, reinterpret_cast(&instr)); + if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); +// } if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; @@ -316,13 +326,13 @@ std::unique_ptr create(arch::${coreD namespace iss { namespace { volatile std::array dummy = { - core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> std::tuple{ + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_m_p(); auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; }), - core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_mu_p(); auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); From c8a4a4c73633ae88900e5075746d4ca3636745f4 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 27 Aug 2023 15:17:12 +0200 Subject: [PATCH 134/184] renames core(s) --- CMakeLists.txt | 8 +-- gen_input/TGC_C.core_desc | 4 +- src/iss/arch/{tgc_c.cpp => tgc5c.cpp} | 24 ++++----- src/iss/arch/{tgc_c.h => tgc5c.h} | 32 ++++++------ src/iss/arch/tgc_mapper.h | 52 ++++++++++---------- src/sysc/core_complex.cpp | 2 +- src/sysc/core_complex.h | 6 +-- src/sysc/register_tgc_c.cpp | 18 +++---- src/vm/interp/{vm_tgc_c.cpp => vm_tgc5c.cpp} | 22 ++++----- src/vm/llvm/{vm_tgc_c.cpp => vm_tgc5c.cpp} | 10 ++-- src/vm/tcc/{vm_tgc_c.cpp => vm_tgc5c.cpp} | 22 ++++----- 11 files changed, 100 insertions(+), 100 deletions(-) rename src/iss/arch/{tgc_c.cpp => tgc5c.cpp} (84%) rename src/iss/arch/{tgc_c.h => tgc5c.h} (93%) rename src/vm/interp/{vm_tgc_c.cpp => vm_tgc5c.cpp} (99%) rename src/vm/llvm/{vm_tgc_c.cpp => vm_tgc5c.cpp} (99%) rename src/vm/tcc/{vm_tgc_c.cpp => vm_tgc5c.cpp} (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d7977b3..fde9fdc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,13 +31,13 @@ add_subdirectory(softfloat) set(LIB_SOURCES src/iss/plugin/instruction_count.cpp - src/iss/arch/tgc_c.cpp - src/vm/tcc/vm_tgc_c.cpp - src/vm/interp/vm_tgc_c.cpp + src/iss/arch/tgc5c.cpp + src/vm/tcc/vm_tgc5c.cpp + src/vm/interp/vm_tgc5c.cpp src/vm/fp_functions.cpp ) if(WITH_TCC) - list(APPEND LIB_SOURCES src/vm/tcc/vm_tgc_c.cpp) + list(APPEND LIB_SOURCES src/vm/tcc/vm_tgc5c.cpp) endif() # library files diff --git a/gen_input/TGC_C.core_desc b/gen_input/TGC_C.core_desc index 8377d41..f57a6c4 100644 --- a/gen_input/TGC_C.core_desc +++ b/gen_input/TGC_C.core_desc @@ -1,8 +1,8 @@ -import "ISA/RV32I.core_desc" +import "ISA/RVI.core_desc" import "ISA/RVM.core_desc" import "ISA/RVC.core_desc" -Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { +Core TGC5C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { architectural_state { XLEN=32; // definitions for the architecture wrapper diff --git a/src/iss/arch/tgc_c.cpp b/src/iss/arch/tgc5c.cpp similarity index 84% rename from src/iss/arch/tgc_c.cpp rename to src/iss/arch/tgc5c.cpp index e4fc905..2b9fc3f 100644 --- a/src/iss/arch/tgc_c.cpp +++ b/src/iss/arch/tgc5c.cpp @@ -30,7 +30,7 @@ * *******************************************************************************/ -#include "tgc_c.h" +#include "tgc5c.h" #include "util/ities.h" #include #include @@ -39,18 +39,18 @@ using namespace iss::arch; -constexpr std::array iss::arch::traits::reg_names; -constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; +constexpr std::array iss::arch::traits::reg_names; +constexpr std::array iss::arch::traits::reg_aliases; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; -tgc_c::tgc_c() = default; +tgc5c::tgc5c() = default; -tgc_c::~tgc_c() = default; +tgc5c::~tgc5c() = default; -void tgc_c::reset(uint64_t address) { - auto base_ptr = reinterpret_cast::reg_t*>(get_regs_base_ptr()); - for(size_t i=0; i::NUM_REGS; ++i) +void tgc5c::reset(uint64_t address) { + auto base_ptr = reinterpret_cast::reg_t*>(get_regs_base_ptr()); + for(size_t i=0; i::NUM_REGS; ++i) *(base_ptr+i)=0; reg.PC=address; reg.NEXT_PC=reg.PC; @@ -59,11 +59,11 @@ void tgc_c::reset(uint64_t address) { reg.icount=0; } -uint8_t *tgc_c::get_regs_base_ptr() { +uint8_t *tgc5c::get_regs_base_ptr() { return reinterpret_cast(®); } -tgc_c::phys_addr_t tgc_c::virt2phys(const iss::addr_t &pc) { +tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t &pc) { return phys_addr_t(pc); // change logical address to physical address } diff --git a/src/iss/arch/tgc_c.h b/src/iss/arch/tgc5c.h similarity index 93% rename from src/iss/arch/tgc_c.h rename to src/iss/arch/tgc5c.h index 2f33ca5..38e2e31 100644 --- a/src/iss/arch/tgc_c.h +++ b/src/iss/arch/tgc5c.h @@ -30,8 +30,8 @@ * *******************************************************************************/ -#ifndef _TGC_C_H_ -#define _TGC_C_H_ +#ifndef _TGC5C_H_ +#define _TGC5C_H_ #include #include @@ -41,11 +41,11 @@ namespace iss { namespace arch { -struct tgc_c; +struct tgc5c; -template <> struct traits { +template <> struct traits { - constexpr static char const* const core_type = "TGC_C"; + constexpr static char const* const core_type = "TGC5C"; static constexpr std::array reg_names{ {"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", "X29", "X30", "X31", "PC", "NEXT_PC", "PRIV", "DPC"}}; @@ -175,15 +175,15 @@ template <> struct traits { }; }; -struct tgc_c: public arch_if { +struct tgc5c: 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; + 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; - tgc_c(); - ~tgc_c(); + tgc5c(); + ~tgc5c(); void reset(uint64_t address=0) override; @@ -196,9 +196,9 @@ struct tgc_c: public arch_if { inline uint64_t stop_code() { return interrupt_sim; } inline phys_addr_t v2p(const iss::addr_t& addr){ - if (addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || + if (addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { - return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); + return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); } else return virt2phys(addr); } @@ -211,7 +211,7 @@ struct tgc_c: public arch_if { #pragma pack(push, 1) - struct TGC_C_regs { + struct TGC5C_regs { uint32_t X0 = 0; uint32_t X1 = 0; uint32_t X2 = 0; @@ -267,4 +267,4 @@ struct tgc_c: public arch_if { } } -#endif /* _TGC_C_H_ */ +#endif /* _TGC5C_H_ */ diff --git a/src/iss/arch/tgc_mapper.h b/src/iss/arch/tgc_mapper.h index ebacac0..83f82da 100644 --- a/src/iss/arch/tgc_mapper.h +++ b/src/iss/arch/tgc_mapper.h @@ -2,49 +2,49 @@ #define _ISS_ARCH_TGC_MAPPER_H #include "riscv_hart_m_p.h" -#include "tgc_c.h" -using tgc_c_plat_type = iss::arch::riscv_hart_m_p; -#ifdef CORE_TGC_A +#include "tgc5c.h" +using tgc5c_plat_type = iss::arch::riscv_hart_m_p; +#ifdef CORE_TGC5A #include "riscv_hart_m_p.h" -#include -using tgc_a_plat_type = iss::arch::riscv_hart_m_p; +#include +using tgc5a_plat_type = iss::arch::riscv_hart_m_p; #endif -#ifdef CORE_TGC_B +#ifdef CORE_TGC5B #include "riscv_hart_m_p.h" -#include -using tgc_b_plat_type = iss::arch::riscv_hart_m_p; +#include +using tgc5b_plat_type = iss::arch::riscv_hart_m_p; #endif -#ifdef CORE_TGC_C_XRB_NN +#ifdef CORE_TGC5C_XRB_NN #include "riscv_hart_m_p.h" #include "hwl.h" -#include -using tgc_c_xrb_nn_plat_type = iss::arch::hwl>; +#include +using tgc5c_xrb_nn_plat_type = iss::arch::hwl>; #endif -#ifdef CORE_TGC_D +#ifdef CORE_TGC5D #include "riscv_hart_mu_p.h" -#include -using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; +#include +using tgc5d_plat_type = iss::arch::riscv_hart_mu_p; #endif -#ifdef CORE_TGC_D_XRB_MAC +#ifdef CORE_TGC5D_XRB_MAC #include "riscv_hart_mu_p.h" -#include -using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p; +#include +using tgc5d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p; #endif -#ifdef CORE_TGC_D_XRB_NN +#ifdef CORE_TGC5D_XRB_NN #include "riscv_hart_mu_p.h" #include "hwl.h" -#include -using tgc_d_xrb_nn_plat_type = iss::arch::hwl>; +#include +using tgc5d_xrb_nn_plat_type = iss::arch::hwl>; #endif -#ifdef CORE_TGC_E +#ifdef CORE_TGC5E #include "riscv_hart_mu_p.h" -#include -using tgc_e_plat_type = iss::arch::riscv_hart_mu_p; +#include +using tgc5e_plat_type = iss::arch::riscv_hart_mu_p; #endif -#ifdef CORE_TGC_X +#ifdef CORE_TGC5X #include "riscv_hart_mu_p.h" -#include -using tgc_x_plat_type = iss::arch::riscv_hart_mu_p; +#include +using tgc5x_plat_type = iss::arch::riscv_hart_mu_p; #endif #endif diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index e3b0433..437412d 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -145,7 +145,7 @@ public: std::tie(cpu, vm) = f.create(type+"|"+backend); } else { auto base_isa = type.substr(0, 5); - if(base_isa=="tgc_d" || base_isa=="tgc_e") { + if(base_isa=="tgc5d" || base_isa=="tgc5e") { std::tie(cpu, vm) = f.create(type + "|mu_p_clic_pmp|" + backend, gdb_port); } else { std::tie(cpu, vm) = f.create(type + "|m_p|" + backend, gdb_port); diff --git a/src/sysc/core_complex.h b/src/sysc/core_complex.h index f9430f4..ec3a05a 100644 --- a/src/sysc/core_complex.h +++ b/src/sysc/core_complex.h @@ -96,7 +96,7 @@ public: cci::cci_param reset_address{"reset_address", 0ULL}; - cci::cci_param core_type{"core_type", "tgc_c"}; + cci::cci_param core_type{"core_type", "tgc5c"}; cci::cci_param backend{"backend", "interp"}; @@ -121,7 +121,7 @@ public: scml_property reset_address{"reset_address", 0ULL}; - scml_property core_type{"core_type", "tgc_c"}; + scml_property core_type{"core_type", "tgc5c"}; scml_property backend{"backend", "interp"}; @@ -139,7 +139,7 @@ public: , elf_file{"elf_file", ""} , enable_disass{"enable_disass", false} , reset_address{"reset_address", 0ULL} - , core_type{"core_type", "tgc_c"} + , core_type{"core_type", "tgc5c"} , backend{"backend", "interp"} , gdb_server_port{"gdb_server_port", 0} , dump_ir{"dump_ir", false} diff --git a/src/sysc/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp index 1fe4194..cf3ccd5 100644 --- a/src/sysc/register_tgc_c.cpp +++ b/src/sysc/register_tgc_c.cpp @@ -31,7 +31,7 @@ *******************************************************************************/ #include -#include +#include #include #include #include "sc_core_adapter.h" @@ -40,14 +40,14 @@ namespace iss { namespace interp { volatile std::array tgc_init = { - core_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ + core_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); - arch::tgc_c* cpu = new sc_core_adapter>(cc); + arch::tgc5c* cpu = new sc_core_adapter>(cc); return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; }), - core_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ + core_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); - arch::tgc_c* cpu = new sc_core_adapter>(cc); + arch::tgc5c* cpu = new sc_core_adapter>(cc); return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; }) }; @@ -55,14 +55,14 @@ volatile std::array tgc_init = { #if defined(WITH_TCC) namespace tcc { volatile std::array tgc_init = { - core_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + core_factory::instance().register_creator("tgc5c|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); - arch::tgc_c* cpu = new sc_core_adapter>(cc); + arch::tgc5c* cpu = new sc_core_adapter>(cc); return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; }), - core_factory::instance().register_creator("tgc_c|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + core_factory::instance().register_creator("tgc5c|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ auto cc = reinterpret_cast(data); - arch::tgc_c* cpu = new sc_core_adapter>(cc); + arch::tgc5c* cpu = new sc_core_adapter>(cc); return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; }) }; diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc5c.cpp similarity index 99% rename from src/vm/interp/vm_tgc_c.cpp rename to src/vm/interp/vm_tgc5c.cpp index 3b409df..07218cf 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -30,7 +30,7 @@ * *******************************************************************************/ -#include +#include #include #include #include @@ -50,7 +50,7 @@ namespace iss { namespace interp { -namespace tgc_c { +namespace tgc5c { using namespace iss::arch; using namespace iss::debugger; using namespace std::placeholders; @@ -2635,11 +2635,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co return pc; } -} // namespace tgc_c +} // namespace tgc5c template <> -std::unique_ptr create(arch::tgc_c *core, unsigned short port, bool dump) { - auto ret = new tgc_c::vm_impl(*core, dump); +std::unique_ptr create(arch::tgc5c *core, unsigned short port, bool dump) { + auto ret = new tgc5c::vm_impl(*core, dump); if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } @@ -2652,15 +2652,15 @@ std::unique_ptr create(arch::tgc_c *core, unsigned short por namespace iss { namespace { volatile std::array dummy = { - core_factory::instance().register_creator("tgc_c|m_p|interp", [](unsigned port, void*) -> std::tuple{ - auto* cpu = new iss::arch::riscv_hart_m_p(); - auto vm = new interp::tgc_c::vm_impl(*cpu, false); + core_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new interp::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; }), - core_factory::instance().register_creator("tgc_c|mu_p|interp", [](unsigned port, void*) -> std::tuple{ - auto* cpu = new iss::arch::riscv_hart_mu_p(); - auto vm = new interp::tgc_c::vm_impl(*cpu, false); + core_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new interp::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; }) diff --git a/src/vm/llvm/vm_tgc_c.cpp b/src/vm/llvm/vm_tgc5c.cpp similarity index 99% rename from src/vm/llvm/vm_tgc_c.cpp rename to src/vm/llvm/vm_tgc5c.cpp index e712445..f65f998 100644 --- a/src/vm/llvm/vm_tgc_c.cpp +++ b/src/vm/llvm/vm_tgc5c.cpp @@ -30,8 +30,8 @@ * *******************************************************************************/ -#include #include +#include #include #include #include @@ -52,7 +52,7 @@ namespace fp_impl { void add_fp_functions_2_module(::llvm::Module *, unsigned, unsigned); } -namespace tgc_c { +namespace tgc5c { using namespace ::llvm; using namespace iss::arch; using namespace iss::debugger; @@ -4151,11 +4151,11 @@ template inline void vm_impl::gen_trap_check(BasicBlock *b bb, this->trap_blk, 1); } -} // namespace tgc_c +} // namespace tgc5c template <> -std::unique_ptr create(arch::tgc_c *core, unsigned short port, bool dump) { - auto ret = new tgc_c::vm_impl(*core, dump); +std::unique_ptr create(arch::tgc5c *core, unsigned short port, bool dump) { + auto ret = new tgc5c::vm_impl(*core, dump); if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } diff --git a/src/vm/tcc/vm_tgc_c.cpp b/src/vm/tcc/vm_tgc5c.cpp similarity index 99% rename from src/vm/tcc/vm_tgc_c.cpp rename to src/vm/tcc/vm_tgc5c.cpp index 371aa95..55bc1f6 100644 --- a/src/vm/tcc/vm_tgc_c.cpp +++ b/src/vm/tcc/vm_tgc5c.cpp @@ -30,7 +30,7 @@ * *******************************************************************************/ -#include +#include #include #include #include @@ -48,7 +48,7 @@ namespace iss { namespace tcc { -namespace tgc_c { +namespace tgc5c { using namespace iss::arch; using namespace iss::debugger; @@ -3210,11 +3210,11 @@ template void vm_impl::gen_trap_behavior(tu_builder& tu) { tu("return *next_pc;"); } -} // namespace tgc_c +} // namespace tgc5c template <> -std::unique_ptr create(arch::tgc_c *core, unsigned short port, bool dump) { - auto ret = new tgc_c::vm_impl(*core, dump); +std::unique_ptr create(arch::tgc5c *core, unsigned short port, bool dump) { + auto ret = new tgc5c::vm_impl(*core, dump); if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } @@ -3227,15 +3227,15 @@ std::unique_ptr create(arch::tgc_c *core, unsigned short por namespace iss { namespace { volatile std::array dummy = { - core_factory::instance().register_creator("tgc_c|m_p|tcc", [](unsigned port, void*) -> std::tuple{ - auto* cpu = new iss::arch::riscv_hart_m_p(); - auto vm = new tcc::tgc_c::vm_impl(*cpu, false); + core_factory::instance().register_creator("tgc5c|m_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto vm = new tcc::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; }), - core_factory::instance().register_creator("tgc_c|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ - auto* cpu = new iss::arch::riscv_hart_mu_p(); - auto vm = new tcc::tgc_c::vm_impl(*cpu, false); + core_factory::instance().register_creator("tgc5c|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto vm = new tcc::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; }) From b5d915f389c757e81355fb19f24e16152bd839c6 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 30 Aug 2023 15:49:28 +0200 Subject: [PATCH 135/184] fixes compile issues from merge --- src/iss/arch/tgc5c.cpp | 4 +- src/iss/arch/tgc5c.h | 8 --- src/sysc/register_tgc_c.cpp | 24 ++++---- src/vm/interp/vm_tgc5c.cpp | 111 ++++++++++++++++++++++++++---------- src/vm/tcc/vm_tgc5c.cpp | 26 ++++----- 5 files changed, 109 insertions(+), 64 deletions(-) diff --git a/src/iss/arch/tgc5c.cpp b/src/iss/arch/tgc5c.cpp index 2b9fc3f..6996cb8 100644 --- a/src/iss/arch/tgc5c.cpp +++ b/src/iss/arch/tgc5c.cpp @@ -63,7 +63,7 @@ uint8_t *tgc5c::get_regs_base_ptr() { return reinterpret_cast(®); } -tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t &pc) { - return phys_addr_t(pc); // change logical address to physical address +tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t &addr) { + return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); } diff --git a/src/iss/arch/tgc5c.h b/src/iss/arch/tgc5c.h index 38e2e31..319f31f 100644 --- a/src/iss/arch/tgc5c.h +++ b/src/iss/arch/tgc5c.h @@ -195,14 +195,6 @@ struct tgc5c: public arch_if { inline uint64_t stop_code() { return interrupt_sim; } - inline phys_addr_t v2p(const iss::addr_t& addr){ - if (addr.space != traits::MEM || addr.type == iss::address_type::PHYSICAL || - addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL) { - return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); - } else - return virt2phys(addr); - } - virtual phys_addr_t virt2phys(const iss::addr_t& addr); virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } diff --git a/src/sysc/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp index be81241..7ea4d5b 100644 --- a/src/sysc/register_tgc_c.cpp +++ b/src/sysc/register_tgc_c.cpp @@ -42,15 +42,15 @@ namespace iss { namespace interp { using namespace sysc; volatile std::array tgc_init = { - core_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ + iss_factory::instance().register_creator("tgc5c|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { auto cc = reinterpret_cast(data); - arch::tgc5c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }), - core_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned gdb_port, void* data) -> std::tuple{ + iss_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { auto cc = reinterpret_cast(data); - arch::tgc5c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }) }; } @@ -58,15 +58,15 @@ volatile std::array tgc_init = { namespace tcc { using namespace sysc; volatile std::array tgc_init = { - core_factory::instance().register_creator("tgc5c|m_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + iss_factory::instance().register_creator("tgc5c|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { auto cc = reinterpret_cast(data); - arch::tgc5c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }), - core_factory::instance().register_creator("tgc5c|mu_p|tcc", [](unsigned gdb_port, void* data) -> std::tuple{ + iss_factory::instance().register_creator("tgc5c|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { auto cc = reinterpret_cast(data); - arch::tgc5c* cpu = new sc_core_adapter>(cc); - return {cpu_ptr{cpu}, vm_ptr{create(cpu, gdb_port)}}; + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; }) }; } diff --git a/src/vm/interp/vm_tgc5c.cpp b/src/vm/interp/vm_tgc5c.cpp index 07218cf..46b46c0 100644 --- a/src/vm/interp/vm_tgc5c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -152,14 +152,22 @@ private: /**************************************************************************** * start opcode definitions ****************************************************************************/ - struct InstructionDesriptor { + struct instruction_descriptor { size_t length; uint32_t value; uint32_t mask; typename arch::traits::opcode_e op; }; + struct decoding_tree_node{ + std::vector instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, arch::traits::opcode_e::LUI}, {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, arch::traits::opcode_e::AUIPC}, @@ -250,18 +258,76 @@ private: {16, 0b0000000000000000, 0b1111111111111111, arch::traits::opcode_e::DII}, }}; - //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ - auto phys_pc = this->core.v2p(pc); - //if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - // if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; - // if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction - // if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) return iss::Err; - //} else { - if (this->core.read(phys_pc, 4, data) != iss::Ok) return iss::Err; - //} + if(this->core.has_mmu()) { + auto phys_pc = this->core.virt2phys(pc); +// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary +// if (this->core.read(phys_pc, 2, data) != iss::Ok) return iss::Err; +// if ((data[0] & 0x3) == 0x3) // this is a 32bit instruction +// if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) +// return iss::Err; +// } else { + if (this->core.read(phys_pc, 4, data) != iss::Ok) + return iss::Err; +// } + } else { + if (this->core.read(phys_addr_t(pc.access, pc.space, pc.val), 4, data) != iss::Ok) + return iss::Err; + + } return iss::Ok; } + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + typename arch::traits::opcode_e decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return arch::traits::opcode_e::MAX_OPCODE; + } }; template void debug_fn(CODE_WORD insn) { @@ -288,16 +354,11 @@ constexpr size_t bit_count(uint32_t u) { template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - unsigned id=0; - for (auto instr : instr_descr) { - auto quadrant = instr.value & 0x3; - qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); - } - for(auto& lut: qlut){ - std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ - return bit_count(a.mask) > bit_count(b.mask); - }); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } inline bool is_count_limit_enabled(finish_cond_e cond){ @@ -308,14 +369,6 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){ return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; } -template -typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t instr){ - for(auto& e: qlut[instr&0x3]){ - if(!((instr&e.mask) ^ e.value )) return e.id; - } - return arch::traits::opcode_e::MAX_OPCODE; -} - template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ auto pc=start; @@ -337,7 +390,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if (is_jump_to_self_enabled(cond) && (instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto inst_id = decode_inst_id(instr); + auto inst_id = decode_instr(root, instr); // pre execution stuff this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); diff --git a/src/vm/tcc/vm_tgc5c.cpp b/src/vm/tcc/vm_tgc5c.cpp index 55bc1f6..474807b 100644 --- a/src/vm/tcc/vm_tgc5c.cpp +++ b/src/vm/tcc/vm_tgc5c.cpp @@ -3138,9 +3138,9 @@ private: } }; -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; } template vm_impl::vm_impl() { this(new ARCH()); } @@ -3163,30 +3163,30 @@ std::tuple vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - // const typename traits::addr_t upper_bits = ~traits::PGMASK; + code_word_t instr = 0; phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); + if(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); + //TODO: re-add page handling // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // auto res = this->core.read(paddr, 2, data); // if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction +// if ((instr & 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); + auto res = this->core.read(paddr, 4, reinterpret_cast(&instr)); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); // } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; + auto lut_val = extract_fields(instr); + auto f = qlut[instr & 0x3][lut_val]; if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, tu); + return (this->*f)(pc, instr, tu); } template void vm_impl::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) { From d5763d2f36b3845b6d613997354fa62e2f6372f3 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 30 Aug 2023 17:11:50 +0200 Subject: [PATCH 136/184] fixes option depended compilation --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ba94a2..6746810 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,6 @@ add_subdirectory(softfloat) set(LIB_SOURCES src/iss/plugin/instruction_count.cpp src/iss/arch/tgc5c.cpp - src/vm/tcc/vm_tgc5c.cpp src/vm/interp/vm_tgc5c.cpp src/vm/fp_functions.cpp ) From 8ee3ac90f72176d0bbdfe10e43ab251f629c7d37 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 4 Sep 2023 12:37:30 +0200 Subject: [PATCH 137/184] adapts name changes --- CMakeLists.txt | 10 ++- src/main.cpp | 2 +- src/vm/llvm/vm_tgc5c.cpp | 24 +++---- src/vm/tcc/vm_tgc5c.cpp | 136 +++++++++++++++++++++------------------ 4 files changed, 95 insertions(+), 77 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6746810..001a346 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,7 @@ if(WITH_TCC) list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) endif() -if(TARGET RapidJSON) +if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON) list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp src/iss/plugin/pctrace.cpp @@ -94,6 +94,14 @@ if(TARGET RapidJSON) target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON) endif() +if(WITH_LLVM) + target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS}) + target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS}) + if(BUILD_SHARED_LIBS) + target_link_libraries( ${PROJECT_NAME} PUBLIC ${LLVM_LIBRARIES}) + endif() +endif() + set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION} FRAMEWORK FALSE diff --git a/src/main.cpp b/src/main.cpp index 0452578..c476611 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) { ("mem,m", po::value(), "the memory input file") ("plugin,p", po::value>(), "plugin to activate") ("backend", po::value()->default_value("interp"), "the ISS backend to use, options are: interp, tcc") - ("isa", po::value()->default_value("tgc_c"), "isa to use for simulation"); + ("isa", po::value()->default_value("tgc5c"), "isa to use for simulation"); // clang-format on auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); try { diff --git a/src/vm/llvm/vm_tgc5c.cpp b/src/vm/llvm/vm_tgc5c.cpp index f65f998..1b327ab 100644 --- a/src/vm/llvm/vm_tgc5c.cpp +++ b/src/vm/llvm/vm_tgc5c.cpp @@ -124,7 +124,7 @@ protected: // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + enum { LUT_SIZE = 1 << util::bit_count((uint32_t)EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count((uint32_t)EXTR_MASK16) }; using this_class = vm_impl; using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, @@ -4082,20 +4082,22 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; code_word_t insn = 0; - const typename traits::addr_t upper_bits = ~traits::PGMASK; + // const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - auto res = this->core.read(paddr, 2, data); - if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) { // this is a 32bit instruction - res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); - } - } else { + if(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); + //TODO: re-add page handling +// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary +// auto res = this->core.read(paddr, 2, data); +// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); +// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction +// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); +// } +// } else { auto res = this->core.read(paddr, 4, data); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } +// } if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; diff --git a/src/vm/tcc/vm_tgc5c.cpp b/src/vm/tcc/vm_tgc5c.cpp index 474807b..5fbe3b0 100644 --- a/src/vm/tcc/vm_tgc5c.cpp +++ b/src/vm/tcc/vm_tgc5c.cpp @@ -120,57 +120,7 @@ protected: } } - // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } + template::type> inline S sext(U from) { auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI, encoding '0b00000000000000000000000000110111' */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, @@ -3136,6 +3095,59 @@ private: vm_impl::gen_trap_check(tu); return BRANCH; } + + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; + } }; template void debug_fn(CODE_WORD instr) { @@ -3148,14 +3160,11 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } template @@ -3171,7 +3180,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // auto res = this->core.read(paddr, 2, data); // if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// if ((instr & 0x3) == 0x3) { // this is a 32bit instruction +// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction // res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); // } // } else { @@ -3181,8 +3190,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(instr); - auto f = qlut[instr & 0x3][lut_val]; + auto f = decode_instr(root, instr); if (f == nullptr) { f = &this_class::illegal_intruction; } @@ -3218,7 +3226,7 @@ std::unique_ptr create(arch::tgc5c *core, unsigned short por if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } -} // namespace tcc +} // namesapce tcc } // namespace iss #include From e21f8dc37911bbc7455a0daa894f44fc32af80fd Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Tue, 5 Sep 2023 10:08:00 +0200 Subject: [PATCH 138/184] allows functions in interp and updates generated --- TGC_C_instr.yaml | 34 +- gen_input/templates/interp/CORENAME.cpp.gtl | 68 +- gen_input/templates/tcc/CORENAME.cpp.gtl | 5 +- src/vm/interp/vm_tgc5c.cpp | 4524 +++++++++---------- src/vm/tcc/vm_tgc5c.cpp | 223 +- 5 files changed, 2452 insertions(+), 2402 deletions(-) diff --git a/TGC_C_instr.yaml b/TGC_C_instr.yaml index c82876f..e28cb64 100644 --- a/TGC_C_instr.yaml +++ b/TGC_C_instr.yaml @@ -15,59 +15,51 @@ RV32I: - JAL: encoding: 0b00000000000000000000000001101111 mask: 0b00000000000000000000000001111111 - attributes: [[name:no_cont]] size: 32 branch: true delay: 1 - JALR: encoding: 0b00000000000000000000000001100111 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont]] size: 32 branch: true delay: 1 - BEQ: encoding: 0b00000000000000000000000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - BNE: encoding: 0b00000000000000000001000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - BLT: encoding: 0b00000000000000000100000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - BGE: encoding: 0b00000000000000000101000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - BLTU: encoding: 0b00000000000000000110000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - BGEU: encoding: 0b00000000000000000111000001100011 mask: 0b00000000000000000111000001111111 - attributes: [[name:no_cont], [name:cond]] size: 32 branch: true - delay: [1,1] + delay: 1 - LB: encoding: 0b00000000000000000000000000000011 mask: 0b00000000000000000111000001111111 @@ -239,14 +231,12 @@ RV32I: - ECALL: encoding: 0b00000000000000000000000001110011 mask: 0b11111111111111111111111111111111 - attributes: [[name:no_cont]] size: 32 branch: false delay: 1 - EBREAK: encoding: 0b00000000000100000000000001110011 mask: 0b11111111111111111111111111111111 - attributes: [[name:no_cont]] size: 32 branch: false delay: 1 @@ -391,7 +381,6 @@ RV32IC: - CJAL: encoding: 0b0010000000000001 mask: 0b1110000000000011 - attributes: [[name:no_cont]] size: 16 branch: true delay: 1 @@ -458,24 +447,21 @@ RV32IC: - CJ: encoding: 0b1010000000000001 mask: 0b1110000000000011 - attributes: [[name:no_cont]] size: 16 branch: true delay: 1 - CBEQZ: encoding: 0b1100000000000001 mask: 0b1110000000000011 - attributes: [[name:no_cont], [name:cond]] size: 16 branch: true - delay: [1,1] + delay: 1 - CBNEZ: encoding: 0b1110000000000001 mask: 0b1110000000000011 - attributes: [[name:no_cont], [name:cond]] size: 16 branch: true - delay: [1,1] + delay: 1 - CSLLI: encoding: 0b0000000000000010 mask: 0b1111000000000011 @@ -497,7 +483,6 @@ RV32IC: - CJR: encoding: 0b1000000000000010 mask: 0b1111000001111111 - attributes: [[name:no_cont]] size: 16 branch: true delay: 1 @@ -510,14 +495,12 @@ RV32IC: - CJALR: encoding: 0b1001000000000010 mask: 0b1111000001111111 - attributes: [[name:no_cont]] size: 16 branch: true delay: 1 - CEBREAK: encoding: 0b1001000000000010 mask: 0b1111111111111111 - attributes: [[name:no_cont]] size: 16 branch: false delay: 1 @@ -530,7 +513,6 @@ RV32IC: - DII: encoding: 0b0000000000000000 mask: 0b1111111111111111 - attributes: [[name:no_cont]] size: 16 branch: false delay: 1 diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 7645bdc..cfb6a76 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -43,6 +43,7 @@ def nativeTypeSize(int size){ #include #include #include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -59,6 +60,10 @@ using namespace iss::arch; using namespace iss::debugger; using namespace std::placeholders; +struct memory_access_exception : public std::exception{ + memory_access_exception(){} +}; + template class vm_impl : public iss::interp::vm_base { public: using traits = arch::traits; @@ -91,30 +96,9 @@ protected: inline const char *name(size_t index){return index::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { - LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), - LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) - }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - struct instruction_pattern { - uint32_t value; - uint32_t mask; - typename arch::traits::opcode_e id; - }; - - std::array, 4> qlut; inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; @@ -314,28 +298,30 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // pre execution stuff this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); - switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> - case arch::traits::opcode_e::${instr.name}: { - <%instr.fields.eachLine{%>${it} - <%}%>if(this->disass_enabled){ - /* generate console output when executing the command */<%instr.disass.eachLine{%> + try{ + switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %> + case arch::traits::opcode_e::${instr.name}: { + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate console output when executing the command */<%instr.disass.eachLine{%> + ${it}<%}%> + } + // used registers<%instr.usedVariables.each{ k,v-> + if(v.isArray) {%> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); + <%}}%>// calculate next pc value + *NEXT_PC = *PC + ${instr.length/8}; + // execute instruction<%instr.behavior.eachLine{%> ${it}<%}%> + break; + }// @suppress("No break at end of case")<%}%> + default: { + *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); + raise(0, 2); } - // used registers<%instr.usedVariables.each{ k,v-> - if(v.isArray) {%> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); - <%}}%>// calculate next pc value - *NEXT_PC = *PC + ${instr.length/8}; - // execute instruction<%instr.behavior.eachLine{%> - ${it}<%}%> - TRAP_${instr.name}:break; - }// @suppress("No break at end of case")<%}%> - default: { - *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); - raise(0, 2); - } - } + } + }catch(memory_access_exception& e){} // post execution stuff process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index fb912cd..6b2ba2b 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -167,8 +167,9 @@ private: auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+ ${instr.length/8}; gen_set_pc(tu, pc, traits::NEXT_PC); - tu.open_scope();<%instr.behavior.eachLine{%> - ${it}<%}%> + tu.open_scope(); + <%instr.behavior.eachLine{%>${it} + <%}%> tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,${idx}); gen_trap_check(tu); diff --git a/src/vm/interp/vm_tgc5c.cpp b/src/vm/interp/vm_tgc5c.cpp index 46b46c0..4ba2443 100644 --- a/src/vm/interp/vm_tgc5c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -55,6 +56,10 @@ using namespace iss::arch; using namespace iss::debugger; using namespace std::placeholders; +struct memory_access_exception : public std::exception{ + memory_access_exception(){} +}; + template class vm_impl : public iss::interp::vm_base { public: using traits = arch::traits; @@ -87,30 +92,9 @@ protected: inline const char *name(size_t index){return index::opcode_e decode_inst_id(code_word_t instr); virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override; // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { - LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), - LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) - }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - struct instruction_pattern { - uint32_t value; - uint32_t mask; - typename arch::traits::opcode_e id; - }; - - std::array, 4> qlut; inline void raise(uint16_t trap_id, uint16_t cause){ auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id; @@ -394,2279 +378,2281 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // pre execution stuff this->core.reg.last_branch = 0; if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast(inst_id)); - switch(inst_id){ - case arch::traits::opcode_e::LUI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)imm); - } - } - } - TRAP_LUI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::AUIPC: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + (int32_t)imm); - } - } - } - TRAP_AUIPC:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::JAL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); + try{ + switch(inst_id){ + case arch::traits::opcode_e::LUI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, 2); } else { if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + 4); + *(X+rd) = (uint32_t)((int32_t)imm); } - *NEXT_PC = (uint32_t)(*PC + (int32_t)sext<21>(imm)); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AUIPC: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*PC + (int32_t)imm); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::JAL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*PC + 4); + } + *NEXT_PC = (uint32_t)(*PC + (int32_t)sext<21>(imm)); + this->core.reg.last_branch = 1; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::JALR: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t new_pc = (uint32_t)((*(X+rs1) + (int16_t)sext<12>(imm)) & ~ 0x1); + if(new_pc % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*PC + 4); + } + *NEXT_PC = new_pc & ~ 0x1; + this->core.reg.last_branch = 1; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BEQ: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1) == *(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BNE: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1) != *(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BLT: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BGE: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BLTU: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1) < *(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::BGEU: { + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs1) >= *(X+rs2)) { + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); + this->core.reg.last_branch = 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LB: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + int8_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int8_t res = (int8_t)read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LH: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + int16_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int16_t res = (int16_t)read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + int32_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + int32_t res = (int32_t)read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LBU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + uint8_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint8_t res = read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::LHU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + uint16_t read_res = super::template read_mem(traits::MEM, load_address); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint16_t res = read_res; + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SB: { + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + super::template write_mem(traits::MEM, store_address, (uint8_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SH: { + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + super::template write_mem(traits::MEM, store_address, (uint16_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SW: { + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rs2 >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + super::template write_mem(traits::MEM, store_address, (uint32_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ADDI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLTI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = ((int32_t)*(X+rs1) < (int16_t)sext<12>(imm))? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLTIU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (*(X+rs1) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::XORI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) ^ (uint32_t)((int16_t)sext<12>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ORI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) | (uint32_t)((int16_t)sext<12>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ANDI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) & (uint32_t)((int16_t)sext<12>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLLI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) << shamt; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRLI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) >> shamt; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRAI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> shamt); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ADD: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*(X+rs1) + *(X+rs2)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SUB: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*(X+rs1) - *(X+rs2)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLT: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (int32_t)*(X+rs1) < (int32_t)*(X+rs2)? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SLTU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) < *(X+rs2)? 1 : 0; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::XOR: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) ^ *(X+rs2); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::SRA: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1))); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::OR: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) | *(X+rs2); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::AND: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1) & *(X+rs2); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::FENCE: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + uint8_t fm = ((bit_sub<28,4>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), + fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + super::template write_mem(traits::FENCE, traits::fence, (uint8_t)pred << 4 | succ); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::ECALL: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "ecall"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + raise(0, 11); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::EBREAK: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "ebreak"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + raise(0, 3); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::MRET: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "mret"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + leave(3); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::WFI: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "wfi"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + wait(1); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRW: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t xrs1 = *(X+rs1); + if(rd != 0) { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd) = xrd; + } + else { + super::template write_mem(traits::CSR, csr, xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRS: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + uint32_t xrs1 = *(X+rs1); + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd | xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRC: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + uint32_t xrs1 = *(X+rs1); + if(rs1 != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRWI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + super::template write_mem(traits::CSR, csr, (uint32_t)zimm); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRSI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRRCI: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t read_res = super::template read_mem(traits::CSR, csr); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + uint32_t xrd = read_res; + if(zimm != 0) { + super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + if(rd != 0) { + *(X+rd) = xrd; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::FENCE_I: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), + fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + super::template write_mem(traits::FENCE, traits::fencei, imm); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::MUL: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint32_t)res; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::MULH: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint32_t)(res >> traits::XLEN); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::MULHSU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (uint64_t)*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint32_t)(res >> traits::XLEN); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::MULHU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + uint64_t res = (uint64_t)((uint64_t)*(X+rs1) * (uint64_t)*(X+rs2)); + if(rd != 0) { + *(X+rd) = (uint32_t)(res >> traits::XLEN); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::DIV: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + int32_t dividend = (int32_t)*(X+rs1); + int32_t divisor = (int32_t)*(X+rs2); + if(rd != 0) { + if(divisor != 0) { + uint32_t MMIN = ((uint32_t)1) << (traits::XLEN - 1); + if(*(X+rs1) == MMIN && divisor == - 1) { + *(X+rd) = MMIN; + } + else { + *(X+rd) = (uint32_t)(dividend / divisor); + } + } + else { + *(X+rd) = (uint32_t)- 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::DIVU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs2) != 0) { + if(rd != 0) { + *(X+rd) = (uint32_t)(*(X+rs1) / *(X+rs2)); + } + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)- 1; + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::REM: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs2) != 0) { + uint32_t MMIN = 1 << (traits::XLEN - 1); + if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) { + if(rd != 0) { + *(X+rd) = 0; + } + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)((int32_t)*(X+rs1) % (int32_t)*(X+rs2)); + } + } + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1); + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::REMU: { + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + { + if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { + raise(0, 2); + } + else { + if(*(X+rs2) != 0) { + if(rd != 0) { + *(X+rd) = *(X+rs1) % *(X+rs2); + } + } + else { + if(rd != 0) { + *(X+rd) = *(X+rs1); + } + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CADDI4SPN: { + uint8_t rd = ((bit_sub<2,3>(instr))); + uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), + fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(imm) { + *(X+rd + 8) = (uint32_t)(*(X+2) + imm); + } + else { + raise(0, 2); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CLW: { + uint8_t rd = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), + fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); + int32_t read_res = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd + 8) = (uint32_t)(int32_t)read_res; + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSW: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), + fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 + 8)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CADDI: { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rs1 != 0) { + *(X+rs1) = (uint32_t)(*(X+rs1) + (int8_t)sext<6>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CNOP: { + uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "cnop"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CJAL: { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+1) = (uint32_t)(*PC + 2); + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); + this->core.reg.last_branch = 1; + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CLI: { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)((int8_t)sext<6>(imm)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CLUI: { + uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(imm == 0 || rd >= traits::RFS) { + raise(0, 2); + } + if(rd != 0) { + *(X+rd) = (uint32_t)((int32_t)sext<18>(imm)); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CADDI16SP: { + uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), + fmt::arg("nzimm", nzimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(nzimm) { + *(X+2) = (uint32_t)(*(X+2) + (int16_t)sext<10>(nzimm)); + } + else { + raise(0, 2); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::__reserved_clui: { + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "__reserved_clui"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + raise(0, 2); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRLI: { + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rs1 + 8) = *(X+rs1 + 8) >> shamt; + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSRAI: { + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(shamt) { + *(X+rs1 + 8) = (uint32_t)(((int32_t)*(X+rs1 + 8)) >> shamt); + } + else { + if(traits::XLEN == 128) { + *(X+rs1 + 8) = (uint32_t)(((int32_t)*(X+rs1 + 8)) >> 64); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CANDI: { + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rs1 + 8) = (uint32_t)(*(X+rs1 + 8) & (int8_t)sext<6>(imm)); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSUB: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rd + 8) = (uint32_t)(*(X+rd + 8) - *(X+rs2 + 8)); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CXOR: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rd + 8) = *(X+rd + 8) ^ *(X+rs2 + 8); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::COR: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rd + 8) = *(X+rd + 8) | *(X+rs2 + 8); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CAND: { + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *(X+rd + 8) = *(X+rd + 8) & *(X+rs2 + 8); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CJ: { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), + fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); + this->core.reg.last_branch = 1; + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CBEQZ: { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(*(X+rs1 + 8) == 0) { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); this->core.reg.last_branch = 1; } } - } - TRAP_JAL:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::JALR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CBNEZ: { + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(*(X+rs1 + 8) != 0) { + *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); + this->core.reg.last_branch = 1; + } } - else { - uint32_t new_pc = (uint32_t)((*(X+rs1) + (int16_t)sext<12>(imm)) & ~ 0x1); - if(new_pc % traits::INSTR_ALIGNMENT) { - raise(0, 0); + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSLLI: { + uint8_t nzuimm = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs1 >= traits::RFS) { + raise(0, 2); + } + else { + if(rs1 != 0) { + *(X+rs1) = *(X+rs1) << nzuimm; + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CLWSP: { + uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rd >= traits::RFS || rd == 0) { + raise(0, 2); + } + else { + uint32_t offs = (uint32_t)(*(X+2) + uimm); + int32_t read_res = super::template read_mem(traits::MEM, offs); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); + *(X+rd) = (uint32_t)(int32_t)read_res; + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CMV: { + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, 2); } else { if(rd != 0) { - *(X+rd) = (uint32_t)(*PC + 4); + *(X+rd) = *(X+rs2); } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CJR: { + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs1 && rs1 < traits::RFS) { + *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; + this->core.reg.last_branch = 1; + } + else { + raise(0, 2); + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::__reserved_cmv: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "__reserved_cmv"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + raise(0, 2); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CADD: { + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rd >= traits::RFS) { + raise(0, 2); + } + else { + if(rd != 0) { + *(X+rd) = (uint32_t)(*(X+rd) + *(X+rs2)); + } + } + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CJALR: { + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), + fmt::arg("rs1", name(rs1))); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs1 >= traits::RFS) { + raise(0, 2); + } + else { + uint32_t new_pc = *(X+rs1); + *(X+1) = (uint32_t)(*PC + 2); *NEXT_PC = new_pc & ~ 0x1; this->core.reg.last_branch = 1; } } - } - TRAP_JALR:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BEQ: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) == *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BEQ:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BNE: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) != *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BNE:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BLT: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BLT:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BGE: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BGE:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BLTU: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) < *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BLTU:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::BGEU: { - uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs1) >= *(X+rs2)) { - if(imm % traits::INSTR_ALIGNMENT) { - raise(0, 0); - } - else { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<13>(imm)); - this->core.reg.last_branch = 1; - } - } - } - } - TRAP_BGEU:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LB: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int8_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LB; - int8_t res = (int8_t)read_res; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_LB:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LH: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int16_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LH; - int16_t res = (int16_t)read_res; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_LH:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LW: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int32_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LW; - int32_t res = (int32_t)read_res; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_LW:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LBU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint8_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LBU; - uint8_t res = read_res; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_LBU:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::LHU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint16_t read_res = super::template read_mem(traits::MEM, load_address); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_LHU; - uint16_t res = read_res; - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_LHU:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SB: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint8_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SB; - } - } - TRAP_SB:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SH: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint16_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SH; - } - } - TRAP_SH:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SW: { - uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rs2 >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t store_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - super::template write_mem(traits::MEM, store_address, (uint32_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_SW; - } - } - TRAP_SW:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ADDI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - } - } - } - TRAP_ADDI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = ((int32_t)*(X+rs1) < (int16_t)sext<12>(imm))? 1 : 0; - } - } - } - TRAP_SLTI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTIU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (*(X+rs1) < (uint32_t)((int16_t)sext<12>(imm)))? 1 : 0; - } - } - } - TRAP_SLTIU:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::XORI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) ^ (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - TRAP_XORI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ORI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) | (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - TRAP_ORI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ANDI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) & (uint32_t)((int16_t)sext<12>(imm)); - } - } - } - TRAP_ANDI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLLI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) << shamt; - } - } - } - TRAP_SLLI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRLI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) >> shamt; - } - } - } - TRAP_SRLI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRAI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> shamt); - } - } - } - TRAP_SRAI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ADD: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) + *(X+rs2)); - } - } - } - TRAP_ADD:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SUB: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) - *(X+rs2)); - } - } - } - TRAP_SUB:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); - } - } - } - TRAP_SLL:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLT: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (int32_t)*(X+rs1) < (int32_t)*(X+rs2)? 1 : 0; - } - } - } - TRAP_SLT:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SLTU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) < *(X+rs2)? 1 : 0; - } - } - } - TRAP_SLTU:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::XOR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) ^ *(X+rs2); - } - } - } - TRAP_XOR:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); - } - } - } - TRAP_SRL:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::SRA: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)*(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1))); - } - } - } - TRAP_SRA:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::OR: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) | *(X+rs2); - } - } - } - TRAP_OR:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::AND: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1) & *(X+rs2); - } - } - } - TRAP_AND:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::FENCE: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - uint8_t fm = ((bit_sub<28,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), - fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - super::template write_mem(traits::FENCE, traits::fence, (uint8_t)pred << 4 | succ); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE; - } - TRAP_FENCE:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::ECALL: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ecall"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - raise(0, 11); - } - TRAP_ECALL:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::EBREAK: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "ebreak"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - raise(0, 3); - } - TRAP_EBREAK:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::MRET: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "mret"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - leave(3); - } - TRAP_MRET:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::WFI: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "wfi"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - wait(1); - } - TRAP_WFI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRW: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t xrs1 = *(X+rs1); - if(rd != 0) { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; - uint32_t xrd = read_res; - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; - *(X+rd) = xrd; + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CEBREAK: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "cebreak"); + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + raise(0, 3); + } + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::CSWSP: { + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + this->core.disass_output(pc.val, mnemonic); + } + // used registers + auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { + if(rs2 >= traits::RFS) { + raise(0, 2); } else { - super::template write_mem(traits::CSR, csr, xrs1); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRW; + uint32_t offs = (uint32_t)(*(X+2) + uimm); + super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2)); + if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); } } - } - TRAP_CSRRW:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRS: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRS; - uint32_t xrd = read_res; - uint32_t xrs1 = *(X+rs1); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd | xrs1); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRS; - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - TRAP_CSRRS:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRC: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRC; - uint32_t xrd = read_res; - uint32_t xrs1 = *(X+rs1); - if(rs1 != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRC; - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - TRAP_CSRRC:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRWI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRWI; - uint32_t xrd = read_res; - super::template write_mem(traits::CSR, csr, (uint32_t)zimm); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRWI; - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - TRAP_CSRRWI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRSI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRSI; - uint32_t xrd = read_res; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRSI; - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - TRAP_CSRRSI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRRCI: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRCI; - uint32_t xrd = read_res; - if(zimm != 0) { - super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSRRCI; - } - if(rd != 0) { - *(X+rd) = xrd; - } - } - } - TRAP_CSRRCI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::FENCE_I: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), - fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - super::template write_mem(traits::FENCE, traits::fencei, imm); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_FENCE_I; - } - TRAP_FENCE_I:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::MUL: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); - if(rd != 0) { - *(X+rd) = (uint32_t)res; - } - } - } - TRAP_MUL:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::MULH: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (int64_t)(int32_t)*(X+rs2)); - if(rd != 0) { - *(X+rd) = (uint32_t)(res >> traits::XLEN); - } - } - } - TRAP_MULH:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::MULHSU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - int64_t res = (int64_t)((int64_t)(int32_t)*(X+rs1) * (uint64_t)*(X+rs2)); - if(rd != 0) { - *(X+rd) = (uint32_t)(res >> traits::XLEN); - } - } - } - TRAP_MULHSU:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::MULHU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - uint64_t res = (uint64_t)((uint64_t)*(X+rs1) * (uint64_t)*(X+rs2)); - if(rd != 0) { - *(X+rd) = (uint32_t)(res >> traits::XLEN); - } - } - } - TRAP_MULHU:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::DIV: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - int32_t dividend = (int32_t)*(X+rs1); - int32_t divisor = (int32_t)*(X+rs2); - if(rd != 0) { - if(divisor != 0) { - uint32_t MMIN = ((uint32_t)1) << (traits::XLEN - 1); - if(*(X+rs1) == MMIN && divisor == - 1) { - *(X+rd) = MMIN; - } - else { - *(X+rd) = (uint32_t)(dividend / divisor); - } - } - else { - *(X+rd) = (uint32_t)- 1; - } - } - } - } - TRAP_DIV:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::DIVU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs2) != 0) { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rs1) / *(X+rs2)); - } - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)- 1; - } - } - } - } - TRAP_DIVU:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::REM: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs2) != 0) { - uint32_t MMIN = 1 << (traits::XLEN - 1); - if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) { - if(rd != 0) { - *(X+rd) = 0; - } - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)*(X+rs1) % (int32_t)*(X+rs2)); - } - } - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1); - } - } - } - } - TRAP_REM:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::REMU: { - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 4; - // execute instruction - { - if(rd >= traits::RFS || rs1 >= traits::RFS || rs2 >= traits::RFS) { - raise(0, 2); - } - else { - if(*(X+rs2) != 0) { - if(rd != 0) { - *(X+rd) = *(X+rs1) % *(X+rs2); - } - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs1); - } - } - } - } - TRAP_REMU:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI4SPN: { - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), - fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(imm) { - *(X+rd + 8) = (uint32_t)(*(X+2) + imm); - } - else { - raise(0, 2); - } - } - TRAP_CADDI4SPN:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLW: { - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); - int32_t read_res = super::template read_mem(traits::MEM, offs); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLW; - *(X+rd + 8) = (uint32_t)(int32_t)read_res; - } - TRAP_CLW:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSW: { - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); - super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2 + 8)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSW; - } - TRAP_CSW:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI: { - uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rs1 != 0) { - *(X+rs1) = (uint32_t)(*(X+rs1) + (int8_t)sext<6>(imm)); - } - } - } - TRAP_CADDI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CNOP: { - uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cnop"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - } - TRAP_CNOP:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJAL: { - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - *(X+1) = (uint32_t)(*PC + 2); - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); - this->core.reg.last_branch = 1; - } - TRAP_CJAL:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLI: { - uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)((int8_t)sext<6>(imm)); - } - } - } - TRAP_CLI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLUI: { - uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(imm == 0 || rd >= traits::RFS) { - raise(0, 2); + break; + }// @suppress("No break at end of case") + case arch::traits::opcode_e::DII: { + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "dii"); } - if(rd != 0) { - *(X+rd) = (uint32_t)((int32_t)sext<18>(imm)); - } - } - TRAP_CLUI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI16SP: { - uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), - fmt::arg("nzimm", nzimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(nzimm) { - *(X+2) = (uint32_t)(*(X+2) + (int16_t)sext<10>(nzimm)); - } - else { + // used registers// calculate next pc value + *NEXT_PC = *PC + 2; + // execute instruction + { raise(0, 2); } - } - TRAP_CADDI16SP:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::__reserved_clui: { - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "__reserved_clui"); + break; + }// @suppress("No break at end of case") + default: { + *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); + raise(0, 2); } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - raise(0, 2); - } - TRAP___reserved_clui:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRLI: { - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - *(X+rs1 + 8) = *(X+rs1 + 8) >> shamt; - } - TRAP_CSRLI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRAI: { - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(shamt) { - *(X+rs1 + 8) = (uint32_t)(((int32_t)*(X+rs1 + 8)) >> shamt); - } - else { - if(traits::XLEN == 128) { - *(X+rs1 + 8) = (uint32_t)(((int32_t)*(X+rs1 + 8)) >> 64); - } - } - } - TRAP_CSRAI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CANDI: { - uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - *(X+rs1 + 8) = (uint32_t)(*(X+rs1 + 8) & (int8_t)sext<6>(imm)); - } - TRAP_CANDI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSUB: { - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - *(X+rd + 8) = (uint32_t)(*(X+rd + 8) - *(X+rs2 + 8)); - } - TRAP_CSUB:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CXOR: { - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - *(X+rd + 8) = *(X+rd + 8) ^ *(X+rs2 + 8); - } - TRAP_CXOR:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::COR: { - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - *(X+rd + 8) = *(X+rd + 8) | *(X+rs2 + 8); - } - TRAP_COR:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CAND: { - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - *(X+rd + 8) = *(X+rd + 8) & *(X+rs2 + 8); - } - TRAP_CAND:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJ: { - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), - fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<12>(imm)); - this->core.reg.last_branch = 1; - } - TRAP_CJ:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CBEQZ: { - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(*(X+rs1 + 8) == 0) { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); - this->core.reg.last_branch = 1; - } - } - TRAP_CBEQZ:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CBNEZ: { - uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(*(X+rs1 + 8) != 0) { - *NEXT_PC = (uint32_t)(*PC + (int16_t)sext<9>(imm)); - this->core.reg.last_branch = 1; - } - } - TRAP_CBNEZ:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSLLI: { - uint8_t nzuimm = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), - fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(rs1 >= traits::RFS) { - raise(0, 2); - } - else { - if(rs1 != 0) { - *(X+rs1) = *(X+rs1) << nzuimm; - } - } - } - TRAP_CSLLI:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLWSP: { - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(rd >= traits::RFS || rd == 0) { - raise(0, 2); - } - else { - uint32_t offs = (uint32_t)(*(X+2) + uimm); - int32_t read_res = super::template read_mem(traits::MEM, offs); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CLWSP; - *(X+rd) = (uint32_t)(int32_t)read_res; - } - } - TRAP_CLWSP:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CMV: { - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = *(X+rs2); - } - } - } - TRAP_CMV:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJR: { - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(rs1 && rs1 < traits::RFS) { - *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; - this->core.reg.last_branch = 1; - } - else { - raise(0, 2); - } - } - TRAP_CJR:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::__reserved_cmv: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "__reserved_cmv"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - raise(0, 2); - } - TRAP___reserved_cmv:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADD: { - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(rd >= traits::RFS) { - raise(0, 2); - } - else { - if(rd != 0) { - *(X+rd) = (uint32_t)(*(X+rd) + *(X+rs2)); - } - } - } - TRAP_CADD:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJALR: { - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), - fmt::arg("rs1", name(rs1))); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(rs1 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t new_pc = *(X+rs1); - *(X+1) = (uint32_t)(*PC + 2); - *NEXT_PC = new_pc & ~ 0x1; - this->core.reg.last_branch = 1; - } - } - TRAP_CJALR:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CEBREAK: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cebreak"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - raise(0, 3); - } - TRAP_CEBREAK:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSWSP: { - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - this->core.disass_output(pc.val, mnemonic); - } - // used registers - auto* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]);// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - if(rs2 >= traits::RFS) { - raise(0, 2); - } - else { - uint32_t offs = (uint32_t)(*(X+2) + uimm); - super::template write_mem(traits::MEM, offs, (uint32_t)*(X+rs2)); - if(this->core.reg.trap_state>=0x80000000UL) goto TRAP_CSWSP; - } - } - TRAP_CSWSP:break; - }// @suppress("No break at end of case") - case arch::traits::opcode_e::DII: { - if(this->disass_enabled){ - /* generate console output when executing the command */ - this->core.disass_output(pc.val, "dii"); - } - // used registers// calculate next pc value - *NEXT_PC = *PC + 2; - // execute instruction - { - raise(0, 2); - } - TRAP_DII:break; - }// @suppress("No break at end of case") - default: { - *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); - raise(0, 2); - } - } + }catch(memory_access_exception& e){} // post execution stuff process_spawn_blocks(); if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(inst_id)); diff --git a/src/vm/tcc/vm_tgc5c.cpp b/src/vm/tcc/vm_tgc5c.cpp index 474807b..484b443 100644 --- a/src/vm/tcc/vm_tgc5c.cpp +++ b/src/vm/tcc/vm_tgc5c.cpp @@ -120,57 +120,7 @@ protected: } } - // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } + template::type> inline S sext(U from) { auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI, encoding '0b00000000000000000000000000110111' */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, @@ -394,6 +353,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,0); gen_trap_check(tu); @@ -426,6 +386,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,1); gen_trap_check(tu); @@ -465,6 +426,7 @@ private: } } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,2); gen_trap_check(tu); @@ -506,6 +468,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,3); gen_trap_check(tu); @@ -545,6 +508,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,4); gen_trap_check(tu); @@ -584,6 +548,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,5); gen_trap_check(tu); @@ -623,6 +588,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,6); gen_trap_check(tu); @@ -662,6 +628,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,7); gen_trap_check(tu); @@ -701,6 +668,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,8); gen_trap_check(tu); @@ -740,6 +708,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,9); gen_trap_check(tu); @@ -775,6 +744,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,10); gen_trap_check(tu); @@ -810,6 +780,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,11); gen_trap_check(tu); @@ -845,6 +816,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,12); gen_trap_check(tu); @@ -880,6 +852,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,13); gen_trap_check(tu); @@ -915,6 +888,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,14); gen_trap_check(tu); @@ -947,6 +921,7 @@ private: tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),8,true)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,15); gen_trap_check(tu); @@ -979,6 +954,7 @@ private: tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),16,true)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,16); gen_trap_check(tu); @@ -1011,6 +987,7 @@ private: tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),32,true)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,17); gen_trap_check(tu); @@ -1044,6 +1021,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,18); gen_trap_check(tu); @@ -1077,6 +1055,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,19); gen_trap_check(tu); @@ -1110,6 +1089,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,20); gen_trap_check(tu); @@ -1143,6 +1123,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,21); gen_trap_check(tu); @@ -1176,6 +1157,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,22); gen_trap_check(tu); @@ -1209,6 +1191,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,23); gen_trap_check(tu); @@ -1242,6 +1225,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,24); gen_trap_check(tu); @@ -1275,6 +1259,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,25); gen_trap_check(tu); @@ -1308,6 +1293,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,26); gen_trap_check(tu); @@ -1341,6 +1327,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,27); gen_trap_check(tu); @@ -1374,6 +1361,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,28); gen_trap_check(tu); @@ -1407,6 +1395,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,29); gen_trap_check(tu); @@ -1440,6 +1429,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,30); gen_trap_check(tu); @@ -1473,6 +1463,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,31); gen_trap_check(tu); @@ -1506,6 +1497,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,32); gen_trap_check(tu); @@ -1539,6 +1531,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,33); gen_trap_check(tu); @@ -1572,6 +1565,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,34); gen_trap_check(tu); @@ -1605,6 +1599,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,35); gen_trap_check(tu); @@ -1638,6 +1633,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,36); gen_trap_check(tu); @@ -1666,6 +1662,7 @@ private: tu.open_scope(); tu.write_mem(traits::FENCE, static_cast(traits:: fence), tu.constant((uint8_t)pred<< 4|succ,8)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,37); gen_trap_check(tu); @@ -1686,6 +1683,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 11); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,38); gen_trap_check(tu); @@ -1706,6 +1704,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 3); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,39); gen_trap_check(tu); @@ -1726,6 +1725,7 @@ private: tu.open_scope(); this->gen_leave_trap(tu, 3); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,40); gen_trap_check(tu); @@ -1746,6 +1746,7 @@ private: tu.open_scope(); this->gen_wait(tu, 1); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,41); gen_trap_check(tu); @@ -1784,6 +1785,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,42); gen_trap_check(tu); @@ -1822,6 +1824,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,43); gen_trap_check(tu); @@ -1860,6 +1863,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,44); gen_trap_check(tu); @@ -1895,6 +1899,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,45); gen_trap_check(tu); @@ -1932,6 +1937,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,46); gen_trap_check(tu); @@ -1969,6 +1975,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,47); gen_trap_check(tu); @@ -1995,6 +2002,7 @@ private: tu.open_scope(); tu.write_mem(traits::FENCE, static_cast(traits:: fencei), tu.constant(imm,16)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,48); gen_trap_check(tu); @@ -2029,6 +2037,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,49); gen_trap_check(tu); @@ -2063,6 +2072,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,50); gen_trap_check(tu); @@ -2097,6 +2107,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,51); gen_trap_check(tu); @@ -2131,6 +2142,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,52); gen_trap_check(tu); @@ -2174,6 +2186,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,53); gen_trap_check(tu); @@ -2213,6 +2226,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,54); gen_trap_check(tu); @@ -2259,6 +2273,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,55); gen_trap_check(tu); @@ -2298,6 +2313,7 @@ private: tu.close_scope(); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,56); gen_trap_check(tu); @@ -2328,6 +2344,7 @@ private: this->gen_raise_trap(tu, 0, 2); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,57); gen_trap_check(tu); @@ -2355,6 +2372,7 @@ private: auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); tu.store(rd+ 8 + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32,true)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,58); gen_trap_check(tu); @@ -2382,6 +2400,7 @@ private: auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,true)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,59); gen_trap_check(tu); @@ -2414,6 +2433,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,60); gen_trap_check(tu); @@ -2434,6 +2454,7 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,61); gen_trap_check(tu); @@ -2461,6 +2482,7 @@ private: tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,62); gen_trap_check(tu); @@ -2493,6 +2515,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,63); gen_trap_check(tu); @@ -2523,6 +2546,7 @@ private: tu.store(rd + traits::X0,tu.constant((uint32_t)((int32_t)sext<18>(imm)),32)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,64); gen_trap_check(tu); @@ -2552,6 +2576,7 @@ private: this->gen_raise_trap(tu, 0, 2); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,65); gen_trap_check(tu); @@ -2573,6 +2598,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 2); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,66); gen_trap_check(tu); @@ -2598,6 +2624,7 @@ private: tu.open_scope(); tu.store(rs1+ 8 + traits::X0,tu.lshr(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(shamt,8))); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,67); gen_trap_check(tu); @@ -2628,6 +2655,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,68); gen_trap_check(tu); @@ -2653,6 +2681,7 @@ private: tu.open_scope(); tu.store(rs1+ 8 + traits::X0,tu.ext((tu.bitwise_and(tu.load(rs1+ 8+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))),32,true)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,69); gen_trap_check(tu); @@ -2678,6 +2707,7 @@ private: tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.ext((tu.sub(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))),32,true)); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,70); gen_trap_check(tu); @@ -2703,6 +2733,7 @@ private: tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_xor(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,71); gen_trap_check(tu); @@ -2728,6 +2759,7 @@ private: tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_or(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,72); gen_trap_check(tu); @@ -2753,6 +2785,7 @@ private: tu.open_scope(); tu.store(rd+ 8 + traits::X0,tu.bitwise_and(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,73); gen_trap_check(tu); @@ -2779,6 +2812,7 @@ private: tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,74); gen_trap_check(tu); @@ -2808,6 +2842,7 @@ private: tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,75); gen_trap_check(tu); @@ -2837,6 +2872,7 @@ private: tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,76); gen_trap_check(tu); @@ -2869,6 +2905,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,77); gen_trap_check(tu); @@ -2900,6 +2937,7 @@ private: tu.store(rd + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32,true)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,78); gen_trap_check(tu); @@ -2932,6 +2970,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,79); gen_trap_check(tu); @@ -2963,6 +3002,7 @@ private: this->gen_raise_trap(tu, 0, 2); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,80); gen_trap_check(tu); @@ -2983,6 +3023,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 2); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,81); gen_trap_check(tu); @@ -3015,6 +3056,7 @@ private: } } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,82); gen_trap_check(tu); @@ -3048,6 +3090,7 @@ private: tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } auto returnValue = std::make_tuple(BRANCH); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,83); gen_trap_check(tu); @@ -3068,6 +3111,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 3); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,84); gen_trap_check(tu); @@ -3099,6 +3143,7 @@ private: tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ traits::X0, 0),32,true)); } auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,85); gen_trap_check(tu); @@ -3119,6 +3164,7 @@ private: tu.open_scope(); this->gen_raise_trap(tu, 0, 2); auto returnValue = std::make_tuple(CONT); + tu.close_scope(); vm_base::gen_sync(tu, POST_SYNC,86); gen_trap_check(tu); @@ -3136,6 +3182,59 @@ private: vm_impl::gen_trap_check(tu); return BRANCH; } + + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; + } }; template void debug_fn(CODE_WORD instr) { @@ -3148,14 +3247,11 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } template @@ -3171,7 +3267,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // auto res = this->core.read(paddr, 2, data); // if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// if ((instr & 0x3) == 0x3) { // this is a 32bit instruction +// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction // res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); // } // } else { @@ -3181,8 +3277,7 @@ vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(instr); - auto f = qlut[instr & 0x3][lut_val]; + auto f = decode_instr(root, instr); if (f == nullptr) { f = &this_class::illegal_intruction; } @@ -3218,7 +3313,7 @@ std::unique_ptr create(arch::tgc5c *core, unsigned short por if (port != 0) debugger::server::run_server(ret, port); return std::unique_ptr(ret); } -} // namespace tcc +} // namesapce tcc } // namespace iss #include From 40f50b0ec079b912ed7ab76756772bd0527ebe05 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 9 Sep 2023 18:54:18 +0200 Subject: [PATCH 139/184] changes register names to lower case in printing --- CMakeLists.txt | 4 ++- gen_input/templates/CORENAME.h.gtl | 4 +-- src/iss/arch/tgc5c.h | 4 +-- src/vm/interp/vm_tgc5c.cpp | 52 +++++++++++++++--------------- 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 001a346..aa62c97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,9 @@ target_force_link_libraries(${PROJECT_NAME} PRIVATE dbt-rise-core) get_target_property(DBT_CORE_INCL dbt-rise-core INTERFACE_INCLUDE_DIRECTORIES) target_include_directories(${PROJECT_NAME} INTERFACE ${DBT_CORE_INCL}) get_target_property(DBT_CORE_DEFS dbt-rise-core INTERFACE_COMPILE_DEFINITIONS) -target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS}) +if(NOT (DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND)) + target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS}) +endif() target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine) if(TARGET jsoncpp::jsoncpp) diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 96ba762..7d3a38c 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -76,10 +76,10 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { constexpr static char const* const core_type = "${coreDef.name}"; static constexpr std::array reg_names{ - {"${registers.collect{it.name}.join('", "')}"}}; + {"${registers.collect{it.name.toLowerCase()}.join('", "')}"}}; static constexpr std::array reg_aliases{ - {"${registers.collect{it.alias}.join('", "')}"}}; + {"${registers.collect{it.alias.toLowerCase()}.join('", "')}"}}; enum constants {${constants.collect{c -> c.name+"="+getCString(c.value)}.join(', ')}}; diff --git a/src/iss/arch/tgc5c.h b/src/iss/arch/tgc5c.h index 319f31f..76e6200 100644 --- a/src/iss/arch/tgc5c.h +++ b/src/iss/arch/tgc5c.h @@ -48,10 +48,10 @@ template <> struct traits { constexpr static char const* const core_type = "TGC5C"; static constexpr std::array reg_names{ - {"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", "X29", "X30", "X31", "PC", "NEXT_PC", "PRIV", "DPC"}}; + {"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", "next_pc", "priv", "dpc"}}; static constexpr std::array reg_aliases{ - {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; + {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}}; enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL}; diff --git a/src/vm/interp/vm_tgc5c.cpp b/src/vm/interp/vm_tgc5c.cpp index 4ba2443..639cb6d 100644 --- a/src/vm/interp/vm_tgc5c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -719,9 +719,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int8_t read_res = super::template read_mem(traits::MEM, load_address); + int8_t res_27 = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int8_t res = (int8_t)read_res; + int8_t res = (int8_t)res_27; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -750,9 +750,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int16_t read_res = super::template read_mem(traits::MEM, load_address); + int16_t res_28 = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int16_t res = (int16_t)read_res; + int16_t res = (int16_t)res_28; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -781,9 +781,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int32_t read_res = super::template read_mem(traits::MEM, load_address); + int32_t res_29 = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int32_t res = (int32_t)read_res; + int32_t res = (int32_t)res_29; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -812,9 +812,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint8_t read_res = super::template read_mem(traits::MEM, load_address); + uint8_t res_30 = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint8_t res = read_res; + uint8_t res = res_30; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -843,9 +843,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint16_t read_res = super::template read_mem(traits::MEM, load_address); + uint16_t res_31 = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint16_t res = read_res; + uint16_t res = res_31; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -1543,9 +1543,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { uint32_t xrs1 = *(X+rs1); if(rd != 0) { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_32 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_32; super::template write_mem(traits::CSR, csr, xrs1); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); *(X+rd) = xrd; @@ -1578,9 +1578,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_33 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_33; uint32_t xrs1 = *(X+rs1); if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd | xrs1); @@ -1613,9 +1613,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_34 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_34; uint32_t xrs1 = *(X+rs1); if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); @@ -1648,9 +1648,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_35 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_35; super::template write_mem(traits::CSR, csr, (uint32_t)zimm); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(rd != 0) { @@ -1680,9 +1680,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_36 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_36; if(zimm != 0) { super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); @@ -1714,9 +1714,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_37 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_37; if(zimm != 0) { super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); @@ -2051,9 +2051,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); - int32_t read_res = super::template read_mem(traits::MEM, offs); + int32_t res_38 = super::template read_mem(traits::MEM, offs); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - *(X+rd + 8) = (uint32_t)(int32_t)read_res; + *(X+rd + 8) = (uint32_t)(int32_t)res_38; } break; }// @suppress("No break at end of case") @@ -2473,9 +2473,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t offs = (uint32_t)(*(X+2) + uimm); - int32_t read_res = super::template read_mem(traits::MEM, offs); + int32_t res_39 = super::template read_mem(traits::MEM, offs); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - *(X+rd) = (uint32_t)(int32_t)read_res; + *(X+rd) = (uint32_t)(int32_t)res_39; } } break; From c7038cafa5f1df1ab5a435308e8b34a95d7da793 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 19 Sep 2023 12:11:49 +0200 Subject: [PATCH 140/184] updates naming in checked-in sources --- src/iss/arch/tgc5c.h | 54 ++++++------- src/vm/interp/vm_tgc5c.cpp | 162 ++++++++++++++++++------------------- 2 files changed, 108 insertions(+), 108 deletions(-) diff --git a/src/iss/arch/tgc5c.h b/src/iss/arch/tgc5c.h index 76e6200..2dddbb3 100644 --- a/src/iss/arch/tgc5c.h +++ b/src/iss/arch/tgc5c.h @@ -141,35 +141,35 @@ template <> struct traits { DIVU = 54, REM = 55, REMU = 56, - CADDI4SPN = 57, - CLW = 58, - CSW = 59, - CADDI = 60, - CNOP = 61, - CJAL = 62, - CLI = 63, - CLUI = 64, - CADDI16SP = 65, + C__ADDI4SPN = 57, + C__LW = 58, + C__SW = 59, + C__ADDI = 60, + C__NOP = 61, + C__JAL = 62, + C__LI = 63, + C__LUI = 64, + C__ADDI16SP = 65, __reserved_clui = 66, - CSRLI = 67, - CSRAI = 68, - CANDI = 69, - CSUB = 70, - CXOR = 71, - COR = 72, - CAND = 73, - CJ = 74, - CBEQZ = 75, - CBNEZ = 76, - CSLLI = 77, - CLWSP = 78, - CMV = 79, - CJR = 80, + C__SRLI = 67, + C__SRAI = 68, + C__ANDI = 69, + C__SUB = 70, + C__XOR = 71, + C__OR = 72, + C__AND = 73, + C__J = 74, + C__BEQZ = 75, + C__BNEZ = 76, + C__SLLI = 77, + C__LWSP = 78, + C__MV = 79, + C__JR = 80, __reserved_cmv = 81, - CADD = 82, - CJALR = 83, - CEBREAK = 84, - CSWSP = 85, + C__ADD = 82, + C__JALR = 83, + C__EBREAK = 84, + C__SWSP = 85, DII = 86, MAX_OPCODE }; diff --git a/src/vm/interp/vm_tgc5c.cpp b/src/vm/interp/vm_tgc5c.cpp index 639cb6d..02c5144 100644 --- a/src/vm/interp/vm_tgc5c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -210,35 +210,35 @@ private: {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIVU}, {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REM}, {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REMU}, - {16, 0b0000000000000000, 0b1110000000000011, arch::traits::opcode_e::CADDI4SPN}, - {16, 0b0100000000000000, 0b1110000000000011, arch::traits::opcode_e::CLW}, - {16, 0b1100000000000000, 0b1110000000000011, arch::traits::opcode_e::CSW}, - {16, 0b0000000000000001, 0b1110000000000011, arch::traits::opcode_e::CADDI}, - {16, 0b0000000000000001, 0b1110111110000011, arch::traits::opcode_e::CNOP}, - {16, 0b0010000000000001, 0b1110000000000011, arch::traits::opcode_e::CJAL}, - {16, 0b0100000000000001, 0b1110000000000011, arch::traits::opcode_e::CLI}, - {16, 0b0110000000000001, 0b1110000000000011, arch::traits::opcode_e::CLUI}, - {16, 0b0110000100000001, 0b1110111110000011, arch::traits::opcode_e::CADDI16SP}, + {16, 0b0000000000000000, 0b1110000000000011, arch::traits::opcode_e::C__ADDI4SPN}, + {16, 0b0100000000000000, 0b1110000000000011, arch::traits::opcode_e::C__LW}, + {16, 0b1100000000000000, 0b1110000000000011, arch::traits::opcode_e::C__SW}, + {16, 0b0000000000000001, 0b1110000000000011, arch::traits::opcode_e::C__ADDI}, + {16, 0b0000000000000001, 0b1110111110000011, arch::traits::opcode_e::C__NOP}, + {16, 0b0010000000000001, 0b1110000000000011, arch::traits::opcode_e::C__JAL}, + {16, 0b0100000000000001, 0b1110000000000011, arch::traits::opcode_e::C__LI}, + {16, 0b0110000000000001, 0b1110000000000011, arch::traits::opcode_e::C__LUI}, + {16, 0b0110000100000001, 0b1110111110000011, arch::traits::opcode_e::C__ADDI16SP}, {16, 0b0110000000000001, 0b1111000001111111, arch::traits::opcode_e::__reserved_clui}, - {16, 0b1000000000000001, 0b1111110000000011, arch::traits::opcode_e::CSRLI}, - {16, 0b1000010000000001, 0b1111110000000011, arch::traits::opcode_e::CSRAI}, - {16, 0b1000100000000001, 0b1110110000000011, arch::traits::opcode_e::CANDI}, - {16, 0b1000110000000001, 0b1111110001100011, arch::traits::opcode_e::CSUB}, - {16, 0b1000110000100001, 0b1111110001100011, arch::traits::opcode_e::CXOR}, - {16, 0b1000110001000001, 0b1111110001100011, arch::traits::opcode_e::COR}, - {16, 0b1000110001100001, 0b1111110001100011, arch::traits::opcode_e::CAND}, - {16, 0b1010000000000001, 0b1110000000000011, arch::traits::opcode_e::CJ}, - {16, 0b1100000000000001, 0b1110000000000011, arch::traits::opcode_e::CBEQZ}, - {16, 0b1110000000000001, 0b1110000000000011, arch::traits::opcode_e::CBNEZ}, - {16, 0b0000000000000010, 0b1111000000000011, arch::traits::opcode_e::CSLLI}, - {16, 0b0100000000000010, 0b1110000000000011, arch::traits::opcode_e::CLWSP}, - {16, 0b1000000000000010, 0b1111000000000011, arch::traits::opcode_e::CMV}, - {16, 0b1000000000000010, 0b1111000001111111, arch::traits::opcode_e::CJR}, + {16, 0b1000000000000001, 0b1111110000000011, arch::traits::opcode_e::C__SRLI}, + {16, 0b1000010000000001, 0b1111110000000011, arch::traits::opcode_e::C__SRAI}, + {16, 0b1000100000000001, 0b1110110000000011, arch::traits::opcode_e::C__ANDI}, + {16, 0b1000110000000001, 0b1111110001100011, arch::traits::opcode_e::C__SUB}, + {16, 0b1000110000100001, 0b1111110001100011, arch::traits::opcode_e::C__XOR}, + {16, 0b1000110001000001, 0b1111110001100011, arch::traits::opcode_e::C__OR}, + {16, 0b1000110001100001, 0b1111110001100011, arch::traits::opcode_e::C__AND}, + {16, 0b1010000000000001, 0b1110000000000011, arch::traits::opcode_e::C__J}, + {16, 0b1100000000000001, 0b1110000000000011, arch::traits::opcode_e::C__BEQZ}, + {16, 0b1110000000000001, 0b1110000000000011, arch::traits::opcode_e::C__BNEZ}, + {16, 0b0000000000000010, 0b1111000000000011, arch::traits::opcode_e::C__SLLI}, + {16, 0b0100000000000010, 0b1110000000000011, arch::traits::opcode_e::C__LWSP}, + {16, 0b1000000000000010, 0b1111000000000011, arch::traits::opcode_e::C__MV}, + {16, 0b1000000000000010, 0b1111000001111111, arch::traits::opcode_e::C__JR}, {16, 0b1000000000000010, 0b1111111111111111, arch::traits::opcode_e::__reserved_cmv}, - {16, 0b1001000000000010, 0b1111000000000011, arch::traits::opcode_e::CADD}, - {16, 0b1001000000000010, 0b1111000001111111, arch::traits::opcode_e::CJALR}, - {16, 0b1001000000000010, 0b1111111111111111, arch::traits::opcode_e::CEBREAK}, - {16, 0b1100000000000010, 0b1110000000000011, arch::traits::opcode_e::CSWSP}, + {16, 0b1001000000000010, 0b1111000000000011, arch::traits::opcode_e::C__ADD}, + {16, 0b1001000000000010, 0b1111000001111111, arch::traits::opcode_e::C__JALR}, + {16, 0b1001000000000010, 0b1111111111111111, arch::traits::opcode_e::C__EBREAK}, + {16, 0b1100000000000010, 0b1110000000000011, arch::traits::opcode_e::C__SWSP}, {16, 0b0000000000000000, 0b1111111111111111, arch::traits::opcode_e::DII}, }}; @@ -2010,13 +2010,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI4SPN: { + case arch::traits::opcode_e::C__ADDI4SPN: { uint8_t rd = ((bit_sub<2,3>(instr))); uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2034,14 +2034,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLW: { + case arch::traits::opcode_e::C__LW: { uint8_t rd = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); this->core.disass_output(pc.val, mnemonic); } @@ -2057,14 +2057,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSW: { + case arch::traits::opcode_e::C__SW: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); this->core.disass_output(pc.val, mnemonic); } @@ -2079,13 +2079,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI: { + case arch::traits::opcode_e::C__ADDI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2105,11 +2105,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CNOP: { + case arch::traits::opcode_e::C__NOP: { uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cnop"); + this->core.disass_output(pc.val, "c__nop"); } // used registers// calculate next pc value *NEXT_PC = *PC + 2; @@ -2118,12 +2118,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJAL: { + case arch::traits::opcode_e::C__JAL: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2138,13 +2138,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLI: { + case arch::traits::opcode_e::C__LI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2164,13 +2164,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLUI: { + case arch::traits::opcode_e::C__LUI: { uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2188,12 +2188,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI16SP: { + case arch::traits::opcode_e::C__ADDI16SP: { uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), fmt::arg("nzimm", nzimm)); this->core.disass_output(pc.val, mnemonic); } @@ -2225,13 +2225,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRLI: { + case arch::traits::opcode_e::C__SRLI: { uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); this->core.disass_output(pc.val, mnemonic); } @@ -2244,13 +2244,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRAI: { + case arch::traits::opcode_e::C__SRAI: { uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); this->core.disass_output(pc.val, mnemonic); } @@ -2270,13 +2270,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CANDI: { + case arch::traits::opcode_e::C__ANDI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2289,13 +2289,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSUB: { + case arch::traits::opcode_e::C__SUB: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2308,13 +2308,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CXOR: { + case arch::traits::opcode_e::C__XOR: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2327,13 +2327,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::COR: { + case arch::traits::opcode_e::C__OR: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2346,13 +2346,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CAND: { + case arch::traits::opcode_e::C__AND: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2365,12 +2365,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJ: { + case arch::traits::opcode_e::C__J: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2383,13 +2383,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CBEQZ: { + case arch::traits::opcode_e::C__BEQZ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2405,13 +2405,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CBNEZ: { + case arch::traits::opcode_e::C__BNEZ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2427,13 +2427,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSLLI: { + case arch::traits::opcode_e::C__SLLI: { uint8_t nzuimm = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "c.slli"), fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); this->core.disass_output(pc.val, mnemonic); } @@ -2453,13 +2453,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLWSP: { + case arch::traits::opcode_e::C__LWSP: { uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); this->core.disass_output(pc.val, mnemonic); } @@ -2480,13 +2480,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CMV: { + case arch::traits::opcode_e::C__MV: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2506,12 +2506,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJR: { + case arch::traits::opcode_e::C__JR: { uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); } @@ -2543,13 +2543,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADD: { + case arch::traits::opcode_e::C__ADD: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2569,12 +2569,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJALR: { + case arch::traits::opcode_e::C__JALR: { uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); } @@ -2595,10 +2595,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CEBREAK: { + case arch::traits::opcode_e::C__EBREAK: { if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cebreak"); + this->core.disass_output(pc.val, "c__ebreak"); } // used registers// calculate next pc value *NEXT_PC = *PC + 2; @@ -2608,13 +2608,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSWSP: { + case arch::traits::opcode_e::C__SWSP: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); this->core.disass_output(pc.val, mnemonic); } From de45d068782e0bd7960dedced11c7ea041a13639 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Tue, 19 Sep 2023 16:26:07 +0200 Subject: [PATCH 141/184] adds initial working version of llvm backend --- CMakeLists.txt | 1 + gen_input/templates/llvm/CORENAME.cpp.gtl | 223 +- src/iss/arch/riscv_hart_m_p.h | 4 +- src/vm/llvm/vm_tgc5c.cpp | 7504 +++++++++++---------- 4 files changed, 4083 insertions(+), 3649 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 001a346..008c6b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,7 @@ if(TARGET RapidJSON) endif() if(WITH_LLVM) + find_package(LLVM) target_compile_definitions(${PROJECT_NAME} PUBLIC ${LLVM_DEFINITIONS}) target_include_directories(${PROJECT_NAME} PUBLIC ${LLVM_INCLUDE_DIRS}) if(BUILD_SHARED_LIBS) diff --git a/gen_input/templates/llvm/CORENAME.cpp.gtl b/gen_input/templates/llvm/CORENAME.cpp.gtl index 5eb61cf..4c074d4 100644 --- a/gen_input/templates/llvm/CORENAME.cpp.gtl +++ b/gen_input/templates/llvm/CORENAME.cpp.gtl @@ -58,6 +58,7 @@ using namespace iss::debugger; template class vm_impl : public iss::llvm::vm_base { public: + using traits = arch::traits; using super = typename iss::llvm::vm_base; using virt_addr_t = typename super::virt_addr_t; using phys_addr_t = typename super::phys_addr_t; @@ -80,7 +81,7 @@ public: protected: using vm_base::get_reg_ptr; - inline const char *name(size_t index){return traits::reg_aliases.at(index);} + inline const char *name(size_t index){return traits::reg_aliases.at(index);} template inline ConstantInt *size(T type) { return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); @@ -88,7 +89,7 @@ protected: void setup_module(Module* m) override { super::setup_module(m); - iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); + iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); } inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { @@ -114,88 +115,70 @@ protected: } inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { - Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); + Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), + this->get_type(traits::XLEN)); this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); } // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) }; using this_class = vm_impl; using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, code_word_t instr, BasicBlock *bb); - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } + template::type> + inline S sext(U from) { + auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> - /* instruction ${instr.instruction.name} */ - {${instr.length}, ${instr.value}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> + /* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */ + {${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> }}; /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> /* instruction ${idx}: ${instr.name} */ - std::tuple __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){<%instr.code.eachLine{%> - ${it}<%}%> + std::tuple __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("${instr.name}_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,${idx}); + uint64_t PC = pc.val; + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate console output when executing the command */<%instr.disass.eachLine{%> + ${it}<%}%> + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ ${instr.length/8}; + this->gen_set_pc(pc, traits::NEXT_PC); + <%instr.behavior.eachLine{%>${it} + <%}%> + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, ${idx}); + this->builder.CreateBr(bb); + return returnValue; } <%}%> /**************************************************************************** @@ -203,23 +186,75 @@ private: ****************************************************************************/ std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); + this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), true), + get_reg_ptr(traits::PC), true); this->builder.CreateStore( - this->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true), + this->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true), this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); + get_reg_ptr(traits::ICOUNT), true); pc = pc + ((instr & 3) == 3 ? 4 : 2); this->gen_raise_trap(0, 2); // illegal instruction trap this->gen_sync(iss::POST_SYNC, instr_descr.size()); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); + } + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; } }; -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; } template vm_impl::vm_impl() { this(new ARCH()); } @@ -227,14 +262,11 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } template @@ -242,50 +274,50 @@ std::tuple vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - // const typename traits::addr_t upper_bits = ~traits::PGMASK; + code_word_t instr = 0; + // const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; - paddr = this->core.v2p(pc); + auto *const data = (uint8_t *)&instr; + if(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); //TODO: re-add page handling // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // auto res = this->core.read(paddr, 2, data); // if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction +// if ((instr & 0x3) == 0x3) { // this is a 32bit instruction // res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); // } // } else { auto res = this->core.read(paddr, 4, data); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); // } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; + auto f = decode_instr(root, instr); if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, this_block); + return (this->*f)(pc, instr, this_block); } template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(arch::traits::NEXT_PC), get_reg_ptr(arch::traits::NEXT_PC), false)); + this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC),get_reg_ptr(traits::NEXT_PC), false)); } template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); - this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_leave_trap(unsigned lvl) { std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) }; this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); - auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_wait(unsigned type) { @@ -295,22 +327,25 @@ template void vm_impl::gen_wait(unsigned type) { template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(arch::traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); + this->gen_sync(POST_SYNC, -1); //TODO get right InstrId + auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), - get_reg_ptr(traits::LAST_BRANCH), false); + get_reg_ptr(traits::LAST_BRANCH), false); std::vector args{this->core_ptr, this->adj_to64(trap_state_val), - this->adj_to64(this->builder.CreateLoad(this->get_typeptr(arch::traits::PC), get_reg_ptr(traits::PC), false))}; + this->adj_to64(this->builder.CreateLoad(this->get_typeptr(traits::PC), get_reg_ptr(traits::PC), false))}; this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); - auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(arch::traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false); + auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false); this->builder.CreateRet(trap_addr_val); } template inline void vm_impl::gen_trap_check(BasicBlock *bb) { - auto *v = this->builder.CreateLoad(this->get_typeptr(arch::traits::TRAP_STATE), get_reg_ptr(arch::traits::TRAP_STATE), true); + auto* target_bb = BasicBlock::Create(this->mod->getContext(), "", this->func, bb); + auto *v = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); this->gen_cond_branch(this->builder.CreateICmp( ICmpInst::ICMP_EQ, v, ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, this->trap_blk, 1); + target_bb, this->trap_blk, 1); + this->builder.SetInsertPoint(target_bb); } } // namespace ${coreDef.name.toLowerCase()} diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 632bdd2..1481b30 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -1113,8 +1113,10 @@ iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned le } this->reg.trap_state=std::numeric_limits::max(); this->interrupt_sim=hostvar; +#ifndef WITH_TCC + throw(iss::simulation_stopped(hostvar)); +#endif break; - //throw(iss::simulation_stopped(hostvar)); case 0x0101: { char c = static_cast(hostvar & 0xff); if (c == '\n' || c == 0) { diff --git a/src/vm/llvm/vm_tgc5c.cpp b/src/vm/llvm/vm_tgc5c.cpp index 1b327ab..5c7fd34 100644 --- a/src/vm/llvm/vm_tgc5c.cpp +++ b/src/vm/llvm/vm_tgc5c.cpp @@ -30,7 +30,6 @@ * *******************************************************************************/ -#include #include #include #include @@ -59,6 +58,7 @@ using namespace iss::debugger; template class vm_impl : public iss::llvm::vm_base { public: + using traits = arch::traits; using super = typename iss::llvm::vm_base; using virt_addr_t = typename super::virt_addr_t; using phys_addr_t = typename super::phys_addr_t; @@ -81,7 +81,7 @@ public: protected: using vm_base::get_reg_ptr; - inline const char *name(size_t index){return traits::reg_aliases.at(index);} + inline const char *name(size_t index){return traits::reg_aliases.at(index);} template inline ConstantInt *size(T type) { return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits())); @@ -89,7 +89,7 @@ protected: void setup_module(Module* m) override { super::setup_module(m); - iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); + iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN); } inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) { @@ -111,3930 +111,4253 @@ protected: void gen_trap_check(BasicBlock *bb); inline Value *gen_reg_load(unsigned i, unsigned level = 0) { - return this->builder.CreateLoad(get_reg_ptr(i), false); + return this->builder.CreateLoad(this->get_typeptr(i), get_reg_ptr(i), false); } inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { - Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), - this->get_type(traits::XLEN)); + Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), + this->get_type(traits::XLEN)); this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); } // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count((uint32_t)EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count((uint32_t)EXTR_MASK16) }; using this_class = vm_impl; using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, code_word_t instr, BasicBlock *bb); - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } + template::type> + inline S sext(U from) { + auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; - const std::array instr_descr = {{ + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ - /* instruction LUI */ + /* instruction LUI, encoding '0b00000000000000000000000000110111' */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, - /* instruction AUIPC */ + /* instruction AUIPC, encoding '0b00000000000000000000000000010111' */ {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, - /* instruction JAL */ + /* instruction JAL, encoding '0b00000000000000000000000001101111' */ {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, - /* instruction JALR */ + /* instruction JALR, encoding '0b00000000000000000000000001100111' */ {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, - /* instruction BEQ */ + /* instruction BEQ, encoding '0b00000000000000000000000001100011' */ {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, - /* instruction BNE */ + /* instruction BNE, encoding '0b00000000000000000001000001100011' */ {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, - /* instruction BLT */ + /* instruction BLT, encoding '0b00000000000000000100000001100011' */ {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, - /* instruction BGE */ + /* instruction BGE, encoding '0b00000000000000000101000001100011' */ {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, - /* instruction BLTU */ + /* instruction BLTU, encoding '0b00000000000000000110000001100011' */ {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, - /* instruction BGEU */ + /* instruction BGEU, encoding '0b00000000000000000111000001100011' */ {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, - /* instruction LB */ + /* instruction LB, encoding '0b00000000000000000000000000000011' */ {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, - /* instruction LH */ + /* instruction LH, encoding '0b00000000000000000001000000000011' */ {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, - /* instruction LW */ + /* instruction LW, encoding '0b00000000000000000010000000000011' */ {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, - /* instruction LBU */ + /* instruction LBU, encoding '0b00000000000000000100000000000011' */ {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, - /* instruction LHU */ + /* instruction LHU, encoding '0b00000000000000000101000000000011' */ {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, - /* instruction SB */ + /* instruction SB, encoding '0b00000000000000000000000000100011' */ {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, - /* instruction SH */ + /* instruction SH, encoding '0b00000000000000000001000000100011' */ {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, - /* instruction SW */ + /* instruction SW, encoding '0b00000000000000000010000000100011' */ {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, - /* instruction ADDI */ + /* instruction ADDI, encoding '0b00000000000000000000000000010011' */ {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, - /* instruction SLTI */ + /* instruction SLTI, encoding '0b00000000000000000010000000010011' */ {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, - /* instruction SLTIU */ + /* instruction SLTIU, encoding '0b00000000000000000011000000010011' */ {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, - /* instruction XORI */ + /* instruction XORI, encoding '0b00000000000000000100000000010011' */ {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, - /* instruction ORI */ + /* instruction ORI, encoding '0b00000000000000000110000000010011' */ {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, - /* instruction ANDI */ + /* instruction ANDI, encoding '0b00000000000000000111000000010011' */ {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, - /* instruction SLLI */ + /* instruction SLLI, encoding '0b00000000000000000001000000010011' */ {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, - /* instruction SRLI */ + /* instruction SRLI, encoding '0b00000000000000000101000000010011' */ {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, - /* instruction SRAI */ + /* instruction SRAI, encoding '0b01000000000000000101000000010011' */ {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, - /* instruction ADD */ + /* instruction ADD, encoding '0b00000000000000000000000000110011' */ {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, - /* instruction SUB */ + /* instruction SUB, encoding '0b01000000000000000000000000110011' */ {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, - /* instruction SLL */ + /* instruction SLL, encoding '0b00000000000000000001000000110011' */ {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, - /* instruction SLT */ + /* instruction SLT, encoding '0b00000000000000000010000000110011' */ {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, - /* instruction SLTU */ + /* instruction SLTU, encoding '0b00000000000000000011000000110011' */ {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, - /* instruction XOR */ + /* instruction XOR, encoding '0b00000000000000000100000000110011' */ {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, - /* instruction SRL */ + /* instruction SRL, encoding '0b00000000000000000101000000110011' */ {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, - /* instruction SRA */ + /* instruction SRA, encoding '0b01000000000000000101000000110011' */ {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, - /* instruction OR */ + /* instruction OR, encoding '0b00000000000000000110000000110011' */ {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, - /* instruction AND */ + /* instruction AND, encoding '0b00000000000000000111000000110011' */ {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, - /* instruction FENCE */ - {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, - /* instruction FENCE_I */ - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, - /* instruction ECALL */ + /* instruction FENCE, encoding '0b00000000000000000000000000001111' */ + {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, &this_class::__fence}, + /* instruction ECALL, encoding '0b00000000000000000000000001110011' */ {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, - /* instruction EBREAK */ + /* instruction EBREAK, encoding '0b00000000000100000000000001110011' */ {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, - /* instruction URET */ - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, - /* instruction SRET */ - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, - /* instruction MRET */ + /* instruction MRET, encoding '0b00110000001000000000000001110011' */ {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, - /* instruction WFI */ + /* instruction WFI, encoding '0b00010000010100000000000001110011' */ {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, - /* instruction SFENCE.VMA */ - {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, - /* instruction CSRRW */ + /* instruction CSRRW, encoding '0b00000000000000000001000001110011' */ {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, - /* instruction CSRRS */ + /* instruction CSRRS, encoding '0b00000000000000000010000001110011' */ {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, - /* instruction CSRRC */ + /* instruction CSRRC, encoding '0b00000000000000000011000001110011' */ {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, - /* instruction CSRRWI */ + /* instruction CSRRWI, encoding '0b00000000000000000101000001110011' */ {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, - /* instruction CSRRSI */ + /* instruction CSRRSI, encoding '0b00000000000000000110000001110011' */ {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, - /* instruction CSRRCI */ + /* instruction CSRRCI, encoding '0b00000000000000000111000001110011' */ {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, - /* instruction MUL */ + /* instruction FENCE_I, encoding '0b00000000000000000001000000001111' */ + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, + /* instruction MUL, encoding '0b00000010000000000000000000110011' */ {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, - /* instruction MULH */ + /* instruction MULH, encoding '0b00000010000000000001000000110011' */ {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, - /* instruction MULHSU */ + /* instruction MULHSU, encoding '0b00000010000000000010000000110011' */ {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, - /* instruction MULHU */ + /* instruction MULHU, encoding '0b00000010000000000011000000110011' */ {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, - /* instruction DIV */ + /* instruction DIV, encoding '0b00000010000000000100000000110011' */ {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, - /* instruction DIVU */ + /* instruction DIVU, encoding '0b00000010000000000101000000110011' */ {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, - /* instruction REM */ + /* instruction REM, encoding '0b00000010000000000110000000110011' */ {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, - /* instruction REMU */ + /* instruction REMU, encoding '0b00000010000000000111000000110011' */ {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction C.ADDI4SPN */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, - /* instruction C.LW */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, - /* instruction C.SW */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, - /* instruction C.ADDI */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, - /* instruction C.NOP */ - {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, - /* instruction C.JAL */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, - /* instruction C.LI */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, - /* instruction C.LUI */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, - /* instruction C.ADDI16SP */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, - /* instruction C.SRLI */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, - /* instruction C.SRAI */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, - /* instruction C.ANDI */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, - /* instruction C.SUB */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, - /* instruction C.XOR */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, - /* instruction C.OR */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, - /* instruction C.AND */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, - /* instruction C.J */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, - /* instruction C.BEQZ */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, - /* instruction C.BNEZ */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, - /* instruction C.SLLI */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, - /* instruction C.LWSP */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, - /* instruction C.MV */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, - /* instruction C.JR */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, - /* instruction C.ADD */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, - /* instruction C.JALR */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, - /* instruction C.EBREAK */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, - /* instruction C.SWSP */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, - /* instruction DII */ + /* instruction CADDI4SPN, encoding '0b0000000000000000' */ + {16, 0b0000000000000000, 0b1110000000000011, &this_class::__caddi4spn}, + /* instruction CLW, encoding '0b0100000000000000' */ + {16, 0b0100000000000000, 0b1110000000000011, &this_class::__clw}, + /* instruction CSW, encoding '0b1100000000000000' */ + {16, 0b1100000000000000, 0b1110000000000011, &this_class::__csw}, + /* instruction CADDI, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110000000000011, &this_class::__caddi}, + /* instruction CNOP, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110111110000011, &this_class::__cnop}, + /* instruction CJAL, encoding '0b0010000000000001' */ + {16, 0b0010000000000001, 0b1110000000000011, &this_class::__cjal}, + /* instruction CLI, encoding '0b0100000000000001' */ + {16, 0b0100000000000001, 0b1110000000000011, &this_class::__cli}, + /* instruction CLUI, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1110000000000011, &this_class::__clui}, + /* instruction CADDI16SP, encoding '0b0110000100000001' */ + {16, 0b0110000100000001, 0b1110111110000011, &this_class::__caddi16sp}, + /* instruction __reserved_clui, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1111000001111111, &this_class::____reserved_clui}, + /* instruction CSRLI, encoding '0b1000000000000001' */ + {16, 0b1000000000000001, 0b1111110000000011, &this_class::__csrli}, + /* instruction CSRAI, encoding '0b1000010000000001' */ + {16, 0b1000010000000001, 0b1111110000000011, &this_class::__csrai}, + /* instruction CANDI, encoding '0b1000100000000001' */ + {16, 0b1000100000000001, 0b1110110000000011, &this_class::__candi}, + /* instruction CSUB, encoding '0b1000110000000001' */ + {16, 0b1000110000000001, 0b1111110001100011, &this_class::__csub}, + /* instruction CXOR, encoding '0b1000110000100001' */ + {16, 0b1000110000100001, 0b1111110001100011, &this_class::__cxor}, + /* instruction COR, encoding '0b1000110001000001' */ + {16, 0b1000110001000001, 0b1111110001100011, &this_class::__cor}, + /* instruction CAND, encoding '0b1000110001100001' */ + {16, 0b1000110001100001, 0b1111110001100011, &this_class::__cand}, + /* instruction CJ, encoding '0b1010000000000001' */ + {16, 0b1010000000000001, 0b1110000000000011, &this_class::__cj}, + /* instruction CBEQZ, encoding '0b1100000000000001' */ + {16, 0b1100000000000001, 0b1110000000000011, &this_class::__cbeqz}, + /* instruction CBNEZ, encoding '0b1110000000000001' */ + {16, 0b1110000000000001, 0b1110000000000011, &this_class::__cbnez}, + /* instruction CSLLI, encoding '0b0000000000000010' */ + {16, 0b0000000000000010, 0b1111000000000011, &this_class::__cslli}, + /* instruction CLWSP, encoding '0b0100000000000010' */ + {16, 0b0100000000000010, 0b1110000000000011, &this_class::__clwsp}, + /* instruction CMV, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000000000011, &this_class::__cmv}, + /* instruction CJR, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000001111111, &this_class::__cjr}, + /* instruction __reserved_cmv, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111111111111111, &this_class::____reserved_cmv}, + /* instruction CADD, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000000000011, &this_class::__cadd}, + /* instruction CJALR, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000001111111, &this_class::__cjalr}, + /* instruction CEBREAK, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__cebreak}, + /* instruction CSWSP, encoding '0b1100000000000010' */ + {16, 0b1100000000000010, 0b1110000000000011, &this_class::__cswsp}, + /* instruction DII, encoding '0b0000000000000000' */ {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, }}; /* instruction definitions */ /* instruction 0: LUI */ std::tuple __lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LUI"); - - this->gen_sync(PRE_SYNC, 0); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LUI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,0); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)((int32_t)imm)), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 0); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 1: AUIPC */ std::tuple __auipc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AUIPC"); - - this->gen_sync(PRE_SYNC, 1); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,20>(instr) << 12)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("AUIPC_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,1); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)(PC+(int32_t)imm)), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 1); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 2: JAL */ std::tuple __jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JAL"); - - this->gen_sync(PRE_SYNC, 2); - - uint8_t rd = ((bit_sub<7,5>(instr))); - int32_t imm = signextend((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("JAL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,2); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)(PC+ 4)), + get_reg_ptr(rd + traits::X0), false); + } + auto PC_val_v = (uint32_t)(PC+(int32_t)sext<21>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 2); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 3: JALR */ std::tuple __jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("JALR"); - - this->gen_sync(PRE_SYNC, 3); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* new_pc_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* PC_val = this->builder.CreateAnd( - new_pc_val, - this->builder.CreateNot(this->gen_const(32U, 0x1))); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("JALR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,3); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto addr_mask =this->gen_const(32,(uint32_t)- 2); + auto new_pc =this->gen_ext( + (this->builder.CreateAnd( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + this->gen_ext(addr_mask, 64,false)) + ), + 32, true); + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateURem( + new_pc, + this->gen_const(32,static_cast(traits::INSTR_ALIGNMENT))) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + this->gen_raise_trap(0, 0); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)(PC+ 4)), + get_reg_ptr(rd + traits::X0), false); + } + auto PC_val_v = new_pc; + this->builder.CreateStore(PC_val_v, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 3); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 4: BEQ */ std::tuple __beq(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BEQ"); - - this->gen_sync(PRE_SYNC, 4); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BEQ_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,4); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 4); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 5: BNE */ std::tuple __bne(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BNE"); - - this->gen_sync(PRE_SYNC, 5); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BNE_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,5); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 5); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 6: BLT */ std::tuple __blt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLT"); - - this->gen_sync(PRE_SYNC, 6); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BLT_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,6); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), + 32, false), + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 6); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 7: BGE */ std::tuple __bge(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGE"); - - this->gen_sync(PRE_SYNC, 7); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SGE, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BGE_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,7); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_SGE, + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), + 32, false), + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 7); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 8: BLTU */ std::tuple __bltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BLTU"); - - this->gen_sync(PRE_SYNC, 8); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BLTU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,8); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_ULT, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 8); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 9: BGEU */ std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("BGEU"); - - this->gen_sync(PRE_SYNC, 9); - - int16_t imm = signextend((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), - fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_UGE, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 4)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + bb->setName(fmt::format("BGEU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,9); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"), + fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_UGE, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ this->gen_raise_trap(0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 9); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 10: LB */ std::tuple __lb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LB"); - - this->gen_sync(PRE_SYNC, 10); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LB_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,10); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto load_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + auto res =this->gen_ext( + this->gen_read_mem(traits::MEM, load_address, 1), + 8, false); + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 10); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 11: LH */ std::tuple __lh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LH"); - - this->gen_sync(PRE_SYNC, 11); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LH_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,11); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto load_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + auto res =this->gen_ext( + this->gen_read_mem(traits::MEM, load_address, 2), + 16, false); + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 11); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 12: LW */ std::tuple __lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LW"); - - this->gen_sync(PRE_SYNC, 12); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LW_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,12); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto load_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + auto res =this->gen_ext( + this->gen_read_mem(traits::MEM, load_address, 4), + 32, false); + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 12); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 13: LBU */ std::tuple __lbu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LBU"); - - this->gen_sync(PRE_SYNC, 13); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 8/8), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LBU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,13); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto load_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + auto res =this->gen_read_mem(traits::MEM, load_address, 1); + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 13); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 14: LHU */ std::tuple __lhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("LHU"); - - this->gen_sync(PRE_SYNC, 14); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - if(rd != 0){ - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 16/8), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("LHU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,14); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto load_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + auto res =this->gen_read_mem(traits::MEM, load_address, 2); + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 14); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 15: SB */ std::tuple __sb(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SB"); - - this->gen_sync(PRE_SYNC, 15); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(8))); - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SB_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,15); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto store_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + this->gen_write_mem(traits::MEM, + store_address, + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 8, false)); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 15); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 16: SH */ std::tuple __sh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SH"); - - this->gen_sync(PRE_SYNC, 16); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(16))); - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SH_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,16); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto store_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + this->gen_write_mem(traits::MEM, + store_address, + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 16, false)); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 16); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 17: SW */ std::tuple __sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SW"); - - this->gen_sync(PRE_SYNC, 17); - - int16_t imm = signextend((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), - fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* offs_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SW_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,17); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"), + fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto store_address =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true); + this->gen_write_mem(traits::MEM, + store_address, + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false)); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 17); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 18: ADDI */ std::tuple __addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADDI"); - - this->gen_sync(PRE_SYNC, 18); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("ADDI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,18); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 64,true)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 18); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 19: SLTI */ std::tuple __slti(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTI"); - - this->gen_sync(PRE_SYNC, 19); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLTI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,19); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->gen_choose((this->builder.CreateICmp(ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + this->gen_ext(this->gen_const(16,(int16_t)sext<12>(imm)), 32,true)) + ), + this->gen_const(8, 1), + this->gen_const(8, 0), + 1), 32), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 19); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 20: SLTIU */ std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTIU"); - - this->gen_sync(PRE_SYNC, 20); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - int32_t full_imm_val = imm; - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, full_imm_val)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLTIU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,20); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->gen_choose((this->builder.CreateICmp(ICmpInst::ICMP_ULT, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_const(32,(uint32_t)((int16_t)sext<12>(imm)))) + ), + this->gen_const(8, 1), + this->gen_const(8, 0), + 1), 32), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 20); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 21: XORI */ std::tuple __xori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XORI"); - - this->gen_sync(PRE_SYNC, 21); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("XORI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,21); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateXor( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_const(32,(uint32_t)((int16_t)sext<12>(imm)))) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 21); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 22: ORI */ std::tuple __ori(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ORI"); - - this->gen_sync(PRE_SYNC, 22); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("ORI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,22); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateOr( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_const(32,(uint32_t)((int16_t)sext<12>(imm)))) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 22); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 23: ANDI */ std::tuple __andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ANDI"); - - this->gen_sync(PRE_SYNC, 23); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - int16_t imm = signextend((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("ANDI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,23); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateAnd( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_const(32,(uint32_t)((int16_t)sext<12>(imm)))) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 23); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 24: SLLI */ std::tuple __slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLLI"); - - this->gen_sync(PRE_SYNC, 24); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLLI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,24); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateShl( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_ext(this->gen_const(8,shamt), 32,false)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 24); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 25: SRLI */ std::tuple __srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRLI"); - - this->gen_sync(PRE_SYNC, 25); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SRLI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,25); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateLShr( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_ext(this->gen_const(8,shamt), 32,false)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 25); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 26: SRAI */ std::tuple __srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRAI"); - - this->gen_sync(PRE_SYNC, 26); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t shamt = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(shamt > 31){ - this->gen_raise_trap(0, 0); - } else { - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SRAI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,26); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAShr( + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + this->gen_ext(this->gen_const(8,shamt), 32,false)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 26); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 27: ADD */ std::tuple __add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ADD"); - - this->gen_sync(PRE_SYNC, 27); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("ADD_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,27); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false)) + ), + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 27); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 28: SUB */ std::tuple __sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SUB"); - - this->gen_sync(PRE_SYNC, 28); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SUB_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,28); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateSub( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 28); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 29: SLL */ std::tuple __sll(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLL"); - - this->gen_sync(PRE_SYNC, 29); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,29); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->builder.CreateShl( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + (this->builder.CreateAnd( + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false), + this->gen_const(64,(static_cast(traits::XLEN)- 1))) + )) + , 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 29); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 30: SLT */ std::tuple __slt(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLT"); - - this->gen_sync(PRE_SYNC, 30); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_SLT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, true)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLT_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,30); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->gen_choose(this->builder.CreateICmp(ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), 32,true)) + , + this->gen_const(8, 1), + this->gen_const(8, 0), + 1), 32), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 30); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 31: SLTU */ std::tuple __sltu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SLTU"); - - this->gen_sync(PRE_SYNC, 31); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 32, - false)), - this->gen_const(32U, 1), - this->gen_const(32U, 0), - 32); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SLTU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,31); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->gen_choose(this->builder.CreateICmp(ICmpInst::ICMP_ULT, + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , + this->gen_const(8, 1), + this->gen_const(8, 0), + 1), 32), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 31); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 32: XOR */ std::tuple __xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("XOR"); - - this->gen_sync(PRE_SYNC, 32); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("XOR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,32); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateXor( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 32); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 33: SRL */ std::tuple __srl(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRL"); - - this->gen_sync(PRE_SYNC, 33); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SRL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,33); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext(this->builder.CreateLShr( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + (this->builder.CreateAnd( + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false), + this->gen_const(64,(static_cast(traits::XLEN)- 1))) + )) + , 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 33); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 34: SRA */ std::tuple __sra(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRA"); - - this->gen_sync(PRE_SYNC, 34); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->builder.CreateAnd( - this->gen_reg_load(rs2 + traits::X0, 0), - this->builder.CreateSub( - this->gen_const(32U, 32), - this->gen_const(32U, 1)))); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("SRA_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,34); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->gen_ext(this->builder.CreateAShr( + this->gen_ext(this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), 64,true), + (this->builder.CreateAnd( + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false), + this->gen_const(64,(static_cast(traits::XLEN)- 1))) + )) + , 32, true)), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 34); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 35: OR */ std::tuple __or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("OR"); - - this->gen_sync(PRE_SYNC, 35); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("OR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,35); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateOr( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 35); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 36: AND */ std::tuple __and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("AND"); - - this->gen_sync(PRE_SYNC, 36); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("AND_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,36); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->builder.CreateAnd( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 36); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } /* instruction 37: FENCE */ std::tuple __fence(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE"); - - this->gen_sync(PRE_SYNC, 37); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t succ = ((bit_sub<20,4>(instr))); - uint8_t pred = ((bit_sub<24,4>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->builder.CreateOr( - this->builder.CreateShl( - this->gen_const(32U, pred), - this->gen_const(32U, 4)), - this->gen_const(32U, succ)); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 0), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("FENCE_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,37); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + uint8_t fm = ((bit_sub<28,4>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"), + fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_write_mem(traits::FENCE, + static_cast(traits::fence), + this->gen_const(8,(uint8_t)pred<< 4|succ)); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 37); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 38: FENCE_I */ - std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("FENCE_I"); - - this->gen_sync(PRE_SYNC, 38); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t imm = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("fence_i"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, imm); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 1), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 38); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(FLUSH, nullptr); - } - - /* instruction 39: ECALL */ + /* instruction 38: ECALL */ std::tuple __ecall(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("ECALL"); - - this->gen_sync(PRE_SYNC, 39); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ecall"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 11); - this->gen_sync(POST_SYNC, 39); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + bb->setName(fmt::format("ECALL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,38); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 11); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 38); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 40: EBREAK */ + /* instruction 39: EBREAK */ std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("EBREAK"); - - this->gen_sync(PRE_SYNC, 40); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("ebreak"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_raise_trap(0, 3); - this->gen_sync(POST_SYNC, 40); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + bb->setName(fmt::format("EBREAK_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,39); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 3); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 39); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 41: URET */ - std::tuple __uret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("URET"); - - this->gen_sync(PRE_SYNC, 41); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("uret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(0); - this->gen_sync(POST_SYNC, 41); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 42: SRET */ - std::tuple __sret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SRET"); - - this->gen_sync(PRE_SYNC, 42); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(1); - this->gen_sync(POST_SYNC, 42); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); - } - - /* instruction 43: MRET */ + /* instruction 40: MRET */ std::tuple __mret(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MRET"); - - this->gen_sync(PRE_SYNC, 43); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("mret"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_leave_trap(3); - this->gen_sync(POST_SYNC, 43); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + bb->setName(fmt::format("MRET_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,40); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_leave_trap(3); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 40); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 44: WFI */ + /* instruction 41: WFI */ std::tuple __wfi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("WFI"); - - this->gen_sync(PRE_SYNC, 44); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("wfi"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - this->gen_wait(1); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 44); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("WFI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,41); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_wait(1); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 41); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 45: SFENCE.VMA */ - std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("SFENCE.VMA"); - - this->gen_sync(PRE_SYNC, 45); - - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("sfence.vma"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* FENCEtmp0_val = this->gen_const(32U, rs1); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 2), - this->builder.CreateZExtOrTrunc(FENCEtmp0_val,this->get_type(32))); - Value* FENCEtmp1_val = this->gen_const(32U, rs2); - this->gen_write_mem( - traits::FENCE, - this->gen_const(64U, 3), - this->builder.CreateZExtOrTrunc(FENCEtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 45); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 46: CSRRW */ + /* instruction 42: CSRRW */ std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRW"); - - this->gen_sync(PRE_SYNC, 46); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* rs_val_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* csr_val_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* CSRtmp0_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - Value* Xtmp1_val = csr_val_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } else { - Value* CSRtmp2_val = rs_val_val; - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp2_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 46); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRW_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,42); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrs1 =this->gen_reg_load(rs1+ traits::X0, 0); + if(rd!= 0){ auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + this->gen_write_mem(traits::CSR, + csr, + xrs1); + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + else{ + this->gen_write_mem(traits::CSR, + csr, + xrs1); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 42); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 47: CSRRS */ + /* instruction 43: CSRRS */ std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRS"); - - this->gen_sync(PRE_SYNC, 47); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateOr( - xrd_val, - xrs1_val); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 47); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRS_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,43); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + auto xrs1 =this->gen_reg_load(rs1+ traits::X0, 0); + if(rs1!= 0) { + this->gen_write_mem(traits::CSR, + csr, + this->builder.CreateOr( + xrd, + xrs1) + ); + } + if(rd!= 0) { + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 43); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 48: CSRRC */ + /* instruction 44: CSRRC */ std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRC"); - - this->gen_sync(PRE_SYNC, 48); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* xrd_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - Value* xrs1_val = this->gen_reg_load(rs1 + traits::X0, 0); - if(rd != 0){ - Value* Xtmp0_val = xrd_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(rs1 != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - xrd_val, - this->builder.CreateNot(xrs1_val)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 48); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRC_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,44); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + auto xrs1 =this->gen_reg_load(rs1+ traits::X0, 0); + if(rs1!= 0) { + this->gen_write_mem(traits::CSR, + csr, + this->builder.CreateAnd( + xrd, + this->builder.CreateNeg(xrs1)) + ); + } + if(rd!= 0) { + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 44); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 49: CSRRWI */ + /* instruction 45: CSRRWI */ std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRWI"); - - this->gen_sync(PRE_SYNC, 49); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* Xtmp0_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - Value* CSRtmp1_val = this->gen_ext( - this->gen_const(32U, zimm), - 32, - false); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 49); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRWI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,45); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + this->gen_write_mem(traits::CSR, + csr, + this->gen_const(32,(uint32_t)zimm)); + if(rd!= 0) { + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 45); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 50: CSRRSI */ + /* instruction 46: CSRRSI */ std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRSI"); - - this->gen_sync(PRE_SYNC, 50); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - if(zimm != 0){ - Value* CSRtmp0_val = this->builder.CreateOr( - res_val, - this->gen_ext( - this->gen_const(32U, zimm), - 32, - false)); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp0_val,this->get_type(32))); - } - if(rd != 0){ - Value* Xtmp1_val = res_val; - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 50); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRSI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,46); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + if(zimm!= 0) { + this->gen_write_mem(traits::CSR, + csr, + this->builder.CreateOr( + xrd, + this->gen_const(32,(uint32_t)zimm)) + ); + } + if(rd!= 0) { + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 46); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 51: CSRRCI */ + /* instruction 47: CSRRCI */ std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("CSRRCI"); - - this->gen_sync(PRE_SYNC, 51); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t zimm = ((bit_sub<15,5>(instr))); - uint16_t csr = ((bit_sub<20,12>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), - fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - Value* res_val = this->gen_read_mem(traits::CSR, this->gen_const(16U, csr), 32/8); - if(rd != 0){ - Value* Xtmp0_val = res_val; - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - if(zimm != 0){ - Value* CSRtmp1_val = this->builder.CreateAnd( - res_val, - this->builder.CreateNot(this->gen_ext( - this->gen_const(32U, zimm), - 32, - false))); - this->gen_write_mem( - traits::CSR, - this->gen_const(16U, csr), - this->builder.CreateZExtOrTrunc(CSRtmp1_val,this->get_type(32))); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 51); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("CSRRCI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,47); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"), + fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto xrd =this->gen_read_mem(traits::CSR, csr, 4); + if(zimm!= 0) { + this->gen_write_mem(traits::CSR, + csr, + this->builder.CreateAnd( + xrd, + this->gen_const(32,~ ((uint32_t)zimm))) + ); + } + if(rd!= 0) { + this->builder.CreateStore( + xrd, + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 47); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 52: MUL */ + /* instruction 48: FENCE_I */ + std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("FENCE_I_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,48); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), + fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_write_mem(traits::FENCE, + static_cast(traits::fencei), + this->gen_const(16,imm)); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 48); + this->builder.CreateBr(bb); + return returnValue; + } + + /* instruction 49: MUL */ std::tuple __mul(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MUL"); - - this->gen_sync(PRE_SYNC, 52); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, - false)); - Value* Xtmp0_val = this->gen_ext( - res_val, - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 52); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("MUL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,49); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto res =this->gen_ext( + (this->builder.CreateMul( + this->gen_ext(this->gen_ext( + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + 64, true), 128,true), + this->gen_ext(this->gen_ext( + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), 32,true), + 64, true), 128,true)) + ), + 64, true); + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + res, + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 49); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 53: MULH */ + /* instruction 50: MULH */ std::tuple __mulh(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULH"); - - this->gen_sync(PRE_SYNC, 53); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, - true)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(32U, 32)), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 53); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("MULH_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,50); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto res =this->gen_ext( + (this->builder.CreateMul( + this->gen_ext(this->gen_ext( + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + 64, true), 128,true), + this->gen_ext(this->gen_ext( + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), 32,true), + 64, true), 128,true)) + ), + 64, true); + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAShr( + res, + this->gen_ext(this->gen_const(32,static_cast(traits::XLEN)), 64,false)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 50); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 54: MULHSU */ + /* instruction 51: MULHSU */ std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULHSU"); - - this->gen_sync(PRE_SYNC, 54); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, - false)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(32U, 32)), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 54); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("MULHSU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,51); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto res =this->gen_ext( + (this->builder.CreateMul( + this->gen_ext(this->gen_ext( + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), 32,true), + 64, true), 128,true), + this->gen_ext(this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 64, false), 128,false)) + ), + 64, true); + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAShr( + res, + this->gen_ext(this->gen_const(32,static_cast(traits::XLEN)), 64,false)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 51); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 55: MULHU */ + /* instruction 52: MULHU */ std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("MULHU"); - - this->gen_sync(PRE_SYNC, 55); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - Value* res_val = this->builder.CreateMul( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 64, - false), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 0), - 64, - false)); - Value* Xtmp0_val = this->gen_ext( - this->builder.CreateLShr( - res_val, - this->gen_const(32U, 32)), - 32, - false); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 55); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("MULHU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,52); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto res =this->gen_ext( + (this->builder.CreateMul( + this->gen_ext(this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), + 64, false), 128,false), + this->gen_ext(this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 64, false), 128,false)) + ), + 64, false); + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateLShr( + res, + this->gen_ext(this->gen_const(32,static_cast(traits::XLEN)), 64,false)) + ), + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 52); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 56: DIV */ + /* instruction 53: DIV */ std::tuple __div(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIV"); - - this->gen_sync(PRE_SYNC, 56); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint8_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateAnd( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_const(32U, MMIN_val)), - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs2 + traits::X0, 1), - this->gen_const(32U, M1_val))), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->gen_const(32U, MMIN_val); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateSDiv( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 2), - 32, true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp2_val = this->builder.CreateNeg(this->gen_const(32U, 1)); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 56); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("DIV_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,53); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto dividend =this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), + 32, false); + auto divisor =this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false); + if(rd!= 0){ auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + divisor, + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + auto MMIN =this->gen_const(32,((uint32_t)1)<<(static_cast(traits::XLEN)-1)); + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateAnd( + this->builder.CreateICmp(ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1+ traits::X0, 0), + MMIN) + , + this->builder.CreateICmp(ICmpInst::ICMP_EQ, + divisor, + this->gen_ext(this->gen_const(8,- 1), 32,true)) + ) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + this->builder.CreateStore( + MMIN, + get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateSDiv( + this->gen_ext(dividend, 64,true), + this->gen_ext(divisor, 64,true)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)- 1), + get_reg_ptr(rd + traits::X0), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 53); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 57: DIVU */ + /* instruction 54: DIVU */ std::tuple __divu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DIVU"); - - this->gen_sync(PRE_SYNC, 57); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->builder.CreateUDiv( - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_reg_load(rs2 + traits::X0, 1)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateNeg(this->gen_const(32U, 1)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 57); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("DIVU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,54); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + this->gen_reg_load(rs2+ traits::X0, 0), + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateUDiv( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + ), + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)- 1), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 54); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 58: REM */ + /* instruction 55: REM */ std::tuple __rem(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REM"); - - this->gen_sync(PRE_SYNC, 58); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - uint32_t M1_val = - 1; - uint32_t XLM1_val = 32 - 1; - uint32_t ONE_val = 1; - uint32_t MMIN_val = ONE_val << XLM1_val; - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateAnd( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_const(32U, MMIN_val)), - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs2 + traits::X0, 1), - this->gen_const(32U, M1_val))), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->gen_const(32U, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->builder.CreateSRem( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 2), - 32, true), - this->gen_ext( - this->gen_reg_load(rs2 + traits::X0, 2), - 32, true)); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp2_val = this->gen_reg_load(rs1 + traits::X0, 1); - this->builder.CreateStore(Xtmp2_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 58); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + bb->setName(fmt::format("REM_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,55); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + this->gen_reg_load(rs2+ traits::X0, 0), + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + auto MMIN =this->gen_const(32,(uint32_t)1<<(static_cast(traits::XLEN)-1)); + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateAnd( + this->builder.CreateICmp(ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1+ traits::X0, 0), + MMIN) + , + this->builder.CreateICmp(ICmpInst::ICMP_EQ, + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false), + this->gen_ext(this->gen_const(8,- 1), 32,true)) + ) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext(this->gen_const(8, 0), 32), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateSRem( + this->gen_ext( + this->gen_reg_load(rs1+ traits::X0, 0), + 32, false), + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false)) + ), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_reg_load(rs1+ traits::X0, 0), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 55); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 59: REMU */ + /* instruction 56: REMU */ std::tuple __remu(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("REMU"); - - this->gen_sync(PRE_SYNC, 59); - - uint8_t rd = ((bit_sub<7,5>(instr))); - uint8_t rs1 = ((bit_sub<15,5>(instr))); - uint8_t rs2 = ((bit_sub<20,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), - fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+4; - - if(rd != 0){ - { - BasicBlock* bbnext = BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); - BasicBlock* bb_then = BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); - BasicBlock* bb_else = BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); - // this->builder.SetInsertPoint(bb); - this->gen_cond_branch(this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs2 + traits::X0, 0), - this->gen_const(32U, 0)), - bb_then, - bb_else); - this->builder.SetInsertPoint(bb_then); - { - Value* Xtmp0_val = this->builder.CreateURem( - this->gen_reg_load(rs1 + traits::X0, 1), - this->gen_reg_load(rs2 + traits::X0, 1)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - this->builder.SetInsertPoint(bb_else); - { - Value* Xtmp1_val = this->gen_reg_load(rs1 + traits::X0, 1); - this->builder.CreateStore(Xtmp1_val, get_reg_ptr(rd + traits::X0), false); - } - this->builder.CreateBr(bbnext); - bb=bbnext; - } - this->builder.SetInsertPoint(bb); - } - this->gen_set_pc(pc, traits::NEXT_PC); + bb->setName(fmt::format("REMU_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,56); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"), + fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 4; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + auto bb_else = BasicBlock::Create(this->mod->getContext(), "bb_else", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + this->gen_reg_load(rs2+ traits::X0, 0), + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_else); + this->builder.SetInsertPoint(bb_then); + { + if(rd!=0) { + this->builder.CreateStore( + this->builder.CreateURem( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_reg_load(rs2+ traits::X0, 0)) + , + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_else); + { + if(rd!=0) { + this->builder.CreateStore( + this->gen_reg_load(rs1+ traits::X0, 0), + get_reg_ptr(rd + traits::X0), false); + } + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 56); + this->builder.CreateBr(bb); + return returnValue; + } + + /* instruction 57: CADDI4SPN */ + std::tuple __caddi4spn(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CADDI4SPN_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,57); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<2,3>(instr))); + uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), + fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(imm) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(2+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,imm), 64,false)) + ), + 32, false), + get_reg_ptr(rd+ 8 + traits::X0), false); + } + else{ + this->gen_raise_trap(0, 2); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 57); + this->builder.CreateBr(bb); + return returnValue; + } + + /* instruction 58: CLW */ + std::tuple __clw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CLW_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,58); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), + fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + auto offs =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ 8+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(8,uimm), 64,false)) + ), + 32, false); + this->builder.CreateStore( + this->gen_ext( + this->gen_ext( + this->gen_read_mem(traits::MEM, offs, 4), + 32, false), + 32, true), + get_reg_ptr(rd+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 58); + this->builder.CreateBr(bb); + return returnValue; + } + + /* instruction 59: CSW */ + std::tuple __csw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSW_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,59); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), + fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + auto offs =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ 8+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(8,uimm), 64,false)) + ), + 32, false); + this->gen_write_mem(traits::MEM, + offs, + this->gen_ext( + this->gen_reg_load(rs2+ 8+ traits::X0, 0), + 32, false)); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 59); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 60: C.ADDI4SPN */ - std::tuple __c_addi4spn(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI4SPN"); - - this->gen_sync(PRE_SYNC, 60); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(imm == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 60: CADDI */ + std::tuple __caddi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CADDI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,60); + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), + fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rs1!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rs1+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(8,(int8_t)sext<6>(imm)), 64,true)) + ), + 32, true), + get_reg_ptr(rs1 + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 60); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 61: C.LW */ - std::tuple __c_lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LW"); - - this->gen_sync(PRE_SYNC, 61); - - uint8_t rd = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), - fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + 8 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 61: CNOP */ + std::tuple __cnop(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CNOP_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,61); + uint64_t PC = pc.val; + uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 61); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 62: C.SW */ - std::tuple __c_sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SW"); - - this->gen_sync(PRE_SYNC, 62); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), - fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + 8 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 62: CJAL */ + std::tuple __cjal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CJAL_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,62); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), + fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->gen_const(32,(uint32_t)(PC+ 2)), + get_reg_ptr(1 + traits::X0), false); + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<12>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 62); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 63: C.ADDI */ - std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI"); - - this->gen_sync(PRE_SYNC, 63); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), - fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(rs1 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 63: CLI */ + std::tuple __cli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CLI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,63); + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)((int8_t)sext<6>(imm))), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 63); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 64: C.NOP */ - std::tuple __c_nop(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.NOP"); - - this->gen_sync(PRE_SYNC, 64); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("c.nop"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - /* TODO: describe operations for C.NOP ! */ - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 64: CLUI */ + std::tuple __clui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CLUI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,64); + uint64_t PC = pc.val; + uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), + fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(imm== 0||rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + if(rd!= 0) { + this->builder.CreateStore( + this->gen_const(32,(uint32_t)((int32_t)sext<18>(imm))), + get_reg_ptr(rd + traits::X0), false); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 64); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 65: C.JAL */ - std::tuple __c_jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JAL"); - - this->gen_sync(PRE_SYNC, 65); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(1 + traits::X0), false); - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 65: CADDI16SP */ + std::tuple __caddi16sp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CADDI16SP_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,65); + uint64_t PC = pc.val; + uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), + fmt::arg("nzimm", nzimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(nzimm) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(2+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(16,(int16_t)sext<10>(nzimm)), 64,true)) + ), + 32, true), + get_reg_ptr(2 + traits::X0), false); + } + else{ + this->gen_raise_trap(0, 2); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 65); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 66: C.LI */ - std::tuple __c_li(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LI"); - - this->gen_sync(PRE_SYNC, 66); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rd == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 66: __reserved_clui */ + std::tuple ____reserved_clui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("__reserved_clui_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,66); + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 2); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 66); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 67: C.LUI */ - std::tuple __c_lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LUI"); - - this->gen_sync(PRE_SYNC, 67); - - int32_t imm = signextend((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), - fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rd == 0){ - this->gen_raise_trap(0, 2); - } - if(imm == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->gen_const(32U, imm); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 67: CSRLI */ + std::tuple __csrli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSRLI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,67); + uint64_t PC = pc.val; + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->builder.CreateLShr( + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + this->gen_ext(this->gen_const(8,shamt), 32,false)) + , + get_reg_ptr(rs1+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 67); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 68: C.ADDI16SP */ - std::tuple __c_addi16sp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADDI16SP"); - - this->gen_sync(PRE_SYNC, 68); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_ext( - this->gen_reg_load(2 + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(2 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 68: CSRAI */ + std::tuple __csrai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSRAI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,68); + uint64_t PC = pc.val; + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(shamt){ this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAShr( + (this->gen_ext( + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + 32, false)), + this->gen_ext(this->gen_const(8,shamt), 32,false)) + ), + 32, true), + get_reg_ptr(rs1+ 8 + traits::X0), false); + } + else{ + if(static_cast(traits::XLEN)== 128){ this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAShr( + (this->gen_ext( + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + 32, false)), + this->gen_ext(this->gen_const(8, 64), 32,false)) + ), + 32, true), + get_reg_ptr(rs1+ 8 + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 68); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 69: C.SRLI */ - std::tuple __c_srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRLI"); - - this->gen_sync(PRE_SYNC, 69); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateLShr( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 69: CANDI */ + std::tuple __candi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CANDI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,69); + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAnd( + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + this->gen_ext(this->gen_const(8,(int8_t)sext<6>(imm)), 32,true)) + ), + 32, true), + get_reg_ptr(rs1+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 69); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 70: C.SRAI */ - std::tuple __c_srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SRAI"); - - this->gen_sync(PRE_SYNC, 70); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateAShr( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 70: CSUB */ + std::tuple __csub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSUB_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,70); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateSub( + this->gen_ext(this->gen_reg_load(rd+ 8+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_reg_load(rs2+ 8+ traits::X0, 0), 64,false)) + ), + 32, true), + get_reg_ptr(rd+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 70); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 71: C.ANDI */ - std::tuple __c_andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ANDI"); - - this->gen_sync(PRE_SYNC, 71); - - int8_t imm = signextend((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rs1_idx_val = rs1 + 8; - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_ext( - this->gen_reg_load(rs1_idx_val + traits::X0, 0), - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 71: CXOR */ + std::tuple __cxor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CXOR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,71); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->builder.CreateXor( + this->gen_reg_load(rd+ 8+ traits::X0, 0), + this->gen_reg_load(rs2+ 8+ traits::X0, 0)) + , + get_reg_ptr(rd+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 71); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 72: C.SUB */ - std::tuple __c_sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SUB"); - - this->gen_sync(PRE_SYNC, 72); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateSub( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 72: COR */ + std::tuple __cor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("COR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,72); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->builder.CreateOr( + this->gen_reg_load(rd+ 8+ traits::X0, 0), + this->gen_reg_load(rs2+ 8+ traits::X0, 0)) + , + get_reg_ptr(rd+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 72); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 73: C.XOR */ - std::tuple __c_xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.XOR"); - - this->gen_sync(PRE_SYNC, 73); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateXor( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 73: CAND */ + std::tuple __cand(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CAND_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,73); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), + fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->builder.CreateStore( + this->builder.CreateAnd( + this->gen_reg_load(rd+ 8+ traits::X0, 0), + this->gen_reg_load(rs2+ 8+ traits::X0, 0)) + , + get_reg_ptr(rd+ 8 + traits::X0), false); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 73); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 74: C.OR */ - std::tuple __c_or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.OR"); - - this->gen_sync(PRE_SYNC, 74); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateOr( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 74: CJ */ + std::tuple __cj(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CJ_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,74); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), + fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<12>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 74); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 75: C.AND */ - std::tuple __c_and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.AND"); - - this->gen_sync(PRE_SYNC, 75); - - uint8_t rs2 = ((bit_sub<2,3>(instr))); - uint8_t rd = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), - fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - uint8_t rd_idx_val = rd + 8; - Value* Xtmp0_val = this->builder.CreateAnd( - this->gen_reg_load(rd_idx_val + traits::X0, 0), - this->gen_reg_load(rs2 + 8 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd_idx_val + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 75: CBEQZ */ + std::tuple __cbeqz(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CBEQZ_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,75); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<9>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 75); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 76: C.J */ - std::tuple __c_j(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.J"); - - this->gen_sync(PRE_SYNC, 76); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), - fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 76: CBNEZ */ + std::tuple __cbnez(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CBNEZ_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,76); + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), + fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + auto bb_merge = BasicBlock::Create(this->mod->getContext(), "bb_merge", this->func, this->leave_blk); + auto bb_then = BasicBlock::Create(this->mod->getContext(), "bb_then", this->func, bb_merge); + this->builder.CreateCondBr(this->gen_ext(this->builder.CreateICmp(ICmpInst::ICMP_NE, + this->gen_reg_load(rs1+ 8+ traits::X0, 0), + this->gen_ext(this->gen_const(8, 0), 32,false)) + , 1), bb_then, bb_merge); + this->builder.SetInsertPoint(bb_then); + { + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<9>(imm)); + this->builder.CreateStore(this->gen_const(32,PC_val_v), get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + this->builder.CreateBr(bb_merge); + this->builder.SetInsertPoint(bb_merge); + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 76); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 77: C.BEQZ */ - std::tuple __c_beqz(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.BEQZ"); - - this->gen_sync(PRE_SYNC, 77); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 77: CSLLI */ + std::tuple __cslli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSLLI_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,77); + uint64_t PC = pc.val; + uint8_t nzuimm = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rs1!= 0) { + this->builder.CreateStore( + this->builder.CreateShl( + this->gen_reg_load(rs1+ traits::X0, 0), + this->gen_ext(this->gen_const(8,nzuimm), 32,false)) + , + get_reg_ptr(rs1 + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 77); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 78: C.BNEZ */ - std::tuple __c_bnez(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.BNEZ"); - - this->gen_sync(PRE_SYNC, 78); - - int16_t imm = signextend((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); - uint8_t rs1 = ((bit_sub<7,3>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), - fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_choose( - this->builder.CreateICmp( - ICmpInst::ICMP_NE, - this->gen_reg_load(rs1 + 8 + traits::X0, 0), - this->gen_const(32U, 0)), - this->builder.CreateAdd( - this->gen_ext( - cur_pc_val, - 32, true), - this->gen_const(32U, imm)), - this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)), - 32); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - Value* is_cont_v = this->builder.CreateICmp(ICmpInst::ICMP_NE, PC_val, this->gen_const(32U, pc.val), "is_cont_v"); - this->builder.CreateStore(this->gen_ext(is_cont_v, 32U, false), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 78: CLWSP */ + std::tuple __clwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CLWSP_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,78); + uint64_t PC = pc.val; + uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), + fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)||rd== 0) { + this->gen_raise_trap(0, 2); + } + else{ + auto offs =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(2+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(8,uimm), 64,false)) + ), + 32, false); + this->builder.CreateStore( + this->gen_ext( + this->gen_ext( + this->gen_read_mem(traits::MEM, offs, 4), + 32, false), + 32, true), + get_reg_ptr(rd + traits::X0), false); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 78); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 79: C.SLLI */ - std::tuple __c_slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SLLI"); - - this->gen_sync(PRE_SYNC, 79); - - uint8_t shamt = ((bit_sub<2,5>(instr))); - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.slli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - if(rs1 == 0){ - this->gen_raise_trap(0, 2); - } - Value* Xtmp0_val = this->builder.CreateShl( - this->gen_reg_load(rs1 + traits::X0, 0), - this->gen_const(32U, shamt)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rs1 + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 79: CMV */ + std::tuple __cmv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CMV_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,79); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_reg_load(rs2+ traits::X0, 0), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 79); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 80: C.LWSP */ - std::tuple __c_lwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.LWSP"); - - this->gen_sync(PRE_SYNC, 80); - - uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), - fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* Xtmp0_val = this->gen_ext( - this->gen_read_mem(traits::MEM, offs_val, 32/8), - 32, - true); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 80: CJR */ + std::tuple __cjr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CJR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,80); + uint64_t PC = pc.val; + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), + fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs1&&rs1(traits::RFS)){ auto addr_mask =this->gen_const(32,(uint32_t)- 2); + auto PC_val_v = this->builder.CreateAnd( + this->gen_reg_load(rs1%static_cast(traits::RFS)+ traits::X0, 0), + addr_mask) + ; + this->builder.CreateStore(PC_val_v, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + else{ + this->gen_raise_trap(0, 2); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 80); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 81: C.MV */ - std::tuple __c_mv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.MV"); - - this->gen_sync(PRE_SYNC, 81); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 81: __reserved_cmv */ + std::tuple ____reserved_cmv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("__reserved_cmv_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,81); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 2); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 81); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 82: C.JR */ - std::tuple __c_jr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JR"); - - this->gen_sync(PRE_SYNC, 82); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), - fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 82: CADD */ + std::tuple __cadd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CADD_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,82); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), + fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rd>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + if(rd!= 0) { + this->builder.CreateStore( + this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(rd+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_reg_load(rs2+ traits::X0, 0), 64,false)) + ), + 32, false), + get_reg_ptr(rd + traits::X0), false); + } + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 82); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 83: C.ADD */ - std::tuple __c_add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.ADD"); - - this->gen_sync(PRE_SYNC, 83); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t rd = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), - fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - this->gen_reg_load(rd + traits::X0, 0), - this->gen_reg_load(rs2 + traits::X0, 0)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(rd + traits::X0), false); - this->gen_set_pc(pc, traits::NEXT_PC); + /* instruction 83: CJALR */ + std::tuple __cjalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CJALR_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,83); + uint64_t PC = pc.val; + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), + fmt::arg("rs1", name(rs1))); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs1>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto addr_mask =this->gen_const(32,(uint32_t)- 2); + auto new_pc =this->gen_reg_load(rs1+ traits::X0, 0); + this->builder.CreateStore( + this->gen_const(32,(uint32_t)(PC+ 2)), + get_reg_ptr(1 + traits::X0), false); + auto PC_val_v = this->builder.CreateAnd( + new_pc, + addr_mask) + ; + this->builder.CreateStore(PC_val_v, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32,2U), get_reg_ptr(traits::LAST_BRANCH), false); + } + bb = this->leave_blk; + auto returnValue = std::make_tuple(BRANCH,nullptr); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 83); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 84: C.JALR */ - std::tuple __c_jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.JALR"); - - this->gen_sync(PRE_SYNC, 84); - - uint8_t rs1 = ((bit_sub<7,5>(instr))); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), - fmt::arg("rs1", name(rs1))); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* Xtmp0_val = this->builder.CreateAdd( - cur_pc_val, - this->gen_const(32U, 2)); - this->builder.CreateStore(Xtmp0_val, get_reg_ptr(1 + traits::X0), false); - Value* PC_val = this->gen_reg_load(rs1 + traits::X0, 0); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + /* instruction 84: CEBREAK */ + std::tuple __cebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CEBREAK_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,84); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 3); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 84); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 85: C.EBREAK */ - std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.EBREAK"); - - this->gen_sync(PRE_SYNC, 85); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("c.ebreak"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - this->gen_raise_trap(0, 3); + /* instruction 85: CSWSP */ + std::tuple __cswsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("CSWSP_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,85); + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), + fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(mnemonic), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + if(rs2>=static_cast(traits::RFS)) { + this->gen_raise_trap(0, 2); + } + else{ + auto offs =this->gen_ext( + (this->builder.CreateAdd( + this->gen_ext(this->gen_reg_load(2+ traits::X0, 0), 64,false), + this->gen_ext(this->gen_const(8,uimm), 64,false)) + ), + 32, false); + this->gen_write_mem(traits::MEM, + offs, + this->gen_ext( + this->gen_reg_load(rs2+ traits::X0, 0), + 32, false)); + } + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 85); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + this->builder.CreateBr(bb); + return returnValue; } - /* instruction 86: C.SWSP */ - std::tuple __c_swsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("C.SWSP"); - - this->gen_sync(PRE_SYNC, 86); - - uint8_t rs2 = ((bit_sub<2,5>(instr))); - uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); - if(this->disass_enabled){ - /* generate console output when executing the command */ - auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), - fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr(mnemonic), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(2 + traits::X0, 0), - this->gen_const(32U, uimm)); - Value* MEMtmp0_val = this->gen_reg_load(rs2 + traits::X0, 0); - this->gen_write_mem( - traits::MEM, - offs_val, - this->builder.CreateZExtOrTrunc(MEMtmp0_val,this->get_type(32))); - this->gen_set_pc(pc, traits::NEXT_PC); - this->gen_sync(POST_SYNC, 86); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ - this->gen_trap_check(bb); - return std::make_tuple(CONT, bb); - } - - /* instruction 87: DII */ + /* instruction 86: DII */ std::tuple __dii(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName("DII"); - - this->gen_sync(PRE_SYNC, 87); - - if(this->disass_enabled){ - /* generate console output when executing the command */ - std::vector args { - this->core_ptr, - this->gen_const(64, pc.val), - this->builder.CreateGlobalStringPtr("dii"), - }; - this->builder.CreateCall(this->mod->getFunction("print_disass"), args); - } - - Value* cur_pc_val = this->gen_const(32, pc.val); - pc=pc+2; - - this->gen_raise_trap(0, 2); - this->gen_sync(POST_SYNC, 87); - this->gen_trap_check(this->leave_blk); - return std::make_tuple(BRANCH, nullptr); + bb->setName(fmt::format("DII_0x{:X}",pc.val)); + this->gen_sync(PRE_SYNC,86); + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate console output when executing the command */ + //This disass is not yet implemented + } + auto cur_pc_val = this->gen_const(32,pc.val); + pc=pc+ 2; + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_raise_trap(0, 2); + bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); + auto returnValue = std::make_tuple(CONT,bb); + + this->gen_trap_check(bb); + this->gen_sync(POST_SYNC, 86); + this->builder.CreateBr(bb); + return returnValue; } /**************************************************************************** @@ -4042,23 +4365,75 @@ private: ****************************************************************************/ std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) { this->gen_sync(iss::PRE_SYNC, instr_descr.size()); - this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), - get_reg_ptr(traits::PC), true); + this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), 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->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true), this->gen_const(64U, 1)), - get_reg_ptr(traits::ICOUNT), true); + get_reg_ptr(traits::ICOUNT), true); pc = pc + ((instr & 3) == 3 ? 4 : 2); this->gen_raise_trap(0, 2); // illegal instruction trap this->gen_sync(iss::POST_SYNC, instr_descr.size()); this->gen_trap_check(this->leave_blk); return std::make_tuple(BRANCH, nullptr); + } + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; } }; -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; } template vm_impl::vm_impl() { this(new ARCH()); } @@ -4066,14 +4441,11 @@ template vm_impl::vm_impl() { this(new ARCH()); } template vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) : vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr:instr_descr){ + root->instrs.push_back(instr); } + populate_decoding_tree(root); } template @@ -4081,51 +4453,50 @@ std::tuple vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; - code_word_t insn = 0; - // const typename traits::addr_t upper_bits = ~traits::PGMASK; + code_word_t instr = 0; + // const typename traits::addr_t upper_bits = ~traits::PGMASK; phys_addr_t paddr(pc); - auto *const data = (uint8_t *)&insn; + auto *const data = (uint8_t *)&instr; if(this->core.has_mmu()) paddr = this->core.virt2phys(pc); //TODO: re-add page handling // if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary // auto res = this->core.read(paddr, 2, data); // if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); -// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction +// if ((instr & 0x3) == 0x3) { // this is a 32bit instruction // res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); // } // } else { auto res = this->core.read(paddr, 4, data); if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val); // } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' // curr pc on stack ++inst_cnt; - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; + auto f = decode_instr(root, instr); if (f == nullptr) { f = &this_class::illegal_intruction; } - return (this->*f)(pc, insn, this_block); + return (this->*f)(pc, instr, this_block); } template void vm_impl::gen_leave_behavior(BasicBlock *leave_blk) { this->builder.SetInsertPoint(leave_blk); - this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); + this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC),get_reg_ptr(traits::NEXT_PC), false)); } template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); - this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_leave_trap(unsigned lvl) { std::vector args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) }; this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); - auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); - this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); - this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); + auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), get_reg_ptr(traits::LAST_BRANCH), false); } template void vm_impl::gen_wait(unsigned type) { @@ -4135,22 +4506,25 @@ template void vm_impl::gen_wait(unsigned type) { template void vm_impl::gen_trap_behavior(BasicBlock *trap_blk) { this->builder.SetInsertPoint(trap_blk); - auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); + this->gen_sync(POST_SYNC, -1); //TODO get right InstrId + auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); this->builder.CreateStore(this->gen_const(32U, std::numeric_limits::max()), - get_reg_ptr(traits::LAST_BRANCH), false); + get_reg_ptr(traits::LAST_BRANCH), false); std::vector args{this->core_ptr, this->adj_to64(trap_state_val), - this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; + this->adj_to64(this->builder.CreateLoad(this->get_typeptr(traits::PC), get_reg_ptr(traits::PC), false))}; this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); - auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); + auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false); this->builder.CreateRet(trap_addr_val); } template inline void vm_impl::gen_trap_check(BasicBlock *bb) { - auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); + auto* target_bb = BasicBlock::Create(this->mod->getContext(), "", this->func, bb); + auto *v = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true); this->gen_cond_branch(this->builder.CreateICmp( ICmpInst::ICMP_EQ, v, ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))), - bb, this->trap_blk, 1); + target_bb, this->trap_blk, 1); + this->builder.SetInsertPoint(target_bb); } } // namespace tgc5c @@ -4163,3 +4537,25 @@ std::unique_ptr create(arch::tgc5c *core, unsigned short por } } // namespace llvm } // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("tgc5c|m_p|llvm", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto* vm = new llvm::tgc5c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("tgc5c|mu_p|llvm", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto* vm = new llvm::tgc5c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} From 51f6fbe0dd59cbacf802d5aa138ba7291e6bb996 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Wed, 20 Sep 2023 15:12:03 +0200 Subject: [PATCH 142/184] applies newest CoreDSL changes --- gen_input/templates/tcc/CORENAME.cpp.gtl | 1 + src/iss/arch/tgc5c.h | 56 +-- src/vm/interp/vm_tgc5c.cpp | 227 ++++----- src/vm/llvm/vm_tgc5c.cpp | 320 ++++++------- src/vm/tcc/vm_tgc5c.cpp | 583 +++++++++++++---------- 5 files changed, 640 insertions(+), 547 deletions(-) diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index 6b2ba2b..9900d60 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -159,6 +159,7 @@ private: compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("${instr.name}_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,${idx}); + uint64_t PC = pc.val; <%instr.fields.eachLine{%>${it} <%}%>if(this->disass_enabled){ /* generate console output when executing the command */<%instr.disass.eachLine{%> diff --git a/src/iss/arch/tgc5c.h b/src/iss/arch/tgc5c.h index 319f31f..0741e4a 100644 --- a/src/iss/arch/tgc5c.h +++ b/src/iss/arch/tgc5c.h @@ -51,7 +51,7 @@ template <> struct traits { {"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", "NEXT_PC", "PRIV", "DPC"}}; static constexpr std::array reg_aliases{ - {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; + {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "PC", "NEXT_PC", "PRIV", "DPC"}}; enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL}; @@ -141,35 +141,35 @@ template <> struct traits { DIVU = 54, REM = 55, REMU = 56, - CADDI4SPN = 57, - CLW = 58, - CSW = 59, - CADDI = 60, - CNOP = 61, - CJAL = 62, - CLI = 63, - CLUI = 64, - CADDI16SP = 65, + C__ADDI4SPN = 57, + C__LW = 58, + C__SW = 59, + C__ADDI = 60, + C__NOP = 61, + C__JAL = 62, + C__LI = 63, + C__LUI = 64, + C__ADDI16SP = 65, __reserved_clui = 66, - CSRLI = 67, - CSRAI = 68, - CANDI = 69, - CSUB = 70, - CXOR = 71, - COR = 72, - CAND = 73, - CJ = 74, - CBEQZ = 75, - CBNEZ = 76, - CSLLI = 77, - CLWSP = 78, - CMV = 79, - CJR = 80, + C__SRLI = 67, + C__SRAI = 68, + C__ANDI = 69, + C__SUB = 70, + C__XOR = 71, + C__OR = 72, + C__AND = 73, + C__J = 74, + C__BEQZ = 75, + C__BNEZ = 76, + C__SLLI = 77, + C__LWSP = 78, + C__MV = 79, + C__JR = 80, __reserved_cmv = 81, - CADD = 82, - CJALR = 83, - CEBREAK = 84, - CSWSP = 85, + C__ADD = 82, + C__JALR = 83, + C__EBREAK = 84, + C__SWSP = 85, DII = 86, MAX_OPCODE }; diff --git a/src/vm/interp/vm_tgc5c.cpp b/src/vm/interp/vm_tgc5c.cpp index 4ba2443..f05220b 100644 --- a/src/vm/interp/vm_tgc5c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -210,35 +210,35 @@ private: {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::DIVU}, {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REM}, {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, arch::traits::opcode_e::REMU}, - {16, 0b0000000000000000, 0b1110000000000011, arch::traits::opcode_e::CADDI4SPN}, - {16, 0b0100000000000000, 0b1110000000000011, arch::traits::opcode_e::CLW}, - {16, 0b1100000000000000, 0b1110000000000011, arch::traits::opcode_e::CSW}, - {16, 0b0000000000000001, 0b1110000000000011, arch::traits::opcode_e::CADDI}, - {16, 0b0000000000000001, 0b1110111110000011, arch::traits::opcode_e::CNOP}, - {16, 0b0010000000000001, 0b1110000000000011, arch::traits::opcode_e::CJAL}, - {16, 0b0100000000000001, 0b1110000000000011, arch::traits::opcode_e::CLI}, - {16, 0b0110000000000001, 0b1110000000000011, arch::traits::opcode_e::CLUI}, - {16, 0b0110000100000001, 0b1110111110000011, arch::traits::opcode_e::CADDI16SP}, + {16, 0b0000000000000000, 0b1110000000000011, arch::traits::opcode_e::C__ADDI4SPN}, + {16, 0b0100000000000000, 0b1110000000000011, arch::traits::opcode_e::C__LW}, + {16, 0b1100000000000000, 0b1110000000000011, arch::traits::opcode_e::C__SW}, + {16, 0b0000000000000001, 0b1110000000000011, arch::traits::opcode_e::C__ADDI}, + {16, 0b0000000000000001, 0b1110111110000011, arch::traits::opcode_e::C__NOP}, + {16, 0b0010000000000001, 0b1110000000000011, arch::traits::opcode_e::C__JAL}, + {16, 0b0100000000000001, 0b1110000000000011, arch::traits::opcode_e::C__LI}, + {16, 0b0110000000000001, 0b1110000000000011, arch::traits::opcode_e::C__LUI}, + {16, 0b0110000100000001, 0b1110111110000011, arch::traits::opcode_e::C__ADDI16SP}, {16, 0b0110000000000001, 0b1111000001111111, arch::traits::opcode_e::__reserved_clui}, - {16, 0b1000000000000001, 0b1111110000000011, arch::traits::opcode_e::CSRLI}, - {16, 0b1000010000000001, 0b1111110000000011, arch::traits::opcode_e::CSRAI}, - {16, 0b1000100000000001, 0b1110110000000011, arch::traits::opcode_e::CANDI}, - {16, 0b1000110000000001, 0b1111110001100011, arch::traits::opcode_e::CSUB}, - {16, 0b1000110000100001, 0b1111110001100011, arch::traits::opcode_e::CXOR}, - {16, 0b1000110001000001, 0b1111110001100011, arch::traits::opcode_e::COR}, - {16, 0b1000110001100001, 0b1111110001100011, arch::traits::opcode_e::CAND}, - {16, 0b1010000000000001, 0b1110000000000011, arch::traits::opcode_e::CJ}, - {16, 0b1100000000000001, 0b1110000000000011, arch::traits::opcode_e::CBEQZ}, - {16, 0b1110000000000001, 0b1110000000000011, arch::traits::opcode_e::CBNEZ}, - {16, 0b0000000000000010, 0b1111000000000011, arch::traits::opcode_e::CSLLI}, - {16, 0b0100000000000010, 0b1110000000000011, arch::traits::opcode_e::CLWSP}, - {16, 0b1000000000000010, 0b1111000000000011, arch::traits::opcode_e::CMV}, - {16, 0b1000000000000010, 0b1111000001111111, arch::traits::opcode_e::CJR}, + {16, 0b1000000000000001, 0b1111110000000011, arch::traits::opcode_e::C__SRLI}, + {16, 0b1000010000000001, 0b1111110000000011, arch::traits::opcode_e::C__SRAI}, + {16, 0b1000100000000001, 0b1110110000000011, arch::traits::opcode_e::C__ANDI}, + {16, 0b1000110000000001, 0b1111110001100011, arch::traits::opcode_e::C__SUB}, + {16, 0b1000110000100001, 0b1111110001100011, arch::traits::opcode_e::C__XOR}, + {16, 0b1000110001000001, 0b1111110001100011, arch::traits::opcode_e::C__OR}, + {16, 0b1000110001100001, 0b1111110001100011, arch::traits::opcode_e::C__AND}, + {16, 0b1010000000000001, 0b1110000000000011, arch::traits::opcode_e::C__J}, + {16, 0b1100000000000001, 0b1110000000000011, arch::traits::opcode_e::C__BEQZ}, + {16, 0b1110000000000001, 0b1110000000000011, arch::traits::opcode_e::C__BNEZ}, + {16, 0b0000000000000010, 0b1111000000000011, arch::traits::opcode_e::C__SLLI}, + {16, 0b0100000000000010, 0b1110000000000011, arch::traits::opcode_e::C__LWSP}, + {16, 0b1000000000000010, 0b1111000000000011, arch::traits::opcode_e::C__MV}, + {16, 0b1000000000000010, 0b1111000001111111, arch::traits::opcode_e::C__JR}, {16, 0b1000000000000010, 0b1111111111111111, arch::traits::opcode_e::__reserved_cmv}, - {16, 0b1001000000000010, 0b1111000000000011, arch::traits::opcode_e::CADD}, - {16, 0b1001000000000010, 0b1111000001111111, arch::traits::opcode_e::CJALR}, - {16, 0b1001000000000010, 0b1111111111111111, arch::traits::opcode_e::CEBREAK}, - {16, 0b1100000000000010, 0b1110000000000011, arch::traits::opcode_e::CSWSP}, + {16, 0b1001000000000010, 0b1111000000000011, arch::traits::opcode_e::C__ADD}, + {16, 0b1001000000000010, 0b1111000001111111, arch::traits::opcode_e::C__JALR}, + {16, 0b1001000000000010, 0b1111111111111111, arch::traits::opcode_e::C__EBREAK}, + {16, 0b1100000000000010, 0b1110000000000011, arch::traits::opcode_e::C__SWSP}, {16, 0b0000000000000000, 0b1111111111111111, arch::traits::opcode_e::DII}, }}; @@ -485,7 +485,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t new_pc = (uint32_t)((*(X+rs1) + (int16_t)sext<12>(imm)) & ~ 0x1); + uint32_t addr_mask = (uint32_t)- 2; + uint32_t new_pc = (uint32_t)((*(X+rs1) + (int16_t)sext<12>(imm)) & addr_mask); if(new_pc % traits::INSTR_ALIGNMENT) { raise(0, 0); } @@ -493,7 +494,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(rd != 0) { *(X+rd) = (uint32_t)(*PC + 4); } - *NEXT_PC = new_pc & ~ 0x1; + *NEXT_PC = new_pc; this->core.reg.last_branch = 1; } } @@ -719,9 +720,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int8_t read_res = super::template read_mem(traits::MEM, load_address); + int8_t res_27 = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int8_t res = (int8_t)read_res; + int8_t res = (int8_t)res_27; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -750,9 +751,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int16_t read_res = super::template read_mem(traits::MEM, load_address); + int16_t res_28 = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int16_t res = (int16_t)read_res; + int16_t res = (int16_t)res_28; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -781,9 +782,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - int32_t read_res = super::template read_mem(traits::MEM, load_address); + int32_t res_29 = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - int32_t res = (int32_t)read_res; + int32_t res = (int32_t)res_29; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -812,9 +813,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint8_t read_res = super::template read_mem(traits::MEM, load_address); + uint8_t res_30 = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint8_t res = read_res; + uint8_t res = res_30; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -843,9 +844,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t load_address = (uint32_t)(*(X+rs1) + (int16_t)sext<12>(imm)); - uint16_t read_res = super::template read_mem(traits::MEM, load_address); + uint16_t res_31 = super::template read_mem(traits::MEM, load_address); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint16_t res = read_res; + uint16_t res = res_31; if(rd != 0) { *(X+rd) = (uint32_t)res; } @@ -1543,9 +1544,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co else { uint32_t xrs1 = *(X+rs1); if(rd != 0) { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_32 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_32; super::template write_mem(traits::CSR, csr, xrs1); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); *(X+rd) = xrd; @@ -1578,9 +1579,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_33 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_33; uint32_t xrs1 = *(X+rs1); if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd | xrs1); @@ -1613,9 +1614,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_34 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_34; uint32_t xrs1 = *(X+rs1); if(rs1 != 0) { super::template write_mem(traits::CSR, csr, xrd & ~ xrs1); @@ -1648,9 +1649,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_35 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_35; super::template write_mem(traits::CSR, csr, (uint32_t)zimm); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); if(rd != 0) { @@ -1680,9 +1681,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_36 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_36; if(zimm != 0) { super::template write_mem(traits::CSR, csr, xrd | (uint32_t)zimm); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); @@ -1714,9 +1715,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t read_res = super::template read_mem(traits::CSR, csr); + uint32_t res_37 = super::template read_mem(traits::CSR, csr); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - uint32_t xrd = read_res; + uint32_t xrd = res_37; if(zimm != 0) { super::template write_mem(traits::CSR, csr, xrd & ~ ((uint32_t)zimm)); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); @@ -1955,7 +1956,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { if(*(X+rs2) != 0) { - uint32_t MMIN = 1 << (traits::XLEN - 1); + uint32_t MMIN = (uint32_t)1 << (traits::XLEN - 1); if(*(X+rs1) == MMIN && (int32_t)*(X+rs2) == - 1) { if(rd != 0) { *(X+rd) = 0; @@ -2010,13 +2011,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI4SPN: { + case arch::traits::opcode_e::C__ADDI4SPN: { uint8_t rd = ((bit_sub<2,3>(instr))); uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"), fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2034,14 +2035,14 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLW: { + case arch::traits::opcode_e::C__LW: { uint8_t rd = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"), fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); this->core.disass_output(pc.val, mnemonic); } @@ -2051,20 +2052,20 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { uint32_t offs = (uint32_t)(*(X+rs1 + 8) + uimm); - int32_t read_res = super::template read_mem(traits::MEM, offs); + int32_t res_38 = super::template read_mem(traits::MEM, offs); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - *(X+rd + 8) = (uint32_t)(int32_t)read_res; + *(X+rd + 8) = (uint32_t)(int32_t)res_38; } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSW: { + case arch::traits::opcode_e::C__SW: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"), fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); this->core.disass_output(pc.val, mnemonic); } @@ -2079,13 +2080,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI: { + case arch::traits::opcode_e::C__ADDI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2105,11 +2106,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CNOP: { + case arch::traits::opcode_e::C__NOP: { uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cnop"); + this->core.disass_output(pc.val, "c__nop"); } // used registers// calculate next pc value *NEXT_PC = *PC + 2; @@ -2118,12 +2119,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJAL: { + case arch::traits::opcode_e::C__JAL: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2138,13 +2139,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLI: { + case arch::traits::opcode_e::C__LI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2164,13 +2165,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLUI: { + case arch::traits::opcode_e::C__LUI: { uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2188,12 +2189,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADDI16SP: { + case arch::traits::opcode_e::C__ADDI16SP: { uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "c.addi16sp"), fmt::arg("nzimm", nzimm)); this->core.disass_output(pc.val, mnemonic); } @@ -2225,13 +2226,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRLI: { + case arch::traits::opcode_e::C__SRLI: { uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"), fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); this->core.disass_output(pc.val, mnemonic); } @@ -2244,13 +2245,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSRAI: { + case arch::traits::opcode_e::C__SRAI: { uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"), fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); this->core.disass_output(pc.val, mnemonic); } @@ -2270,13 +2271,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CANDI: { + case arch::traits::opcode_e::C__ANDI: { uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2289,13 +2290,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSUB: { + case arch::traits::opcode_e::C__SUB: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2308,13 +2309,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CXOR: { + case arch::traits::opcode_e::C__XOR: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2327,13 +2328,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::COR: { + case arch::traits::opcode_e::C__OR: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2346,13 +2347,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CAND: { + case arch::traits::opcode_e::C__AND: { uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2365,12 +2366,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJ: { + case arch::traits::opcode_e::C__J: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2383,13 +2384,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CBEQZ: { + case arch::traits::opcode_e::C__BEQZ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2405,13 +2406,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CBNEZ: { + case arch::traits::opcode_e::C__BNEZ: { uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); this->core.disass_output(pc.val, mnemonic); } @@ -2427,13 +2428,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSLLI: { + case arch::traits::opcode_e::C__SLLI: { uint8_t nzuimm = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "c.slli"), fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); this->core.disass_output(pc.val, mnemonic); } @@ -2453,13 +2454,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CLWSP: { + case arch::traits::opcode_e::C__LWSP: { uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); this->core.disass_output(pc.val, mnemonic); } @@ -2473,20 +2474,20 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } else { uint32_t offs = (uint32_t)(*(X+2) + uimm); - int32_t read_res = super::template read_mem(traits::MEM, offs); + int32_t res_39 = super::template read_mem(traits::MEM, offs); if(this->core.reg.trap_state>=0x80000000UL) throw memory_access_exception(); - *(X+rd) = (uint32_t)(int32_t)read_res; + *(X+rd) = (uint32_t)(int32_t)res_39; } } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CMV: { + case arch::traits::opcode_e::C__MV: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"), fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2506,12 +2507,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJR: { + case arch::traits::opcode_e::C__JR: { uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); } @@ -2521,7 +2522,8 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if(rs1 && rs1 < traits::RFS) { - *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; + uint32_t addr_mask = (uint32_t)- 2; + *NEXT_PC = *(X+rs1 % traits::RFS) & addr_mask; this->core.reg.last_branch = 1; } else { @@ -2543,13 +2545,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CADD: { + case arch::traits::opcode_e::C__ADD: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"), fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); this->core.disass_output(pc.val, mnemonic); } @@ -2569,12 +2571,12 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CJALR: { + case arch::traits::opcode_e::C__JALR: { uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"), fmt::arg("rs1", name(rs1))); this->core.disass_output(pc.val, mnemonic); } @@ -2587,18 +2589,19 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { + uint32_t addr_mask = (uint32_t)- 2; uint32_t new_pc = *(X+rs1); *(X+1) = (uint32_t)(*PC + 2); - *NEXT_PC = new_pc & ~ 0x1; + *NEXT_PC = new_pc & addr_mask; this->core.reg.last_branch = 1; } } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CEBREAK: { + case arch::traits::opcode_e::C__EBREAK: { if(this->disass_enabled){ /* generate console output when executing the command */ - this->core.disass_output(pc.val, "cebreak"); + this->core.disass_output(pc.val, "c__ebreak"); } // used registers// calculate next pc value *NEXT_PC = *PC + 2; @@ -2608,13 +2611,13 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co } break; }// @suppress("No break at end of case") - case arch::traits::opcode_e::CSWSP: { + case arch::traits::opcode_e::C__SWSP: { uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"), fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); this->core.disass_output(pc.val, mnemonic); } diff --git a/src/vm/llvm/vm_tgc5c.cpp b/src/vm/llvm/vm_tgc5c.cpp index 5c7fd34..c211906 100644 --- a/src/vm/llvm/vm_tgc5c.cpp +++ b/src/vm/llvm/vm_tgc5c.cpp @@ -269,64 +269,64 @@ private: {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, /* instruction REMU, encoding '0b00000010000000000111000000110011' */ {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction CADDI4SPN, encoding '0b0000000000000000' */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__caddi4spn}, - /* instruction CLW, encoding '0b0100000000000000' */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__clw}, - /* instruction CSW, encoding '0b1100000000000000' */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__csw}, - /* instruction CADDI, encoding '0b0000000000000001' */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__caddi}, - /* instruction CNOP, encoding '0b0000000000000001' */ - {16, 0b0000000000000001, 0b1110111110000011, &this_class::__cnop}, - /* instruction CJAL, encoding '0b0010000000000001' */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__cjal}, - /* instruction CLI, encoding '0b0100000000000001' */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__cli}, - /* instruction CLUI, encoding '0b0110000000000001' */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__clui}, - /* instruction CADDI16SP, encoding '0b0110000100000001' */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__caddi16sp}, + /* instruction C__ADDI4SPN, encoding '0b0000000000000000' */ + {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c__addi4spn}, + /* instruction C__LW, encoding '0b0100000000000000' */ + {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c__lw}, + /* instruction C__SW, encoding '0b1100000000000000' */ + {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c__sw}, + /* instruction C__ADDI, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c__addi}, + /* instruction C__NOP, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110111110000011, &this_class::__c__nop}, + /* instruction C__JAL, encoding '0b0010000000000001' */ + {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c__jal}, + /* instruction C__LI, encoding '0b0100000000000001' */ + {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c__li}, + /* instruction C__LUI, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c__lui}, + /* instruction C__ADDI16SP, encoding '0b0110000100000001' */ + {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c__addi16sp}, /* instruction __reserved_clui, encoding '0b0110000000000001' */ {16, 0b0110000000000001, 0b1111000001111111, &this_class::____reserved_clui}, - /* instruction CSRLI, encoding '0b1000000000000001' */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__csrli}, - /* instruction CSRAI, encoding '0b1000010000000001' */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__csrai}, - /* instruction CANDI, encoding '0b1000100000000001' */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__candi}, - /* instruction CSUB, encoding '0b1000110000000001' */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__csub}, - /* instruction CXOR, encoding '0b1000110000100001' */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__cxor}, - /* instruction COR, encoding '0b1000110001000001' */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__cor}, - /* instruction CAND, encoding '0b1000110001100001' */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__cand}, - /* instruction CJ, encoding '0b1010000000000001' */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__cj}, - /* instruction CBEQZ, encoding '0b1100000000000001' */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__cbeqz}, - /* instruction CBNEZ, encoding '0b1110000000000001' */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__cbnez}, - /* instruction CSLLI, encoding '0b0000000000000010' */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__cslli}, - /* instruction CLWSP, encoding '0b0100000000000010' */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__clwsp}, - /* instruction CMV, encoding '0b1000000000000010' */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__cmv}, - /* instruction CJR, encoding '0b1000000000000010' */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__cjr}, + /* instruction C__SRLI, encoding '0b1000000000000001' */ + {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c__srli}, + /* instruction C__SRAI, encoding '0b1000010000000001' */ + {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c__srai}, + /* instruction C__ANDI, encoding '0b1000100000000001' */ + {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c__andi}, + /* instruction C__SUB, encoding '0b1000110000000001' */ + {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c__sub}, + /* instruction C__XOR, encoding '0b1000110000100001' */ + {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c__xor}, + /* instruction C__OR, encoding '0b1000110001000001' */ + {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c__or}, + /* instruction C__AND, encoding '0b1000110001100001' */ + {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c__and}, + /* instruction C__J, encoding '0b1010000000000001' */ + {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c__j}, + /* instruction C__BEQZ, encoding '0b1100000000000001' */ + {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c__beqz}, + /* instruction C__BNEZ, encoding '0b1110000000000001' */ + {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c__bnez}, + /* instruction C__SLLI, encoding '0b0000000000000010' */ + {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c__slli}, + /* instruction C__LWSP, encoding '0b0100000000000010' */ + {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c__lwsp}, + /* instruction C__MV, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c__mv}, + /* instruction C__JR, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c__jr}, /* instruction __reserved_cmv, encoding '0b1000000000000010' */ {16, 0b1000000000000010, 0b1111111111111111, &this_class::____reserved_cmv}, - /* instruction CADD, encoding '0b1001000000000010' */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__cadd}, - /* instruction CJALR, encoding '0b1001000000000010' */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__cjalr}, - /* instruction CEBREAK, encoding '0b1001000000000010' */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__cebreak}, - /* instruction CSWSP, encoding '0b1100000000000010' */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__cswsp}, + /* instruction C__ADD, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c__add}, + /* instruction C__JALR, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c__jalr}, + /* instruction C__EBREAK, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c__ebreak}, + /* instruction C__SWSP, encoding '0b1100000000000010' */ + {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c__swsp}, /* instruction DII, encoding '0b0000000000000000' */ {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, }}; @@ -3194,9 +3194,9 @@ private: return returnValue; } - /* instruction 57: CADDI4SPN */ - std::tuple __caddi4spn(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CADDI4SPN_0x{:X}",pc.val)); + /* instruction 57: C__ADDI4SPN */ + std::tuple __c__addi4spn(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__ADDI4SPN_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,57); uint64_t PC = pc.val; uint8_t rd = ((bit_sub<2,3>(instr))); @@ -3204,7 +3204,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c__addi4spn"), fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); std::vector args { this->core_ptr, @@ -3238,9 +3238,9 @@ private: return returnValue; } - /* instruction 58: CLW */ - std::tuple __clw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CLW_0x{:X}",pc.val)); + /* instruction 58: C__LW */ + std::tuple __c__lw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__LW_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,58); uint64_t PC = pc.val; uint8_t rd = ((bit_sub<2,3>(instr))); @@ -3249,7 +3249,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c__lw"), fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); std::vector args { this->core_ptr, @@ -3283,9 +3283,9 @@ private: return returnValue; } - /* instruction 59: CSW */ - std::tuple __csw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CSW_0x{:X}",pc.val)); + /* instruction 59: C__SW */ + std::tuple __c__sw(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__SW_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,59); uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,3>(instr))); @@ -3294,7 +3294,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c__sw"), fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); std::vector args { this->core_ptr, @@ -3326,9 +3326,9 @@ private: return returnValue; } - /* instruction 60: CADDI */ - std::tuple __caddi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CADDI_0x{:X}",pc.val)); + /* instruction 60: C__ADDI */ + std::tuple __c__addi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__ADDI_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,60); uint64_t PC = pc.val; uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); @@ -3336,7 +3336,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__addi"), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); std::vector args { this->core_ptr, @@ -3372,9 +3372,9 @@ private: return returnValue; } - /* instruction 61: CNOP */ - std::tuple __cnop(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CNOP_0x{:X}",pc.val)); + /* instruction 61: C__NOP */ + std::tuple __c__nop(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__NOP_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,61); uint64_t PC = pc.val; uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); @@ -3394,16 +3394,16 @@ private: return returnValue; } - /* instruction 62: CJAL */ - std::tuple __cjal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CJAL_0x{:X}",pc.val)); + /* instruction 62: C__JAL */ + std::tuple __c__jal(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__JAL_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,62); uint64_t PC = pc.val; uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c__jal"), fmt::arg("imm", imm)); std::vector args { this->core_ptr, @@ -3430,9 +3430,9 @@ private: return returnValue; } - /* instruction 63: CLI */ - std::tuple __cli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CLI_0x{:X}",pc.val)); + /* instruction 63: C__LI */ + std::tuple __c__li(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__LI_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,63); uint64_t PC = pc.val; uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); @@ -3440,7 +3440,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c__li"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); std::vector args { this->core_ptr, @@ -3471,9 +3471,9 @@ private: return returnValue; } - /* instruction 64: CLUI */ - std::tuple __clui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CLUI_0x{:X}",pc.val)); + /* instruction 64: C__LUI */ + std::tuple __c__lui(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__LUI_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,64); uint64_t PC = pc.val; uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); @@ -3481,7 +3481,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c__lui"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); std::vector args { this->core_ptr, @@ -3510,16 +3510,16 @@ private: return returnValue; } - /* instruction 65: CADDI16SP */ - std::tuple __caddi16sp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CADDI16SP_0x{:X}",pc.val)); + /* instruction 65: C__ADDI16SP */ + std::tuple __c__addi16sp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__ADDI16SP_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,65); uint64_t PC = pc.val; uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "c__addi16sp"), fmt::arg("nzimm", nzimm)); std::vector args { this->core_ptr, @@ -3576,9 +3576,9 @@ private: return returnValue; } - /* instruction 67: CSRLI */ - std::tuple __csrli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CSRLI_0x{:X}",pc.val)); + /* instruction 67: C__SRLI */ + std::tuple __c__srli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__SRLI_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,67); uint64_t PC = pc.val; uint8_t shamt = ((bit_sub<2,5>(instr))); @@ -3586,7 +3586,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c__srli"), fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); std::vector args { this->core_ptr, @@ -3613,9 +3613,9 @@ private: return returnValue; } - /* instruction 68: CSRAI */ - std::tuple __csrai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CSRAI_0x{:X}",pc.val)); + /* instruction 68: C__SRAI */ + std::tuple __c__srai(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__SRAI_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,68); uint64_t PC = pc.val; uint8_t shamt = ((bit_sub<2,5>(instr))); @@ -3623,7 +3623,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c__srai"), fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); std::vector args { this->core_ptr, @@ -3668,9 +3668,9 @@ private: return returnValue; } - /* instruction 69: CANDI */ - std::tuple __candi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CANDI_0x{:X}",pc.val)); + /* instruction 69: C__ANDI */ + std::tuple __c__andi(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__ANDI_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,69); uint64_t PC = pc.val; uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); @@ -3678,7 +3678,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__andi"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); std::vector args { this->core_ptr, @@ -3707,9 +3707,9 @@ private: return returnValue; } - /* instruction 70: CSUB */ - std::tuple __csub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CSUB_0x{:X}",pc.val)); + /* instruction 70: C__SUB */ + std::tuple __c__sub(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__SUB_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,70); uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,3>(instr))); @@ -3717,7 +3717,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__sub"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); std::vector args { this->core_ptr, @@ -3746,9 +3746,9 @@ private: return returnValue; } - /* instruction 71: CXOR */ - std::tuple __cxor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CXOR_0x{:X}",pc.val)); + /* instruction 71: C__XOR */ + std::tuple __c__xor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__XOR_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,71); uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,3>(instr))); @@ -3756,7 +3756,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__xor"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); std::vector args { this->core_ptr, @@ -3783,9 +3783,9 @@ private: return returnValue; } - /* instruction 72: COR */ - std::tuple __cor(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("COR_0x{:X}",pc.val)); + /* instruction 72: C__OR */ + std::tuple __c__or(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__OR_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,72); uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,3>(instr))); @@ -3793,7 +3793,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__or"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); std::vector args { this->core_ptr, @@ -3820,9 +3820,9 @@ private: return returnValue; } - /* instruction 73: CAND */ - std::tuple __cand(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CAND_0x{:X}",pc.val)); + /* instruction 73: C__AND */ + std::tuple __c__and(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__AND_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,73); uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,3>(instr))); @@ -3830,7 +3830,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__and"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); std::vector args { this->core_ptr, @@ -3857,16 +3857,16 @@ private: return returnValue; } - /* instruction 74: CJ */ - std::tuple __cj(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CJ_0x{:X}",pc.val)); + /* instruction 74: C__J */ + std::tuple __c__j(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__J_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,74); uint64_t PC = pc.val; uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c__j"), fmt::arg("imm", imm)); std::vector args { this->core_ptr, @@ -3890,9 +3890,9 @@ private: return returnValue; } - /* instruction 75: CBEQZ */ - std::tuple __cbeqz(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CBEQZ_0x{:X}",pc.val)); + /* instruction 75: C__BEQZ */ + std::tuple __c__beqz(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__BEQZ_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,75); uint64_t PC = pc.val; uint16_t imm = ((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)); @@ -3900,7 +3900,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__beqz"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); std::vector args { this->core_ptr, @@ -3935,9 +3935,9 @@ private: return returnValue; } - /* instruction 76: CBNEZ */ - std::tuple __cbnez(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CBNEZ_0x{:X}",pc.val)); + /* instruction 76: C__BNEZ */ + std::tuple __c__bnez(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__BNEZ_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,76); uint64_t PC = pc.val; uint16_t imm = ((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)); @@ -3945,7 +3945,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__bnez"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); std::vector args { this->core_ptr, @@ -3980,9 +3980,9 @@ private: return returnValue; } - /* instruction 77: CSLLI */ - std::tuple __cslli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CSLLI_0x{:X}",pc.val)); + /* instruction 77: C__SLLI */ + std::tuple __c__slli(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__SLLI_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,77); uint64_t PC = pc.val; uint8_t nzuimm = ((bit_sub<2,5>(instr))); @@ -3990,7 +3990,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "c__slli"), fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); std::vector args { this->core_ptr, @@ -4024,9 +4024,9 @@ private: return returnValue; } - /* instruction 78: CLWSP */ - std::tuple __clwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CLWSP_0x{:X}",pc.val)); + /* instruction 78: C__LWSP */ + std::tuple __c__lwsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__LWSP_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,78); uint64_t PC = pc.val; uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); @@ -4034,7 +4034,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c__lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); std::vector args { this->core_ptr, @@ -4073,9 +4073,9 @@ private: return returnValue; } - /* instruction 79: CMV */ - std::tuple __cmv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CMV_0x{:X}",pc.val)); + /* instruction 79: C__MV */ + std::tuple __c__mv(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__MV_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,79); uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,5>(instr))); @@ -4083,7 +4083,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__mv"), fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); std::vector args { this->core_ptr, @@ -4114,16 +4114,16 @@ private: return returnValue; } - /* instruction 80: CJR */ - std::tuple __cjr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CJR_0x{:X}",pc.val)); + /* instruction 80: C__JR */ + std::tuple __c__jr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__JR_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,80); uint64_t PC = pc.val; uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c__jr"), fmt::arg("rs1", name(rs1))); std::vector args { this->core_ptr, @@ -4177,9 +4177,9 @@ private: return returnValue; } - /* instruction 82: CADD */ - std::tuple __cadd(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CADD_0x{:X}",pc.val)); + /* instruction 82: C__ADD */ + std::tuple __c__add(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__ADD_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,82); uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,5>(instr))); @@ -4187,7 +4187,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__add"), fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); std::vector args { this->core_ptr, @@ -4223,16 +4223,16 @@ private: return returnValue; } - /* instruction 83: CJALR */ - std::tuple __cjalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CJALR_0x{:X}",pc.val)); + /* instruction 83: C__JALR */ + std::tuple __c__jalr(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__JALR_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,83); uint64_t PC = pc.val; uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c__jalr"), fmt::arg("rs1", name(rs1))); std::vector args { this->core_ptr, @@ -4269,9 +4269,9 @@ private: return returnValue; } - /* instruction 84: CEBREAK */ - std::tuple __cebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CEBREAK_0x{:X}",pc.val)); + /* instruction 84: C__EBREAK */ + std::tuple __c__ebreak(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__EBREAK_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,84); uint64_t PC = pc.val; if(this->disass_enabled){ @@ -4291,9 +4291,9 @@ private: return returnValue; } - /* instruction 85: CSWSP */ - std::tuple __cswsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ - bb->setName(fmt::format("CSWSP_0x{:X}",pc.val)); + /* instruction 85: C__SWSP */ + std::tuple __c__swsp(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){ + bb->setName(fmt::format("C__SWSP_0x{:X}",pc.val)); this->gen_sync(PRE_SYNC,85); uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,5>(instr))); @@ -4301,7 +4301,7 @@ private: if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c__swsp"), fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); std::vector args { this->core_ptr, diff --git a/src/vm/tcc/vm_tgc5c.cpp b/src/vm/tcc/vm_tgc5c.cpp index 484b443..36e5ad8 100644 --- a/src/vm/tcc/vm_tgc5c.cpp +++ b/src/vm/tcc/vm_tgc5c.cpp @@ -264,64 +264,64 @@ private: {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, /* instruction REMU, encoding '0b00000010000000000111000000110011' */ {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, - /* instruction CADDI4SPN, encoding '0b0000000000000000' */ - {16, 0b0000000000000000, 0b1110000000000011, &this_class::__caddi4spn}, - /* instruction CLW, encoding '0b0100000000000000' */ - {16, 0b0100000000000000, 0b1110000000000011, &this_class::__clw}, - /* instruction CSW, encoding '0b1100000000000000' */ - {16, 0b1100000000000000, 0b1110000000000011, &this_class::__csw}, - /* instruction CADDI, encoding '0b0000000000000001' */ - {16, 0b0000000000000001, 0b1110000000000011, &this_class::__caddi}, - /* instruction CNOP, encoding '0b0000000000000001' */ - {16, 0b0000000000000001, 0b1110111110000011, &this_class::__cnop}, - /* instruction CJAL, encoding '0b0010000000000001' */ - {16, 0b0010000000000001, 0b1110000000000011, &this_class::__cjal}, - /* instruction CLI, encoding '0b0100000000000001' */ - {16, 0b0100000000000001, 0b1110000000000011, &this_class::__cli}, - /* instruction CLUI, encoding '0b0110000000000001' */ - {16, 0b0110000000000001, 0b1110000000000011, &this_class::__clui}, - /* instruction CADDI16SP, encoding '0b0110000100000001' */ - {16, 0b0110000100000001, 0b1110111110000011, &this_class::__caddi16sp}, + /* instruction C__ADDI4SPN, encoding '0b0000000000000000' */ + {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c__addi4spn}, + /* instruction C__LW, encoding '0b0100000000000000' */ + {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c__lw}, + /* instruction C__SW, encoding '0b1100000000000000' */ + {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c__sw}, + /* instruction C__ADDI, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c__addi}, + /* instruction C__NOP, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110111110000011, &this_class::__c__nop}, + /* instruction C__JAL, encoding '0b0010000000000001' */ + {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c__jal}, + /* instruction C__LI, encoding '0b0100000000000001' */ + {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c__li}, + /* instruction C__LUI, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c__lui}, + /* instruction C__ADDI16SP, encoding '0b0110000100000001' */ + {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c__addi16sp}, /* instruction __reserved_clui, encoding '0b0110000000000001' */ {16, 0b0110000000000001, 0b1111000001111111, &this_class::____reserved_clui}, - /* instruction CSRLI, encoding '0b1000000000000001' */ - {16, 0b1000000000000001, 0b1111110000000011, &this_class::__csrli}, - /* instruction CSRAI, encoding '0b1000010000000001' */ - {16, 0b1000010000000001, 0b1111110000000011, &this_class::__csrai}, - /* instruction CANDI, encoding '0b1000100000000001' */ - {16, 0b1000100000000001, 0b1110110000000011, &this_class::__candi}, - /* instruction CSUB, encoding '0b1000110000000001' */ - {16, 0b1000110000000001, 0b1111110001100011, &this_class::__csub}, - /* instruction CXOR, encoding '0b1000110000100001' */ - {16, 0b1000110000100001, 0b1111110001100011, &this_class::__cxor}, - /* instruction COR, encoding '0b1000110001000001' */ - {16, 0b1000110001000001, 0b1111110001100011, &this_class::__cor}, - /* instruction CAND, encoding '0b1000110001100001' */ - {16, 0b1000110001100001, 0b1111110001100011, &this_class::__cand}, - /* instruction CJ, encoding '0b1010000000000001' */ - {16, 0b1010000000000001, 0b1110000000000011, &this_class::__cj}, - /* instruction CBEQZ, encoding '0b1100000000000001' */ - {16, 0b1100000000000001, 0b1110000000000011, &this_class::__cbeqz}, - /* instruction CBNEZ, encoding '0b1110000000000001' */ - {16, 0b1110000000000001, 0b1110000000000011, &this_class::__cbnez}, - /* instruction CSLLI, encoding '0b0000000000000010' */ - {16, 0b0000000000000010, 0b1111000000000011, &this_class::__cslli}, - /* instruction CLWSP, encoding '0b0100000000000010' */ - {16, 0b0100000000000010, 0b1110000000000011, &this_class::__clwsp}, - /* instruction CMV, encoding '0b1000000000000010' */ - {16, 0b1000000000000010, 0b1111000000000011, &this_class::__cmv}, - /* instruction CJR, encoding '0b1000000000000010' */ - {16, 0b1000000000000010, 0b1111000001111111, &this_class::__cjr}, + /* instruction C__SRLI, encoding '0b1000000000000001' */ + {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c__srli}, + /* instruction C__SRAI, encoding '0b1000010000000001' */ + {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c__srai}, + /* instruction C__ANDI, encoding '0b1000100000000001' */ + {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c__andi}, + /* instruction C__SUB, encoding '0b1000110000000001' */ + {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c__sub}, + /* instruction C__XOR, encoding '0b1000110000100001' */ + {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c__xor}, + /* instruction C__OR, encoding '0b1000110001000001' */ + {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c__or}, + /* instruction C__AND, encoding '0b1000110001100001' */ + {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c__and}, + /* instruction C__J, encoding '0b1010000000000001' */ + {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c__j}, + /* instruction C__BEQZ, encoding '0b1100000000000001' */ + {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c__beqz}, + /* instruction C__BNEZ, encoding '0b1110000000000001' */ + {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c__bnez}, + /* instruction C__SLLI, encoding '0b0000000000000010' */ + {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c__slli}, + /* instruction C__LWSP, encoding '0b0100000000000010' */ + {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c__lwsp}, + /* instruction C__MV, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c__mv}, + /* instruction C__JR, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c__jr}, /* instruction __reserved_cmv, encoding '0b1000000000000010' */ {16, 0b1000000000000010, 0b1111111111111111, &this_class::____reserved_cmv}, - /* instruction CADD, encoding '0b1001000000000010' */ - {16, 0b1001000000000010, 0b1111000000000011, &this_class::__cadd}, - /* instruction CJALR, encoding '0b1001000000000010' */ - {16, 0b1001000000000010, 0b1111000001111111, &this_class::__cjalr}, - /* instruction CEBREAK, encoding '0b1001000000000010' */ - {16, 0b1001000000000010, 0b1111111111111111, &this_class::__cebreak}, - /* instruction CSWSP, encoding '0b1100000000000010' */ - {16, 0b1100000000000010, 0b1110000000000011, &this_class::__cswsp}, + /* instruction C__ADD, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c__add}, + /* instruction C__JALR, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c__jalr}, + /* instruction C__EBREAK, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c__ebreak}, + /* instruction C__SWSP, encoding '0b1100000000000010' */ + {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c__swsp}, /* instruction DII, encoding '0b0000000000000000' */ {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, }}; @@ -331,6 +331,7 @@ private: compile_ret_t __lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LUI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,0); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ @@ -364,6 +365,7 @@ private: compile_ret_t __auipc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("AUIPC_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,1); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,20>(instr) << 12)); if(this->disass_enabled){ @@ -382,7 +384,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)imm,32))),32,true)); + tu.store(rd + traits::X0,tu.constant((uint32_t)(PC+(int32_t)imm),32)); } } auto returnValue = std::make_tuple(CONT); @@ -397,6 +399,7 @@ private: compile_ret_t __jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("JAL_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,2); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); if(this->disass_enabled){ @@ -418,9 +421,9 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 4,8))),32,true)); + tu.store(rd + traits::X0,tu.constant((uint32_t)(PC+ 4),32)); } - auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int32_t)sext<21>(imm),32))),32,true),32); + auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int32_t)sext<21>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -437,6 +440,7 @@ private: compile_ret_t __jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("JALR_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,3); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -455,14 +459,15 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto new_pc = tu.assignment(tu.ext((tu.bitwise_and((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),tu.constant(~ 0x1,8))),32,true),32); + auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); + auto new_pc = tu.assignment(tu.ext((tu.bitwise_and((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),addr_mask)),32,false),32); tu.open_if(tu.srem(new_pc,tu.constant(static_cast(traits:: INSTR_ALIGNMENT),32))); this->gen_raise_trap(tu, 0, 0); tu.open_else(); if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 4,8))),32,true)); + tu.store(rd + traits::X0,tu.constant((uint32_t)(PC+ 4),32)); } - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); + auto PC_val_v = tu.assignment("PC_val", new_pc,32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); @@ -479,6 +484,7 @@ private: compile_ret_t __beq(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BEQ_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,4); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -501,7 +507,7 @@ private: if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); + auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<13>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -519,6 +525,7 @@ private: compile_ret_t __bne(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BNE_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,5); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -541,7 +548,7 @@ private: if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); + auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<13>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -559,6 +566,7 @@ private: compile_ret_t __blt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BLT_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,6); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -577,11 +585,11 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false))); + tu.open_if(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true))); if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); + auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<13>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -599,6 +607,7 @@ private: compile_ret_t __bge(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BGE_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,7); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -617,11 +626,11 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_SGE,tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false))); + tu.open_if(tu.icmp(ICmpInst::ICMP_SGE,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true))); if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); + auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<13>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -639,6 +648,7 @@ private: compile_ret_t __bltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BLTU_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,8); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -661,7 +671,7 @@ private: if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); + auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<13>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -679,6 +689,7 @@ private: compile_ret_t __bgeu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("BGEU_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,9); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -701,7 +712,7 @@ private: if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ - auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<13>(imm),16))),32,true),32); + auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<13>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -719,6 +730,7 @@ private: compile_ret_t __lb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LB_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,10); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -737,10 +749,10 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); - auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 8),8,false),8); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 8),8,true),8); if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext(res,32,true)); + tu.store(rd + traits::X0,tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -755,6 +767,7 @@ private: compile_ret_t __lh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LH_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,11); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -773,10 +786,10 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); - auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 16),16,false),16); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 16),16,true),16); if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext(res,32,true)); + tu.store(rd + traits::X0,tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -791,6 +804,7 @@ private: compile_ret_t __lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LW_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,12); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -809,10 +823,10 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); - auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,false),32); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,true),32); if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext(res,32,true)); + tu.store(rd + traits::X0,tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -827,6 +841,7 @@ private: compile_ret_t __lbu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LBU_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,13); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -845,10 +860,10 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); auto res = tu.assignment(tu.read_mem(traits::MEM, load_address, 8),8); if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext(res,32,true)); + tu.store(rd + traits::X0,tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -863,6 +878,7 @@ private: compile_ret_t __lhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("LHU_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,14); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -881,10 +897,10 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); + auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); auto res = tu.assignment(tu.read_mem(traits::MEM, load_address, 16),16); if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext(res,32,true)); + tu.store(rd + traits::X0,tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -899,6 +915,7 @@ private: compile_ret_t __sb(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SB_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,15); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -917,8 +934,8 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); - tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),8,true)); + auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),8,false)); } auto returnValue = std::make_tuple(CONT); @@ -932,6 +949,7 @@ private: compile_ret_t __sh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SH_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,16); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -950,8 +968,8 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); - tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),16,true)); + auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),16,false)); } auto returnValue = std::make_tuple(CONT); @@ -965,6 +983,7 @@ private: compile_ret_t __sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SW_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,17); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -983,8 +1002,8 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); - tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),32,true)); + auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),32,false)); } auto returnValue = std::make_tuple(CONT); @@ -998,6 +1017,7 @@ private: compile_ret_t __addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ADDI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,18); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1017,7 +1037,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -1032,6 +1052,7 @@ private: compile_ret_t __slti(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLTI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,19); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1051,7 +1072,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant((int16_t)sext<12>(imm),16))), tu.constant( 1,8),tu.constant( 0,8))); + tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.constant((int16_t)sext<12>(imm),16))), tu.constant( 1,8),tu.constant( 0,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1066,6 +1087,7 @@ private: compile_ret_t __sltiu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLTIU_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,20); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1100,6 +1122,7 @@ private: compile_ret_t __xori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("XORI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,21); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1134,6 +1157,7 @@ private: compile_ret_t __ori(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ORI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,22); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1168,6 +1192,7 @@ private: compile_ret_t __andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ANDI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,23); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -1202,6 +1227,7 @@ private: compile_ret_t __slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLLI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,24); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1236,6 +1262,7 @@ private: compile_ret_t __srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRLI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,25); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1255,7 +1282,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.lshr(tu.load(rs1+ traits::X0, 0),tu.constant(shamt,8))); + tu.store(rd + traits::X0,tu.ashr(tu.load(rs1+ traits::X0, 0),tu.constant(shamt,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1270,6 +1297,7 @@ private: compile_ret_t __srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRAI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,26); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t shamt = ((bit_sub<20,5>(instr))); @@ -1289,7 +1317,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.constant(shamt,8))),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.ashr(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.constant(shamt,8))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -1304,6 +1332,7 @@ private: compile_ret_t __add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ADD_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,27); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1323,7 +1352,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -1338,6 +1367,7 @@ private: compile_ret_t __sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SUB_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,28); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1357,7 +1387,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.sub(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.sub(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -1372,6 +1402,7 @@ private: compile_ret_t __sll(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLL_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,29); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1406,6 +1437,7 @@ private: compile_ret_t __slt(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLT_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,30); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1425,7 +1457,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true)), tu.constant( 1,8),tu.constant( 0,8))); + tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false)), tu.constant( 1,8),tu.constant( 0,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1440,6 +1472,7 @@ private: compile_ret_t __sltu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SLTU_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,31); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1474,6 +1507,7 @@ private: compile_ret_t __xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("XOR_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,32); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1508,6 +1542,7 @@ private: compile_ret_t __srl(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRL_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,33); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1527,7 +1562,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.lshr(tu.load(rs1+ traits::X0, 0),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); + tu.store(rd + traits::X0,tu.ashr(tu.load(rs1+ traits::X0, 0),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); } } auto returnValue = std::make_tuple(CONT); @@ -1542,6 +1577,7 @@ private: compile_ret_t __sra(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("SRA_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,34); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1561,7 +1597,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.lshr(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.ashr(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -1576,6 +1612,7 @@ private: compile_ret_t __or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("OR_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,35); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1610,6 +1647,7 @@ private: compile_ret_t __and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("AND_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,36); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -1644,6 +1682,7 @@ private: compile_ret_t __fence(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("FENCE_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,37); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t succ = ((bit_sub<20,4>(instr))); @@ -1673,6 +1712,7 @@ private: compile_ret_t __ecall(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("ECALL_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,38); + uint64_t PC = pc.val; if(this->disass_enabled){ /* generate console output when executing the command */ tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ecall"); @@ -1694,6 +1734,7 @@ private: compile_ret_t __ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("EBREAK_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,39); + uint64_t PC = pc.val; if(this->disass_enabled){ /* generate console output when executing the command */ tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "ebreak"); @@ -1715,6 +1756,7 @@ private: compile_ret_t __mret(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MRET_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,40); + uint64_t PC = pc.val; if(this->disass_enabled){ /* generate console output when executing the command */ tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "mret"); @@ -1736,6 +1778,7 @@ private: compile_ret_t __wfi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("WFI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,41); + uint64_t PC = pc.val; if(this->disass_enabled){ /* generate console output when executing the command */ tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "wfi"); @@ -1757,6 +1800,7 @@ private: compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRW_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,42); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1796,6 +1840,7 @@ private: compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRS_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,43); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1835,6 +1880,7 @@ private: compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRC_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,44); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1874,6 +1920,7 @@ private: compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRWI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,45); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1910,6 +1957,7 @@ private: compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRSI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,46); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1948,6 +1996,7 @@ private: compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("CSRRCI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,47); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -1986,6 +2035,7 @@ private: compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("FENCE_I_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,48); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t imm = ((bit_sub<20,12>(instr))); @@ -2013,6 +2063,7 @@ private: compile_ret_t __mul(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MUL_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,49); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2031,9 +2082,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false))),64,false),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),64,true),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,false),64,true))),64,true),64); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext(res,32,true)); + tu.store(rd + traits::X0,tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2048,6 +2099,7 @@ private: compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MULH_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,50); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2066,9 +2118,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,false))),64,false),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),64,true),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,false),64,true))),64,true),64); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.ashr(res,tu.constant(static_cast(traits:: XLEN),32))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2083,6 +2135,7 @@ private: compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MULHSU_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,51); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2101,9 +2154,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,false),tu.ext(tu.load(rs2+ traits::X0, 0),64,true))),64,false),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),64,true),tu.ext(tu.load(rs2+ traits::X0, 0),64,false))),64,true),64); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.ashr(res,tu.constant(static_cast(traits:: XLEN),32))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2118,6 +2171,7 @@ private: compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("MULHU_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,52); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2136,9 +2190,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),64,true),tu.ext(tu.load(rs2+ traits::X0, 0),64,true))),64,true),64); + auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),64,false),tu.ext(tu.load(rs2+ traits::X0, 0),64,false))),64,false),64); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext((tu.lshr(res,tu.constant(static_cast(traits:: XLEN),32))),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.ashr(res,tu.constant(static_cast(traits:: XLEN),32))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2153,6 +2207,7 @@ private: compile_ret_t __div(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("DIV_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,53); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2171,14 +2226,14 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto dividend = tu.assignment(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),32); - auto divisor = tu.assignment(tu.ext(tu.load(rs2+ traits::X0, 0),32,false),32); + auto dividend = tu.assignment(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),32); + auto divisor = tu.assignment(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),32); if(rd!= 0){ tu.open_if(tu.icmp(ICmpInst::ICMP_NE,divisor,tu.constant( 0,8))); auto MMIN = tu.assignment(tu.constant(((uint32_t)1)<<(static_cast(traits:: XLEN)-1),32),32); tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,divisor,tu.constant(- 1,8)))); tu.store(rd + traits::X0,MMIN); tu.open_else(); - tu.store(rd + traits::X0,tu.ext((tu.sdiv(dividend,divisor)),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.sdiv(dividend,divisor)),32,false)); tu.close_scope(); tu.open_else(); tu.store(rd + traits::X0,tu.constant((uint32_t)- 1,32)); @@ -2197,6 +2252,7 @@ private: compile_ret_t __divu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("DIVU_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,54); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2217,7 +2273,7 @@ private: else{ tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,8))); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext((tu.sdiv(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.sdiv(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,false)); } tu.open_else(); if(rd!=0) { @@ -2237,6 +2293,7 @@ private: compile_ret_t __rem(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("REM_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,55); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2256,14 +2313,14 @@ private: } else{ tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,8))); - auto MMIN = tu.assignment(tu.constant( 1<<(static_cast(traits:: XLEN)-1),8),32); - tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,tu.ext(tu.load(rs2+ traits::X0, 0),32,false),tu.constant(- 1,8)))); + auto MMIN = tu.assignment(tu.constant((uint32_t)1<<(static_cast(traits:: XLEN)-1),32),32); + tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,tu.ext(tu.load(rs2+ traits::X0, 0),32,true),tu.constant(- 1,8)))); if(rd!=0) { tu.store(rd + traits::X0,tu.constant( 0,8)); } tu.open_else(); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext((tu.srem(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false))),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.srem(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true))),32,false)); } tu.close_scope(); tu.open_else(); @@ -2284,6 +2341,7 @@ private: compile_ret_t __remu(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("REMU_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,56); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2320,16 +2378,17 @@ private: return returnValue; } - /* instruction 57: CADDI4SPN */ - compile_ret_t __caddi4spn(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CADDI4SPN_{:#010x}:", pc.val); + /* instruction 57: C__ADDI4SPN */ + compile_ret_t __c__addi4spn(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__ADDI4SPN_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,57); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<2,3>(instr))); uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "caddi4spn"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c__addi4spn"), fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2338,7 +2397,7 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(imm) { - tu.store(rd+ 8 + traits::X0,tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(imm,8))),32,true)); + tu.store(rd+ 8 + traits::X0,tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(imm,16))),32,false)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -2351,17 +2410,18 @@ private: return returnValue; } - /* instruction 58: CLW */ - compile_ret_t __clw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CLW_{:#010x}:", pc.val); + /* instruction 58: C__LW */ + compile_ret_t __c__lw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__LW_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,58); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "clw"), + "{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c__lw"), fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2369,8 +2429,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); - tu.store(rd+ 8 + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32,true)); + auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,false),32); + tu.store(rd+ 8 + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,true),32,false)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2379,17 +2439,18 @@ private: return returnValue; } - /* instruction 59: CSW */ - compile_ret_t __csw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSW_{:#010x}:", pc.val); + /* instruction 59: C__SW */ + compile_ret_t __c__sw(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__SW_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,59); + uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "csw"), + "{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c__sw"), fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1))); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2397,8 +2458,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); - tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,true)); + auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,false),32); + tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,false)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2407,16 +2468,17 @@ private: return returnValue; } - /* instruction 60: CADDI */ - compile_ret_t __caddi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CADDI_{:#010x}:", pc.val); + /* instruction 60: C__ADDI */ + compile_ret_t __c__addi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__ADDI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,60); + uint64_t PC = pc.val; uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "caddi"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__addi"), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2429,7 +2491,7 @@ private: } else{ if(rs1!= 0) { - tu.store(rs1 + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))),32,true)); + tu.store(rs1 + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2440,14 +2502,15 @@ private: return returnValue; } - /* instruction 61: CNOP */ - compile_ret_t __cnop(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CNOP_{:#010x}:", pc.val); + /* instruction 61: C__NOP */ + compile_ret_t __c__nop(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__NOP_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,61); + uint64_t PC = pc.val; uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "cnop"); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c__nop"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+ 2; @@ -2461,15 +2524,16 @@ private: return returnValue; } - /* instruction 62: CJAL */ - compile_ret_t __cjal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CJAL_{:#010x}:", pc.val); + /* instruction 62: C__JAL */ + compile_ret_t __c__jal(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__JAL_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,62); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cjal"), + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c__jal"), fmt::arg("imm", imm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2477,8 +2541,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(1 + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,8))),32,true)); - auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); + tu.store(1 + traits::X0,tu.constant((uint32_t)(PC+ 2),32)); + auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<12>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); auto returnValue = std::make_tuple(BRANCH); @@ -2489,16 +2553,17 @@ private: return returnValue; } - /* instruction 63: CLI */ - compile_ret_t __cli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CLI_{:#010x}:", pc.val); + /* instruction 63: C__LI */ + compile_ret_t __c__li(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__LI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,63); + uint64_t PC = pc.val; uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "cli"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c__li"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2522,16 +2587,17 @@ private: return returnValue; } - /* instruction 64: CLUI */ - compile_ret_t __clui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CLUI_{:#010x}:", pc.val); + /* instruction 64: C__LUI */ + compile_ret_t __c__lui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__LUI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,64); + uint64_t PC = pc.val; uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "clui"), + "{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c__lui"), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2553,15 +2619,16 @@ private: return returnValue; } - /* instruction 65: CADDI16SP */ - compile_ret_t __caddi16sp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CADDI16SP_{:#010x}:", pc.val); + /* instruction 65: C__ADDI16SP */ + compile_ret_t __c__addi16sp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__ADDI16SP_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,65); + uint64_t PC = pc.val; uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "caddi16sp"), + "{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "c__addi16sp"), fmt::arg("nzimm", nzimm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2570,7 +2637,7 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(nzimm) { - tu.store(2 + traits::X0,tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant((int16_t)sext<10>(nzimm),16))),32,true)); + tu.store(2 + traits::X0,tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant((int16_t)sext<10>(nzimm),16))),32,false)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -2587,6 +2654,7 @@ private: compile_ret_t ____reserved_clui(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("__reserved_clui_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,66); + uint64_t PC = pc.val; uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -2605,16 +2673,17 @@ private: return returnValue; } - /* instruction 67: CSRLI */ - compile_ret_t __csrli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRLI_{:#010x}:", pc.val); + /* instruction 67: C__SRLI */ + compile_ret_t __c__srli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__SRLI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,67); + uint64_t PC = pc.val; uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrli"), + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c__srli"), fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2622,7 +2691,7 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(rs1+ 8 + traits::X0,tu.lshr(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(shamt,8))); + tu.store(rs1+ 8 + traits::X0,tu.ashr(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(shamt,8))); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2631,16 +2700,17 @@ private: return returnValue; } - /* instruction 68: CSRAI */ - compile_ret_t __csrai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSRAI_{:#010x}:", pc.val); + /* instruction 68: C__SRAI */ + compile_ret_t __c__srai(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__SRAI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,68); + uint64_t PC = pc.val; uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "csrai"), + "{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c__srai"), fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2648,10 +2718,10 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - if(shamt){ tu.store(rs1+ 8 + traits::X0,tu.ext((tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant(shamt,8))),32,true)); + if(shamt){ tu.store(rs1+ 8 + traits::X0,tu.ext((tu.ashr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,true)),tu.constant(shamt,8))),32,false)); } else{ - if(static_cast(traits:: XLEN)== 128){ tu.store(rs1+ 8 + traits::X0,tu.ext((tu.lshr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,false)),tu.constant( 64,8))),32,true)); + if(static_cast(traits:: XLEN)== 128){ tu.store(rs1+ 8 + traits::X0,tu.ext((tu.ashr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,true)),tu.constant( 64,8))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2662,16 +2732,17 @@ private: return returnValue; } - /* instruction 69: CANDI */ - compile_ret_t __candi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CANDI_{:#010x}:", pc.val); + /* instruction 69: C__ANDI */ + compile_ret_t __c__andi(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__ANDI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,69); + uint64_t PC = pc.val; uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "candi"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__andi"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2679,7 +2750,7 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(rs1+ 8 + traits::X0,tu.ext((tu.bitwise_and(tu.load(rs1+ 8+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))),32,true)); + tu.store(rs1+ 8 + traits::X0,tu.ext((tu.bitwise_and(tu.load(rs1+ 8+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))),32,false)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2688,16 +2759,17 @@ private: return returnValue; } - /* instruction 70: CSUB */ - compile_ret_t __csub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSUB_{:#010x}:", pc.val); + /* instruction 70: C__SUB */ + compile_ret_t __c__sub(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__SUB_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,70); + uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "csub"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__sub"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2705,7 +2777,7 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(rd+ 8 + traits::X0,tu.ext((tu.sub(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))),32,true)); + tu.store(rd+ 8 + traits::X0,tu.ext((tu.sub(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))),32,false)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2714,16 +2786,17 @@ private: return returnValue; } - /* instruction 71: CXOR */ - compile_ret_t __cxor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CXOR_{:#010x}:", pc.val); + /* instruction 71: C__XOR */ + compile_ret_t __c__xor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__XOR_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,71); + uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cxor"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__xor"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2740,16 +2813,17 @@ private: return returnValue; } - /* instruction 72: COR */ - compile_ret_t __cor(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("COR_{:#010x}:", pc.val); + /* instruction 72: C__OR */ + compile_ret_t __c__or(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__OR_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,72); + uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cor"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__or"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2766,16 +2840,17 @@ private: return returnValue; } - /* instruction 73: CAND */ - compile_ret_t __cand(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CAND_{:#010x}:", pc.val); + /* instruction 73: C__AND */ + compile_ret_t __c__and(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__AND_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,73); + uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cand"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__and"), fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2))); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2792,15 +2867,16 @@ private: return returnValue; } - /* instruction 74: CJ */ - compile_ret_t __cj(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CJ_{:#010x}:", pc.val); + /* instruction 74: C__J */ + compile_ret_t __c__j(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__J_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,74); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "cj"), + "{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c__j"), fmt::arg("imm", imm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2808,7 +2884,7 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<12>(imm),16))),32,true),32); + auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<12>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); auto returnValue = std::make_tuple(BRANCH); @@ -2819,16 +2895,17 @@ private: return returnValue; } - /* instruction 75: CBEQZ */ - compile_ret_t __cbeqz(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CBEQZ_{:#010x}:", pc.val); + /* instruction 75: C__BEQZ */ + compile_ret_t __c__beqz(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__BEQZ_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,75); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbeqz"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__beqz"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2837,7 +2914,7 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,8))); - auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16))),32,true),32); + auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<9>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); @@ -2849,16 +2926,17 @@ private: return returnValue; } - /* instruction 76: CBNEZ */ - compile_ret_t __cbnez(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CBNEZ_{:#010x}:", pc.val); + /* instruction 76: C__BNEZ */ + compile_ret_t __c__bnez(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__BNEZ_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,76); + uint64_t PC = pc.val; uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "cbnez"), + "{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c__bnez"), fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2867,7 +2945,7 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,8))); - auto PC_val_v = tu.assignment("PC_val", tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant((int16_t)sext<9>(imm),16))),32,true),32); + auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<9>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); @@ -2879,16 +2957,17 @@ private: return returnValue; } - /* instruction 77: CSLLI */ - compile_ret_t __cslli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSLLI_{:#010x}:", pc.val); + /* instruction 77: C__SLLI */ + compile_ret_t __c__slli(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__SLLI_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,77); + uint64_t PC = pc.val; uint8_t nzuimm = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "c__slli"), fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2912,16 +2991,17 @@ private: return returnValue; } - /* instruction 78: CLWSP */ - compile_ret_t __clwsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CLWSP_{:#010x}:", pc.val); + /* instruction 78: C__LWSP */ + compile_ret_t __c__lwsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__LWSP_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,78); + uint64_t PC = pc.val; uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "clwsp"), + "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c__lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2933,8 +3013,8 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto offs = tu.assignment(tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); - tu.store(rd + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,false),32,true)); + auto offs = tu.assignment(tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8))),32,false),32); + tu.store(rd + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,true),32,false)); } auto returnValue = std::make_tuple(CONT); @@ -2944,16 +3024,17 @@ private: return returnValue; } - /* instruction 79: CMV */ - compile_ret_t __cmv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CMV_{:#010x}:", pc.val); + /* instruction 79: C__MV */ + compile_ret_t __c__mv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__MV_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,79); + uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cmv"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__mv"), fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2977,15 +3058,16 @@ private: return returnValue; } - /* instruction 80: CJR */ - compile_ret_t __cjr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CJR_{:#010x}:", pc.val); + /* instruction 80: C__JR */ + compile_ret_t __c__jr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__JR_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,80); + uint64_t PC = pc.val; uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjr"), + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c__jr"), fmt::arg("rs1", name(rs1))); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -2993,10 +3075,10 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - if(rs1&&rs1(traits:: RFS)) { - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0),tu.constant(~ 0x1,8)),32); - tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); + if(rs1&&rs1(traits:: RFS)){ auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0),addr_mask),32); + tu.store(traits::NEXT_PC, PC_val_v); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -3013,6 +3095,7 @@ private: compile_ret_t ____reserved_cmv(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("__reserved_cmv_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,81); + uint64_t PC = pc.val; if(this->disass_enabled){ /* generate console output when executing the command */ tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "__reserved_cmv"); @@ -3030,16 +3113,17 @@ private: return returnValue; } - /* instruction 82: CADD */ - compile_ret_t __cadd(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CADD_{:#010x}:", pc.val); + /* instruction 82: C__ADD */ + compile_ret_t __c__add(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__ADD_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,82); + uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "cadd"), + "{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c__add"), fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2))); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -3052,7 +3136,7 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rd+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,true)); + tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rd+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -3063,15 +3147,16 @@ private: return returnValue; } - /* instruction 83: CJALR */ - compile_ret_t __cjalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CJALR_{:#010x}:", pc.val); + /* instruction 83: C__JALR */ + compile_ret_t __c__jalr(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__JALR_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,83); + uint64_t PC = pc.val; uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "cjalr"), + "{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c__jalr"), fmt::arg("rs1", name(rs1))); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -3083,9 +3168,10 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ + auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); auto new_pc = tu.assignment(tu.load(rs1+ traits::X0, 0),32); - tu.store(1 + traits::X0,tu.ext((tu.add(tu.ext(cur_pc_val,32,false),tu.constant( 2,8))),32,true)); - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,tu.constant(~ 0x1,8)),32); + tu.store(1 + traits::X0,tu.constant((uint32_t)(PC+ 2),32)); + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,addr_mask),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -3097,13 +3183,14 @@ private: return returnValue; } - /* instruction 84: CEBREAK */ - compile_ret_t __cebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CEBREAK_{:#010x}:", pc.val); + /* instruction 84: C__EBREAK */ + compile_ret_t __c__ebreak(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__EBREAK_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,84); + uint64_t PC = pc.val; if(this->disass_enabled){ /* generate console output when executing the command */ - tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "cebreak"); + tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "c__ebreak"); } auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]); pc=pc+ 2; @@ -3118,16 +3205,17 @@ private: return returnValue; } - /* instruction 85: CSWSP */ - compile_ret_t __cswsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ - tu("CSWSP_{:#010x}:", pc.val); + /* instruction 85: C__SWSP */ + compile_ret_t __c__swsp(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ + tu("C__SWSP_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,85); + uint64_t PC = pc.val; uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "cswsp"), + "{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c__swsp"), fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm)); tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic); } @@ -3139,8 +3227,8 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto offs = tu.assignment(tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8))),32,true),32); - tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ traits::X0, 0),32,true)); + auto offs = tu.assignment(tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8))),32,false),32); + tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ traits::X0, 0),32,false)); } auto returnValue = std::make_tuple(CONT); @@ -3154,6 +3242,7 @@ private: compile_ret_t __dii(virt_addr_t& pc, code_word_t instr, tu_builder& tu){ tu("DII_{:#010x}:", pc.val); vm_base::gen_sync(tu, PRE_SYNC,86); + uint64_t PC = pc.val; if(this->disass_enabled){ /* generate console output when executing the command */ tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, "dii"); From 633c0d21a000c70ec2010231ed297c129b929f0f Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Wed, 20 Sep 2023 15:17:43 +0200 Subject: [PATCH 143/184] Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop --- CMakeLists.txt | 4 +++- gen_input/templates/CORENAME.h.gtl | 4 ++-- src/iss/arch/tgc5c.h | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 008c6b0..18eb42d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,9 @@ target_force_link_libraries(${PROJECT_NAME} PRIVATE dbt-rise-core) get_target_property(DBT_CORE_INCL dbt-rise-core INTERFACE_INCLUDE_DIRECTORIES) target_include_directories(${PROJECT_NAME} INTERFACE ${DBT_CORE_INCL}) get_target_property(DBT_CORE_DEFS dbt-rise-core INTERFACE_COMPILE_DEFINITIONS) -target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS}) +if(NOT (DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND)) + target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS}) +endif() target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine) if(TARGET jsoncpp::jsoncpp) diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 96ba762..7d3a38c 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -76,10 +76,10 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { constexpr static char const* const core_type = "${coreDef.name}"; static constexpr std::array reg_names{ - {"${registers.collect{it.name}.join('", "')}"}}; + {"${registers.collect{it.name.toLowerCase()}.join('", "')}"}}; static constexpr std::array reg_aliases{ - {"${registers.collect{it.alias}.join('", "')}"}}; + {"${registers.collect{it.alias.toLowerCase()}.join('", "')}"}}; enum constants {${constants.collect{c -> c.name+"="+getCString(c.value)}.join(', ')}}; diff --git a/src/iss/arch/tgc5c.h b/src/iss/arch/tgc5c.h index 0741e4a..2dddbb3 100644 --- a/src/iss/arch/tgc5c.h +++ b/src/iss/arch/tgc5c.h @@ -48,10 +48,10 @@ template <> struct traits { constexpr static char const* const core_type = "TGC5C"; static constexpr std::array reg_names{ - {"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", "X29", "X30", "X31", "PC", "NEXT_PC", "PRIV", "DPC"}}; + {"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", "next_pc", "priv", "dpc"}}; static constexpr std::array reg_aliases{ - {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "PC", "NEXT_PC", "PRIV", "DPC"}}; + {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}}; enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL}; From f74f98f3618adb5d99c9adf68563cf7e9dbd3dd9 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Fri, 22 Sep 2023 12:40:12 +0200 Subject: [PATCH 144/184] improves readability --- src/vm/tcc/vm_tgc5c.cpp | 450 ++++++++++++++++++++++++++++++---------- 1 file changed, 344 insertions(+), 106 deletions(-) diff --git a/src/vm/tcc/vm_tgc5c.cpp b/src/vm/tcc/vm_tgc5c.cpp index 36e5ad8..5e93d1a 100644 --- a/src/vm/tcc/vm_tgc5c.cpp +++ b/src/vm/tcc/vm_tgc5c.cpp @@ -350,7 +350,8 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.constant((uint32_t)((int32_t)imm),32)); + tu.store(rd + traits::X0, + tu.constant((uint32_t)((int32_t)imm),32)); } } auto returnValue = std::make_tuple(CONT); @@ -384,7 +385,8 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.constant((uint32_t)(PC+(int32_t)imm),32)); + tu.store(rd + traits::X0, + tu.constant((uint32_t)(PC+(int32_t)imm),32)); } } auto returnValue = std::make_tuple(CONT); @@ -421,7 +423,8 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.constant((uint32_t)(PC+ 4),32)); + tu.store(rd + traits::X0, + tu.constant((uint32_t)(PC+ 4),32)); } auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int32_t)sext<21>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); @@ -460,12 +463,19 @@ private: } else{ auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); - auto new_pc = tu.assignment(tu.ext((tu.bitwise_and((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),addr_mask)),32,false),32); - tu.open_if(tu.srem(new_pc,tu.constant(static_cast(traits:: INSTR_ALIGNMENT),32))); + auto new_pc = tu.assignment(tu.ext((tu.bitwise_and( + (tu.add( + tu.load(rs1+ traits::X0, 0), + tu.constant((int16_t)sext<12>(imm),16))), + addr_mask)),32,false),32); + tu.open_if(tu.urem( + new_pc, + tu.constant(static_cast(traits:: INSTR_ALIGNMENT),32))); this->gen_raise_trap(tu, 0, 0); tu.open_else(); if(rd!= 0) { - tu.store(rd + traits::X0,tu.constant((uint32_t)(PC+ 4),32)); + tu.store(rd + traits::X0, + tu.constant((uint32_t)(PC+ 4),32)); } auto PC_val_v = tu.assignment("PC_val", new_pc,32); tu.store(traits::NEXT_PC, PC_val_v); @@ -503,7 +513,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.open_if(tu.icmp(ICmpInst::ICMP_EQ, + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))); if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ @@ -544,7 +556,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.open_if(tu.icmp(ICmpInst::ICMP_NE, + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))); if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ @@ -585,7 +599,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true))); + tu.open_if(tu.icmp(ICmpInst::ICMP_SLT, + tu.ext(tu.load(rs1+ traits::X0, 0),32,true), + tu.ext(tu.load(rs2+ traits::X0, 0),32,true))); if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ @@ -626,7 +642,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_SGE,tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true))); + tu.open_if(tu.icmp(ICmpInst::ICMP_SGE, + tu.ext(tu.load(rs1+ traits::X0, 0),32,true), + tu.ext(tu.load(rs2+ traits::X0, 0),32,true))); if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ @@ -667,7 +685,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.open_if(tu.icmp(ICmpInst::ICMP_ULT, + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))); if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ @@ -708,7 +728,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_SGE,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.open_if(tu.icmp(ICmpInst::ICMP_UGE, + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))); if(imm%static_cast(traits:: INSTR_ALIGNMENT)){ this->gen_raise_trap(tu, 0, 0); } else{ @@ -749,10 +771,13 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + auto load_address = tu.assignment(tu.ext((tu.add( + tu.load(rs1+ traits::X0, 0), + tu.constant((int16_t)sext<12>(imm),16))),32,false),32); auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 8),8,true),8); if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext(res,32,false)); + tu.store(rd + traits::X0, + tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -786,10 +811,13 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + auto load_address = tu.assignment(tu.ext((tu.add( + tu.load(rs1+ traits::X0, 0), + tu.constant((int16_t)sext<12>(imm),16))),32,false),32); auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 16),16,true),16); if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext(res,32,false)); + tu.store(rd + traits::X0, + tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -823,10 +851,13 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + auto load_address = tu.assignment(tu.ext((tu.add( + tu.load(rs1+ traits::X0, 0), + tu.constant((int16_t)sext<12>(imm),16))),32,false),32); auto res = tu.assignment(tu.ext(tu.read_mem(traits::MEM, load_address, 32),32,true),32); if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext(res,32,false)); + tu.store(rd + traits::X0, + tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -860,10 +891,13 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + auto load_address = tu.assignment(tu.ext((tu.add( + tu.load(rs1+ traits::X0, 0), + tu.constant((int16_t)sext<12>(imm),16))),32,false),32); auto res = tu.assignment(tu.read_mem(traits::MEM, load_address, 8),8); if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext(res,32,false)); + tu.store(rd + traits::X0, + tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -897,10 +931,13 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto load_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + auto load_address = tu.assignment(tu.ext((tu.add( + tu.load(rs1+ traits::X0, 0), + tu.constant((int16_t)sext<12>(imm),16))),32,false),32); auto res = tu.assignment(tu.read_mem(traits::MEM, load_address, 16),16); if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext(res,32,false)); + tu.store(rd + traits::X0, + tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -934,7 +971,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + auto store_address = tu.assignment(tu.ext((tu.add( + tu.load(rs1+ traits::X0, 0), + tu.constant((int16_t)sext<12>(imm),16))),32,false),32); tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),8,false)); } auto returnValue = std::make_tuple(CONT); @@ -968,7 +1007,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + auto store_address = tu.assignment(tu.ext((tu.add( + tu.load(rs1+ traits::X0, 0), + tu.constant((int16_t)sext<12>(imm),16))),32,false),32); tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),16,false)); } auto returnValue = std::make_tuple(CONT); @@ -1002,7 +1043,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto store_address = tu.assignment(tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false),32); + auto store_address = tu.assignment(tu.ext((tu.add( + tu.load(rs1+ traits::X0, 0), + tu.constant((int16_t)sext<12>(imm),16))),32,false),32); tu.write_mem(traits::MEM, store_address, tu.ext(tu.load(rs2+ traits::X0, 0),32,false)); } auto returnValue = std::make_tuple(CONT); @@ -1037,7 +1080,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int16_t)sext<12>(imm),16))),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.add( + tu.load(rs1+ traits::X0, 0), + tu.constant((int16_t)sext<12>(imm),16))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -1072,7 +1118,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.constant((int16_t)sext<12>(imm),16))), tu.constant( 1,8),tu.constant( 0,8))); + tu.store(rd + traits::X0, + tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT, + tu.ext(tu.load(rs1+ traits::X0, 0),32,true), + tu.constant((int16_t)sext<12>(imm),16))), tu.constant( 1,8),tu.constant( 0,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1107,7 +1156,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))), tu.constant( 1,8),tu.constant( 0,8))); + tu.store(rd + traits::X0, + tu.conditionalAssignment((tu.icmp(ICmpInst::ICMP_ULT, + tu.load(rs1+ traits::X0, 0), + tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))), tu.constant( 1,8),tu.constant( 0,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1142,7 +1194,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.bitwise_xor(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); + tu.store(rd + traits::X0, + tu.bitwise_xor( + tu.load(rs1+ traits::X0, 0), + tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); } } auto returnValue = std::make_tuple(CONT); @@ -1177,7 +1232,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.bitwise_or(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); + tu.store(rd + traits::X0, + tu.bitwise_or( + tu.load(rs1+ traits::X0, 0), + tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); } } auto returnValue = std::make_tuple(CONT); @@ -1212,7 +1270,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.bitwise_and(tu.load(rs1+ traits::X0, 0),tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); + tu.store(rd + traits::X0, + tu.bitwise_and( + tu.load(rs1+ traits::X0, 0), + tu.constant((uint32_t)((int16_t)sext<12>(imm)),32))); } } auto returnValue = std::make_tuple(CONT); @@ -1247,7 +1308,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),tu.constant(shamt,8))); + tu.store(rd + traits::X0, + tu.shl( + tu.load(rs1+ traits::X0, 0), + tu.constant(shamt,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1282,7 +1346,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ashr(tu.load(rs1+ traits::X0, 0),tu.constant(shamt,8))); + tu.store(rd + traits::X0, + tu.lshr( + tu.load(rs1+ traits::X0, 0), + tu.constant(shamt,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1317,7 +1384,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.ashr(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.constant(shamt,8))),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.ashr( + tu.ext(tu.load(rs1+ traits::X0, 0),32,true), + tu.constant(shamt,8))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -1352,7 +1422,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.add( + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -1387,7 +1460,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.sub(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.sub( + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -1422,7 +1498,12 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); + tu.store(rd + traits::X0, + tu.shl( + tu.load(rs1+ traits::X0, 0), + (tu.bitwise_and( + tu.load(rs2+ traits::X0, 0), + tu.constant((static_cast(traits:: XLEN)- 1),64))))); } } auto returnValue = std::make_tuple(CONT); @@ -1457,7 +1538,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.ext(tu.load(rs1+ traits::X0, 0),32,false),tu.ext(tu.load(rs2+ traits::X0, 0),32,false)), tu.constant( 1,8),tu.constant( 0,8))); + tu.store(rd + traits::X0, + tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT, + tu.ext(tu.load(rs1+ traits::X0, 0),32,true), + tu.ext(tu.load(rs2+ traits::X0, 0),32,true)), tu.constant( 1,8),tu.constant( 0,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1492,7 +1576,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_SLT,tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0)), tu.constant( 1,8),tu.constant( 0,8))); + tu.store(rd + traits::X0, + tu.conditionalAssignment(tu.icmp(ICmpInst::ICMP_ULT, + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0)), tu.constant( 1,8),tu.constant( 0,8))); } } auto returnValue = std::make_tuple(CONT); @@ -1527,7 +1614,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.bitwise_xor(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.store(rd + traits::X0, + tu.bitwise_xor( + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))); } } auto returnValue = std::make_tuple(CONT); @@ -1562,7 +1652,12 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ashr(tu.load(rs1+ traits::X0, 0),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))); + tu.store(rd + traits::X0, + tu.lshr( + tu.load(rs1+ traits::X0, 0), + (tu.bitwise_and( + tu.load(rs2+ traits::X0, 0), + tu.constant((static_cast(traits:: XLEN)- 1),64))))); } } auto returnValue = std::make_tuple(CONT); @@ -1597,7 +1692,12 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.ashr(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),(tu.bitwise_and(tu.load(rs2+ traits::X0, 0),tu.constant((static_cast(traits:: XLEN)- 1),64))))),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.ashr( + tu.ext(tu.load(rs1+ traits::X0, 0),32,true), + (tu.bitwise_and( + tu.load(rs2+ traits::X0, 0), + tu.constant((static_cast(traits:: XLEN)- 1),64))))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -1632,7 +1732,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.bitwise_or(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.store(rd + traits::X0, + tu.bitwise_or( + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))); } } auto returnValue = std::make_tuple(CONT); @@ -1667,7 +1770,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.bitwise_and(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.store(rd + traits::X0, + tu.bitwise_and( + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))); } } auto returnValue = std::make_tuple(CONT); @@ -1822,7 +1928,8 @@ private: auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); if(rd!= 0){ auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); tu.write_mem(traits::CSR, csr, xrs1); - tu.store(rd + traits::X0,xrd); + tu.store(rd + traits::X0, + xrd); } else{ tu.write_mem(traits::CSR, csr, xrs1); @@ -1862,10 +1969,13 @@ private: auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); if(rs1!= 0) { - tu.write_mem(traits::CSR, csr, tu.bitwise_or(xrd,xrs1)); + tu.write_mem(traits::CSR, csr, tu.bitwise_or( + xrd, + xrs1)); } if(rd!= 0) { - tu.store(rd + traits::X0,xrd); + tu.store(rd + traits::X0, + xrd); } } auto returnValue = std::make_tuple(CONT); @@ -1902,10 +2012,13 @@ private: auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); auto xrs1 = tu.assignment(tu.load(rs1+ traits::X0, 0),32); if(rs1!= 0) { - tu.write_mem(traits::CSR, csr, tu.bitwise_and(xrd,tu.logical_neg(xrs1))); + tu.write_mem(traits::CSR, csr, tu.bitwise_and( + xrd, + tu.logical_neg(xrs1))); } if(rd!= 0) { - tu.store(rd + traits::X0,xrd); + tu.store(rd + traits::X0, + xrd); } } auto returnValue = std::make_tuple(CONT); @@ -1942,7 +2055,8 @@ private: auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); tu.write_mem(traits::CSR, csr, tu.constant((uint32_t)zimm,32)); if(rd!= 0) { - tu.store(rd + traits::X0,xrd); + tu.store(rd + traits::X0, + xrd); } } auto returnValue = std::make_tuple(CONT); @@ -1978,10 +2092,13 @@ private: else{ auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); if(zimm!= 0) { - tu.write_mem(traits::CSR, csr, tu.bitwise_or(xrd,tu.constant((uint32_t)zimm,32))); + tu.write_mem(traits::CSR, csr, tu.bitwise_or( + xrd, + tu.constant((uint32_t)zimm,32))); } if(rd!= 0) { - tu.store(rd + traits::X0,xrd); + tu.store(rd + traits::X0, + xrd); } } auto returnValue = std::make_tuple(CONT); @@ -2017,10 +2134,13 @@ private: else{ auto xrd = tu.assignment(tu.read_mem(traits::CSR, csr, 32),32); if(zimm!= 0) { - tu.write_mem(traits::CSR, csr, tu.bitwise_and(xrd,tu.constant(~ ((uint32_t)zimm),32))); + tu.write_mem(traits::CSR, csr, tu.bitwise_and( + xrd, + tu.constant(~ ((uint32_t)zimm),32))); } if(rd!= 0) { - tu.store(rd + traits::X0,xrd); + tu.store(rd + traits::X0, + xrd); } } auto returnValue = std::make_tuple(CONT); @@ -2082,9 +2202,12 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),64,true),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,false),64,true))),64,true),64); + auto res = tu.assignment(tu.ext((tu.mul( + tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,true), + tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,true))),64,true),64); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext(res,32,false)); + tu.store(rd + traits::X0, + tu.ext(res,32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2118,9 +2241,14 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),64,true),tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,false),64,true))),64,true),64); + auto res = tu.assignment(tu.ext((tu.mul( + tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,true), + tu.ext(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),64,true))),64,true),64); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext((tu.ashr(res,tu.constant(static_cast(traits:: XLEN),32))),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.ashr( + res, + tu.constant(static_cast(traits:: XLEN),32))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2154,9 +2282,14 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,false),64,true),tu.ext(tu.load(rs2+ traits::X0, 0),64,false))),64,true),64); + auto res = tu.assignment(tu.ext((tu.mul( + tu.ext(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),64,true), + tu.ext(tu.load(rs2+ traits::X0, 0),64,false))),64,true),64); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext((tu.ashr(res,tu.constant(static_cast(traits:: XLEN),32))),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.ashr( + res, + tu.constant(static_cast(traits:: XLEN),32))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2190,9 +2323,14 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto res = tu.assignment(tu.ext((tu.mul(tu.ext(tu.load(rs1+ traits::X0, 0),64,false),tu.ext(tu.load(rs2+ traits::X0, 0),64,false))),64,false),64); + auto res = tu.assignment(tu.ext((tu.mul( + tu.ext(tu.load(rs1+ traits::X0, 0),64,false), + tu.ext(tu.load(rs2+ traits::X0, 0),64,false))),64,false),64); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext((tu.ashr(res,tu.constant(static_cast(traits:: XLEN),32))),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.lshr( + res, + tu.constant(static_cast(traits:: XLEN),32))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2228,15 +2366,28 @@ private: else{ auto dividend = tu.assignment(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),32); auto divisor = tu.assignment(tu.ext(tu.load(rs2+ traits::X0, 0),32,true),32); - if(rd!= 0){ tu.open_if(tu.icmp(ICmpInst::ICMP_NE,divisor,tu.constant( 0,8))); + if(rd!= 0){ tu.open_if(tu.icmp(ICmpInst::ICMP_NE, + divisor, + tu.constant( 0,8))); auto MMIN = tu.assignment(tu.constant(((uint32_t)1)<<(static_cast(traits:: XLEN)-1),32),32); - tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,divisor,tu.constant(- 1,8)))); - tu.store(rd + traits::X0,MMIN); + tu.open_if(tu.logical_and( + tu.icmp(ICmpInst::ICMP_EQ, + tu.load(rs1+ traits::X0, 0), + MMIN), + tu.icmp(ICmpInst::ICMP_EQ, + divisor, + tu.constant(- 1,8)))); + tu.store(rd + traits::X0, + MMIN); tu.open_else(); - tu.store(rd + traits::X0,tu.ext((tu.sdiv(dividend,divisor)),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.sdiv( + dividend, + divisor)),32,false)); tu.close_scope(); tu.open_else(); - tu.store(rd + traits::X0,tu.constant((uint32_t)- 1,32)); + tu.store(rd + traits::X0, + tu.constant((uint32_t)- 1,32)); tu.close_scope(); } } @@ -2271,13 +2422,19 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,8))); + tu.open_if(tu.icmp(ICmpInst::ICMP_NE, + tu.load(rs2+ traits::X0, 0), + tu.constant( 0,8))); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext((tu.sdiv(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.udiv( + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))),32,false)); } tu.open_else(); if(rd!=0) { - tu.store(rd + traits::X0,tu.constant((uint32_t)- 1,32)); + tu.store(rd + traits::X0, + tu.constant((uint32_t)- 1,32)); } tu.close_scope(); } @@ -2312,20 +2469,33 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,8))); + tu.open_if(tu.icmp(ICmpInst::ICMP_NE, + tu.load(rs2+ traits::X0, 0), + tu.constant( 0,8))); auto MMIN = tu.assignment(tu.constant((uint32_t)1<<(static_cast(traits:: XLEN)-1),32),32); - tu.open_if(tu.logical_and(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ traits::X0, 0),MMIN),tu.icmp(ICmpInst::ICMP_EQ,tu.ext(tu.load(rs2+ traits::X0, 0),32,true),tu.constant(- 1,8)))); + tu.open_if(tu.logical_and( + tu.icmp(ICmpInst::ICMP_EQ, + tu.load(rs1+ traits::X0, 0), + MMIN), + tu.icmp(ICmpInst::ICMP_EQ, + tu.ext(tu.load(rs2+ traits::X0, 0),32,true), + tu.constant(- 1,8)))); if(rd!=0) { - tu.store(rd + traits::X0,tu.constant( 0,8)); + tu.store(rd + traits::X0, + tu.constant( 0,8)); } tu.open_else(); if(rd!=0) { - tu.store(rd + traits::X0,tu.ext((tu.srem(tu.ext(tu.load(rs1+ traits::X0, 0),32,true),tu.ext(tu.load(rs2+ traits::X0, 0),32,true))),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.srem( + tu.ext(tu.load(rs1+ traits::X0, 0),32,true), + tu.ext(tu.load(rs2+ traits::X0, 0),32,true))),32,false)); } tu.close_scope(); tu.open_else(); if(rd!=0) { - tu.store(rd + traits::X0,tu.load(rs1+ traits::X0, 0)); + tu.store(rd + traits::X0, + tu.load(rs1+ traits::X0, 0)); } tu.close_scope(); } @@ -2360,13 +2530,19 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs2+ traits::X0, 0),tu.constant( 0,8))); + tu.open_if(tu.icmp(ICmpInst::ICMP_NE, + tu.load(rs2+ traits::X0, 0), + tu.constant( 0,8))); if(rd!=0) { - tu.store(rd + traits::X0,tu.srem(tu.load(rs1+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))); + tu.store(rd + traits::X0, + tu.urem( + tu.load(rs1+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))); } tu.open_else(); if(rd!=0) { - tu.store(rd + traits::X0,tu.load(rs1+ traits::X0, 0)); + tu.store(rd + traits::X0, + tu.load(rs1+ traits::X0, 0)); } tu.close_scope(); } @@ -2397,7 +2573,10 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(imm) { - tu.store(rd+ 8 + traits::X0,tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(imm,16))),32,false)); + tu.store(rd+ 8 + traits::X0, + tu.ext((tu.add( + tu.load(2+ traits::X0, 0), + tu.constant(imm,16))),32,false)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -2429,8 +2608,11 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,false),32); - tu.store(rd+ 8 + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,true),32,false)); + auto offs = tu.assignment(tu.ext((tu.add( + tu.load(rs1+ 8+ traits::X0, 0), + tu.constant(uimm,8))),32,false),32); + tu.store(rd+ 8 + traits::X0, + tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,true),32,false)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2458,7 +2640,9 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - auto offs = tu.assignment(tu.ext((tu.add(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(uimm,8))),32,false),32); + auto offs = tu.assignment(tu.ext((tu.add( + tu.load(rs1+ 8+ traits::X0, 0), + tu.constant(uimm,8))),32,false),32); tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ 8+ traits::X0, 0),32,false)); auto returnValue = std::make_tuple(CONT); @@ -2491,7 +2675,10 @@ private: } else{ if(rs1!= 0) { - tu.store(rs1 + traits::X0,tu.ext((tu.add(tu.load(rs1+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))),32,false)); + tu.store(rs1 + traits::X0, + tu.ext((tu.add( + tu.load(rs1+ traits::X0, 0), + tu.constant((int8_t)sext<6>(imm),8))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2541,7 +2728,8 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(1 + traits::X0,tu.constant((uint32_t)(PC+ 2),32)); + tu.store(1 + traits::X0, + tu.constant((uint32_t)(PC+ 2),32)); auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<12>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); @@ -2576,7 +2764,8 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.constant((uint32_t)((int8_t)sext<6>(imm)),32)); + tu.store(rd + traits::X0, + tu.constant((uint32_t)((int8_t)sext<6>(imm)),32)); } } auto returnValue = std::make_tuple(CONT); @@ -2609,7 +2798,8 @@ private: this->gen_raise_trap(tu, 0, 2); } if(rd!= 0) { - tu.store(rd + traits::X0,tu.constant((uint32_t)((int32_t)sext<18>(imm)),32)); + tu.store(rd + traits::X0, + tu.constant((uint32_t)((int32_t)sext<18>(imm)),32)); } auto returnValue = std::make_tuple(CONT); @@ -2637,7 +2827,10 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(nzimm) { - tu.store(2 + traits::X0,tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant((int16_t)sext<10>(nzimm),16))),32,false)); + tu.store(2 + traits::X0, + tu.ext((tu.add( + tu.load(2+ traits::X0, 0), + tu.constant((int16_t)sext<10>(nzimm),16))),32,false)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -2691,7 +2884,10 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(rs1+ 8 + traits::X0,tu.ashr(tu.load(rs1+ 8+ traits::X0, 0),tu.constant(shamt,8))); + tu.store(rs1+ 8 + traits::X0, + tu.lshr( + tu.load(rs1+ 8+ traits::X0, 0), + tu.constant(shamt,8))); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2718,10 +2914,16 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - if(shamt){ tu.store(rs1+ 8 + traits::X0,tu.ext((tu.ashr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,true)),tu.constant(shamt,8))),32,false)); + if(shamt){ tu.store(rs1+ 8 + traits::X0, + tu.ext((tu.ashr( + (tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,true)), + tu.constant(shamt,8))),32,false)); } else{ - if(static_cast(traits:: XLEN)== 128){ tu.store(rs1+ 8 + traits::X0,tu.ext((tu.ashr((tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,true)),tu.constant( 64,8))),32,false)); + if(static_cast(traits:: XLEN)== 128){ tu.store(rs1+ 8 + traits::X0, + tu.ext((tu.ashr( + (tu.ext(tu.load(rs1+ 8+ traits::X0, 0),32,true)), + tu.constant( 64,8))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -2750,7 +2952,10 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(rs1+ 8 + traits::X0,tu.ext((tu.bitwise_and(tu.load(rs1+ 8+ traits::X0, 0),tu.constant((int8_t)sext<6>(imm),8))),32,false)); + tu.store(rs1+ 8 + traits::X0, + tu.ext((tu.bitwise_and( + tu.load(rs1+ 8+ traits::X0, 0), + tu.constant((int8_t)sext<6>(imm),8))),32,false)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2777,7 +2982,10 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(rd+ 8 + traits::X0,tu.ext((tu.sub(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))),32,false)); + tu.store(rd+ 8 + traits::X0, + tu.ext((tu.sub( + tu.load(rd+ 8+ traits::X0, 0), + tu.load(rs2+ 8+ traits::X0, 0))),32,false)); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2804,7 +3012,10 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(rd+ 8 + traits::X0,tu.bitwise_xor(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); + tu.store(rd+ 8 + traits::X0, + tu.bitwise_xor( + tu.load(rd+ 8+ traits::X0, 0), + tu.load(rs2+ 8+ traits::X0, 0))); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2831,7 +3042,10 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(rd+ 8 + traits::X0,tu.bitwise_or(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); + tu.store(rd+ 8 + traits::X0, + tu.bitwise_or( + tu.load(rd+ 8+ traits::X0, 0), + tu.load(rs2+ 8+ traits::X0, 0))); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2858,7 +3072,10 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.store(rd+ 8 + traits::X0,tu.bitwise_and(tu.load(rd+ 8+ traits::X0, 0),tu.load(rs2+ 8+ traits::X0, 0))); + tu.store(rd+ 8 + traits::X0, + tu.bitwise_and( + tu.load(rd+ 8+ traits::X0, 0), + tu.load(rs2+ 8+ traits::X0, 0))); auto returnValue = std::make_tuple(CONT); tu.close_scope(); @@ -2913,7 +3130,9 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.open_if(tu.icmp(ICmpInst::ICMP_EQ,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,8))); + tu.open_if(tu.icmp(ICmpInst::ICMP_EQ, + tu.load(rs1+ 8+ traits::X0, 0), + tu.constant( 0,8))); auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<9>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); @@ -2944,7 +3163,9 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - tu.open_if(tu.icmp(ICmpInst::ICMP_NE,tu.load(rs1+ 8+ traits::X0, 0),tu.constant( 0,8))); + tu.open_if(tu.icmp(ICmpInst::ICMP_NE, + tu.load(rs1+ 8+ traits::X0, 0), + tu.constant( 0,8))); auto PC_val_v = tu.assignment("PC_val", (uint32_t)(PC+(int16_t)sext<9>(imm)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); @@ -2980,7 +3201,10 @@ private: } else{ if(rs1!= 0) { - tu.store(rs1 + traits::X0,tu.shl(tu.load(rs1+ traits::X0, 0),tu.constant(nzuimm,8))); + tu.store(rs1 + traits::X0, + tu.shl( + tu.load(rs1+ traits::X0, 0), + tu.constant(nzuimm,8))); } } auto returnValue = std::make_tuple(CONT); @@ -3013,8 +3237,11 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto offs = tu.assignment(tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8))),32,false),32); - tu.store(rd + traits::X0,tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,true),32,false)); + auto offs = tu.assignment(tu.ext((tu.add( + tu.load(2+ traits::X0, 0), + tu.constant(uimm,8))),32,false),32); + tu.store(rd + traits::X0, + tu.ext(tu.ext(tu.read_mem(traits::MEM, offs, 32),32,true),32,false)); } auto returnValue = std::make_tuple(CONT); @@ -3047,7 +3274,8 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.load(rs2+ traits::X0, 0)); + tu.store(rd + traits::X0, + tu.load(rs2+ traits::X0, 0)); } } auto returnValue = std::make_tuple(CONT); @@ -3076,7 +3304,9 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); if(rs1&&rs1(traits:: RFS)){ auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0),addr_mask),32); + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( + tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0), + addr_mask),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -3136,7 +3366,10 @@ private: } else{ if(rd!= 0) { - tu.store(rd + traits::X0,tu.ext((tu.add(tu.load(rd+ traits::X0, 0),tu.load(rs2+ traits::X0, 0))),32,false)); + tu.store(rd + traits::X0, + tu.ext((tu.add( + tu.load(rd+ traits::X0, 0), + tu.load(rs2+ traits::X0, 0))),32,false)); } } auto returnValue = std::make_tuple(CONT); @@ -3170,8 +3403,11 @@ private: else{ auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); auto new_pc = tu.assignment(tu.load(rs1+ traits::X0, 0),32); - tu.store(1 + traits::X0,tu.constant((uint32_t)(PC+ 2),32)); - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and(new_pc,addr_mask),32); + tu.store(1 + traits::X0, + tu.constant((uint32_t)(PC+ 2),32)); + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( + new_pc, + addr_mask),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -3227,7 +3463,9 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto offs = tu.assignment(tu.ext((tu.add(tu.load(2+ traits::X0, 0),tu.constant(uimm,8))),32,false),32); + auto offs = tu.assignment(tu.ext((tu.add( + tu.load(2+ traits::X0, 0), + tu.constant(uimm,8))),32,false),32); tu.write_mem(traits::MEM, offs, tu.ext(tu.load(rs2+ traits::X0, 0),32,false)); } auto returnValue = std::make_tuple(CONT); From 212fb1c8fff472723295a561dde59ab75ae069d2 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Fri, 22 Sep 2023 12:40:35 +0200 Subject: [PATCH 145/184] adds tracing functionality --- src/iss/arch/riscv_hart_m_p.h | 10 ++++--- src/iss/arch/riscv_hart_msu_vp.h | 10 ++++--- src/iss/arch/riscv_hart_mu_p.h | 10 ++++--- src/iss/plugin/README.md | 8 ++++++ src/iss/plugin/pctrace.cpp | 46 +++++++++++++++++++++----------- src/iss/plugin/pctrace.h | 11 +++++--- 6 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 src/iss/plugin/README.md diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 1481b30..935c774 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -304,9 +304,9 @@ protected: */ const std::string core_type_name() const override { return traits::core_type; } - uint64_t get_pc() override { return arch.reg.PC; }; + uint64_t get_pc() override { return arch.reg.PC; } - uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; + uint64_t get_next_pc() override { return arch.reg.NEXT_PC; } uint64_t get_instr_word() override { return arch.reg.instruction; } @@ -316,9 +316,11 @@ protected: uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } - void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; + void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; } - bool is_branch_taken() override { return arch.reg.last_branch; }; + bool is_branch_taken() override { return arch.reg.last_branch; } + + unsigned get_reg_num() override {return traits::NUM_REGS;} riscv_hart_m_p &arch; }; diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index 23a805b..ccf9e31 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -331,9 +331,9 @@ protected: */ const std::string core_type_name() const override { return traits::core_type; } - uint64_t get_pc() override { return arch.reg.PC; }; + uint64_t get_pc() override { return arch.reg.PC; } - uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; + uint64_t get_next_pc() override { return arch.reg.NEXT_PC; } uint64_t get_instr_word() override { return arch.reg.instruction; } @@ -343,9 +343,11 @@ protected: uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } - void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; + void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; } - bool is_branch_taken() override { return arch.reg.last_branch; }; + bool is_branch_taken() override { return arch.reg.last_branch; } + + unsigned get_reg_num() override {return traits::NUM_REGS; } riscv_hart_msu_vp &arch; }; diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index da30b21..48cf106 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -329,9 +329,9 @@ protected: */ const std::string core_type_name() const override { return traits::core_type; } - uint64_t get_pc() override { return arch.reg.PC; }; + uint64_t get_pc() override { return arch.reg.PC; } - uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; + uint64_t get_next_pc() override { return arch.reg.NEXT_PC; } uint64_t get_instr_word() override { return arch.reg.instruction; } @@ -341,9 +341,11 @@ protected: uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } - void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; + void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; } - bool is_branch_taken() override { return arch.reg.last_branch; }; + bool is_branch_taken() override { return arch.reg.last_branch; } + + unsigned get_reg_num() override {return traits::NUM_REGS; } riscv_hart_mu_p &arch; }; diff --git a/src/iss/plugin/README.md b/src/iss/plugin/README.md new file mode 100644 index 0000000..87f7db3 --- /dev/null +++ b/src/iss/plugin/README.md @@ -0,0 +1,8 @@ +# pctrace + +Trace functionality to allow visualizing coverage in lcov and cachegrind tools. Use environment variables NOCOMPRES and REGDUMP to toggle functionality. +- NOCOMPRES: any value turns off the LZ4 compression +- REGDUMP: any value switches to tracing the registers instead. Also turns off compression. + +Known Bugs: +- currently does not work correctly with jit backends, the plugin cant tell if instructions are compressed. Additionaly the cost of instrs that raise a trap is not known. It takes the cost of the instrid -1 (0 at the moment). diff --git a/src/iss/plugin/pctrace.cpp b/src/iss/plugin/pctrace.cpp index ea20702..97f6ee9 100644 --- a/src/iss/plugin/pctrace.cpp +++ b/src/iss/plugin/pctrace.cpp @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * Contributors: - * alex.com - initial implementation + * alex@minres.com - initial implementation ******************************************************************************/ #include @@ -55,11 +55,11 @@ using namespace rapidjson; using namespace std; #ifdef WITH_LZ4 -class lz4compress_steambuf: public std::streambuf { +class lz4compress_streambuf: public std::streambuf { public: - lz4compress_steambuf(const lz4compress_steambuf&) = delete; - lz4compress_steambuf& operator=(const lz4compress_steambuf&) = delete; - lz4compress_steambuf(std::ostream &sink, size_t buf_size) + lz4compress_streambuf(const lz4compress_streambuf&) = delete; + lz4compress_streambuf& operator=(const lz4compress_streambuf&) = delete; + lz4compress_streambuf(std::ostream &sink, size_t buf_size) : sink(sink) , src_buf(buf_size) , dest_buf(LZ4F_compressBound(buf_size, nullptr)) @@ -74,7 +74,7 @@ public: sink.write(dest_buf.data(), ret); } - ~lz4compress_steambuf() { + ~lz4compress_streambuf() { close(); } @@ -126,17 +126,21 @@ private: pctrace::pctrace(std::string const &filename) : instr_if(nullptr) , filename(filename) +, reg_dump(getenv("REGDUMP")) +, no_compres(getenv("NOCOMPRES")) , output("output.trc") #ifdef WITH_LZ4 -, strbuf(new lz4compress_steambuf(output, 4096)) +, strbuf( (no_compres || reg_dump)? nullptr: new lz4compress_streambuf(output, 4096)) , ostr(strbuf.get()) #endif -{ } +{} pctrace::~pctrace() { } bool pctrace::registration(const char *const version, vm_if& vm) { instr_if = vm.get_arch()->get_instrumentation_if(); + reg_base_ptr = reinterpret_cast(vm.get_arch()->get_regs_base_ptr()); + if(!instr_if) return false; const string core_name = instr_if->core_type_name(); if (filename.length() > 0) { @@ -203,12 +207,22 @@ void pctrace::callback(instr_info_t iinfo) { if (entry.not_taken > 1) instr_if->update_last_instr_cycles(entry.not_taken); } -#ifndef WITH_LZ4 - output<get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; -#else - auto rdbuf=ostr.rdbuf(); - ostr<get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; -#endif -} -} + if(no_compres|| reg_dump){ + if(reg_dump){ + for(size_t i=0; i< instr_if->get_reg_num(); ++i){ + uint32_t reg_val = *(reg_base_ptr+i); + output << "0x" << std::setfill('0') << std::setw(8) << std::hex << reg_val << " "; + } + output<<"\n" ; + } + else{ + output<get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; + } } +}//namespace plugin +}//namespace iss diff --git a/src/iss/plugin/pctrace.h b/src/iss/plugin/pctrace.h index 0e89110..ca5d677 100644 --- a/src/iss/plugin/pctrace.h +++ b/src/iss/plugin/pctrace.h @@ -39,11 +39,10 @@ #include "iss/instrumentation_if.h" #include #include - - +#include namespace iss { namespace plugin { -class lz4compress_steambuf; +class lz4compress_streambuf; class pctrace : public iss::vm_plugin { struct instr_delay { std::string instr_name; @@ -86,9 +85,13 @@ public: private: iss::instrumentation_if *instr_if {nullptr}; + uint32_t* reg_base_ptr {nullptr}; + bool reg_dump {false}; + bool no_compres {false}; std::ofstream output; + #ifdef WITH_LZ4 - std::unique_ptr strbuf; + std::unique_ptr strbuf; std::ostream ostr; #endif std::string filename; From 8db0cc5d0501f043325bf7a1c3433884c95bf2dd Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sat, 23 Sep 2023 10:34:58 +0200 Subject: [PATCH 146/184] removes clutter --- gen_input/templates/CORENAME_decoder.cpp.gtl | 86 --------- src/iss/arch/tgc_c_decoder.cpp | 175 ------------------- 2 files changed, 261 deletions(-) delete mode 100644 gen_input/templates/CORENAME_decoder.cpp.gtl delete mode 100644 src/iss/arch/tgc_c_decoder.cpp diff --git a/gen_input/templates/CORENAME_decoder.cpp.gtl b/gen_input/templates/CORENAME_decoder.cpp.gtl deleted file mode 100644 index 9291118..0000000 --- a/gen_input/templates/CORENAME_decoder.cpp.gtl +++ /dev/null @@ -1,86 +0,0 @@ -#include "${coreDef.name.toLowerCase()}.h" -#include -#include -#include -#include - -namespace iss { -namespace arch { -namespace { -// according to -// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation -#ifdef __GCC__ -constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); } -#elif __cplusplus < 201402L -constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); } -constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; } -#else -constexpr size_t bit_count(uint32_t u) { - size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); - return ((uCount + (uCount >> 3)) & 030707070707) % 63; -} -#endif - -using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e; - -/**************************************************************************** - * start opcode definitions - ****************************************************************************/ -struct instruction_desriptor { - size_t length; - uint32_t value; - uint32_t mask; - opcode_e op; -}; - -const std::array instr_descr = {{ - /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> - {${instr.length}, ${instr.encoding}, ${instr.mask}, opcode_e::${instr.instruction.name}},<%}%> -}}; - -} - -template<> -struct instruction_decoder<${coreDef.name.toLowerCase()}> { - using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e; - using code_word_t=traits<${coreDef.name.toLowerCase()}>::code_word_t; - - struct instruction_pattern { - uint32_t value; - uint32_t mask; - opcode_e id; - }; - - std::array, 4> qlut; - - template - unsigned decode_instruction(T); - - instruction_decoder() { - for (auto instr : instr_descr) { - auto quadrant = instr.value & 0x3; - qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); - } - for(auto& lut: qlut){ - std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ - return bit_count(a.mask) < bit_count(b.mask); - }); - } - } -}; - -template<> -unsigned instruction_decoder<${coreDef.name.toLowerCase()}>::decode_instruction::code_word_t>(traits<${coreDef.name.toLowerCase()}>::code_word_t instr){ - auto res = std::find_if(std::begin(qlut[instr&0x3]), std::end(qlut[instr&0x3]), [instr](instruction_pattern const& e){ - return !((instr&e.mask) ^ e.value ); - }); - return static_cast(res!=std::end(qlut[instr&0x3])? res->id : opcode_e::MAX_OPCODE); -} - - -std::unique_ptr> traits<${coreDef.name.toLowerCase()}>::get_decoder(){ - return std::make_unique>(); -} - -} -} diff --git a/src/iss/arch/tgc_c_decoder.cpp b/src/iss/arch/tgc_c_decoder.cpp deleted file mode 100644 index 3526fda..0000000 --- a/src/iss/arch/tgc_c_decoder.cpp +++ /dev/null @@ -1,175 +0,0 @@ -#include "tgc_c.h" -#include -#include -#include -#include - -namespace iss { -namespace arch { -namespace { -// according to -// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation -#ifdef __GCC__ -constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); } -#elif __cplusplus < 201402L -constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); } -constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; } -#else -constexpr size_t bit_count(uint32_t u) { - size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); - return ((uCount + (uCount >> 3)) & 030707070707) % 63; -} -#endif - -using opcode_e = traits::opcode_e; - -/**************************************************************************** - * start opcode definitions - ****************************************************************************/ -struct instruction_desriptor { - size_t length; - uint32_t value; - uint32_t mask; - opcode_e op; -}; - -const std::array instr_descr = {{ - /* entries are: size, valid value, valid mask, function ptr */ - {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, opcode_e::LUI}, - {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, opcode_e::AUIPC}, - {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, opcode_e::JAL}, - {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, opcode_e::JALR}, - {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, opcode_e::BEQ}, - {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, opcode_e::BNE}, - {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, opcode_e::BLT}, - {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, opcode_e::BGE}, - {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, opcode_e::BLTU}, - {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, opcode_e::BGEU}, - {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, opcode_e::LB}, - {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, opcode_e::LH}, - {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, opcode_e::LW}, - {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, opcode_e::LBU}, - {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, opcode_e::LHU}, - {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, opcode_e::SB}, - {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, opcode_e::SH}, - {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, opcode_e::SW}, - {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, opcode_e::ADDI}, - {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, opcode_e::SLTI}, - {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, opcode_e::SLTIU}, - {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, opcode_e::XORI}, - {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, opcode_e::ORI}, - {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, opcode_e::ANDI}, - {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, opcode_e::SLLI}, - {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, opcode_e::SRLI}, - {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, opcode_e::SRAI}, - {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::ADD}, - {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::SUB}, - {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, opcode_e::SLL}, - {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, opcode_e::SLT}, - {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, opcode_e::SLTU}, - {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, opcode_e::XOR}, - {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::SRL}, - {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::SRA}, - {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, opcode_e::OR}, - {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, opcode_e::AND}, - {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, opcode_e::FENCE}, - {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, opcode_e::ECALL}, - {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, opcode_e::EBREAK}, - {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::URET}, - {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::SRET}, - {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::MRET}, - {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, opcode_e::WFI}, - {32, 0b01111011001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::DRET}, - {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRW}, - {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRS}, - {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRC}, - {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRWI}, - {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRSI}, - {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRCI}, - {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, opcode_e::FENCE_I}, - {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::MUL}, - {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, opcode_e::MULH}, - {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, opcode_e::MULHSU}, - {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, opcode_e::MULHU}, - {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, opcode_e::DIV}, - {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::DIVU}, - {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, opcode_e::REM}, - {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, opcode_e::REMU}, - {16, 0b0000000000000000, 0b1110000000000011, opcode_e::CADDI4SPN}, - {16, 0b0100000000000000, 0b1110000000000011, opcode_e::CLW}, - {16, 0b1100000000000000, 0b1110000000000011, opcode_e::CSW}, - {16, 0b0000000000000001, 0b1110000000000011, opcode_e::CADDI}, - {16, 0b0000000000000001, 0b1110111110000011, opcode_e::CNOP}, - {16, 0b0010000000000001, 0b1110000000000011, opcode_e::CJAL}, - {16, 0b0100000000000001, 0b1110000000000011, opcode_e::CLI}, - {16, 0b0110000000000001, 0b1110000000000011, opcode_e::CLUI}, - {16, 0b0110000100000001, 0b1110111110000011, opcode_e::CADDI16SP}, - {16, 0b0110000000000001, 0b1111000001111111, opcode_e::__reserved_clui}, - {16, 0b1000000000000001, 0b1111110000000011, opcode_e::CSRLI}, - {16, 0b1000010000000001, 0b1111110000000011, opcode_e::CSRAI}, - {16, 0b1000100000000001, 0b1110110000000011, opcode_e::CANDI}, - {16, 0b1000110000000001, 0b1111110001100011, opcode_e::CSUB}, - {16, 0b1000110000100001, 0b1111110001100011, opcode_e::CXOR}, - {16, 0b1000110001000001, 0b1111110001100011, opcode_e::COR}, - {16, 0b1000110001100001, 0b1111110001100011, opcode_e::CAND}, - {16, 0b1010000000000001, 0b1110000000000011, opcode_e::CJ}, - {16, 0b1100000000000001, 0b1110000000000011, opcode_e::CBEQZ}, - {16, 0b1110000000000001, 0b1110000000000011, opcode_e::CBNEZ}, - {16, 0b0000000000000010, 0b1111000000000011, opcode_e::CSLLI}, - {16, 0b0100000000000010, 0b1110000000000011, opcode_e::CLWSP}, - {16, 0b1000000000000010, 0b1111000000000011, opcode_e::CMV}, - {16, 0b1000000000000010, 0b1111000001111111, opcode_e::CJR}, - {16, 0b1000000000000010, 0b1111111111111111, opcode_e::__reserved_cmv}, - {16, 0b1001000000000010, 0b1111000000000011, opcode_e::CADD}, - {16, 0b1001000000000010, 0b1111000001111111, opcode_e::CJALR}, - {16, 0b1001000000000010, 0b1111111111111111, opcode_e::CEBREAK}, - {16, 0b1100000000000010, 0b1110000000000011, opcode_e::CSWSP}, - {16, 0b0000000000000000, 0b1111111111111111, opcode_e::DII}, -}}; - -} - -template<> -struct instruction_decoder { - using opcode_e = traits::opcode_e; - using code_word_t=traits::code_word_t; - - struct instruction_pattern { - uint32_t value; - uint32_t mask; - opcode_e id; - }; - - std::array, 4> qlut; - - template - unsigned decode_instruction(T); - - instruction_decoder() { - for (auto instr : instr_descr) { - auto quadrant = instr.value & 0x3; - qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); - } - for(auto& lut: qlut){ - std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ - return bit_count(a.mask) > bit_count(b.mask); - }); - } - } -}; - -template<> -unsigned instruction_decoder::decode_instruction::code_word_t>(traits::code_word_t instr){ - auto res = std::find_if(std::begin(qlut[instr&0x3]), std::end(qlut[instr&0x3]), [instr](instruction_pattern const& e){ - return !((instr&e.mask) ^ e.value ); - }); - return static_cast(res!=std::end(qlut[instr&0x3])? res->id : opcode_e::MAX_OPCODE); -} - - -std::unique_ptr> traits::get_decoder(){ - return std::make_unique>(); -} - -} -} From 70839bbbf2ffd76e9bb8c00edf6c4b0d361139b0 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sat, 23 Sep 2023 10:35:21 +0200 Subject: [PATCH 147/184] changes templates for correct plugin callback in case of trap --- gen_input/templates/tcc/CORENAME.cpp.gtl | 2 ++ src/vm/tcc/vm_tgc5c.cpp | 26 +++++++++++++----------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index 9900d60..1a51d40 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -305,6 +305,8 @@ template void vm_impl::gen_wait(tu_builder& tu, unsigned t } template void vm_impl::gen_trap_behavior(tu_builder& tu) { + tu("trap_entry_plugin:"); + this->gen_sync(tu, POST_SYNC, -1); tu("trap_entry:"); tu("enter_trap(core_ptr, *trap_state, *pc, 0);"); tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(),32)); diff --git a/src/vm/tcc/vm_tgc5c.cpp b/src/vm/tcc/vm_tgc5c.cpp index 5e93d1a..a94d30a 100644 --- a/src/vm/tcc/vm_tgc5c.cpp +++ b/src/vm/tcc/vm_tgc5c.cpp @@ -462,12 +462,11 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); auto new_pc = tu.assignment(tu.ext((tu.bitwise_and( (tu.add( tu.load(rs1+ traits::X0, 0), tu.constant((int16_t)sext<12>(imm),16))), - addr_mask)),32,false),32); + tu.constant(~ 0x1,8))),32,false),32); tu.open_if(tu.urem( new_pc, tu.constant(static_cast(traits:: INSTR_ALIGNMENT),32))); @@ -477,7 +476,9 @@ private: tu.store(rd + traits::X0, tu.constant((uint32_t)(PC+ 4),32)); } - auto PC_val_v = tu.assignment("PC_val", new_pc,32); + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( + new_pc, + tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); @@ -2472,7 +2473,7 @@ private: tu.open_if(tu.icmp(ICmpInst::ICMP_NE, tu.load(rs2+ traits::X0, 0), tu.constant( 0,8))); - auto MMIN = tu.assignment(tu.constant((uint32_t)1<<(static_cast(traits:: XLEN)-1),32),32); + auto MMIN = tu.assignment(tu.constant( 1<<(static_cast(traits:: XLEN)-1),8),32); tu.open_if(tu.logical_and( tu.icmp(ICmpInst::ICMP_EQ, tu.load(rs1+ traits::X0, 0), @@ -3303,12 +3304,12 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - if(rs1&&rs1(traits:: RFS)){ auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( - tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0), - addr_mask),32); - tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); + if(rs1&&rs1(traits:: RFS)) { + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( + tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0), + tu.constant(~ 0x1,8)),32); + tu.store(traits::NEXT_PC, PC_val_v); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -3401,13 +3402,12 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); auto new_pc = tu.assignment(tu.load(rs1+ traits::X0, 0),32); tu.store(1 + traits::X0, tu.constant((uint32_t)(PC+ 2),32)); auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( new_pc, - addr_mask),32); + tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -3626,6 +3626,8 @@ template void vm_impl::gen_wait(tu_builder& tu, unsigned t } template void vm_impl::gen_trap_behavior(tu_builder& tu) { + tu("trap_entry_plugin:"); + this->gen_sync(tu, POST_SYNC, -1); tu("trap_entry:"); tu("enter_trap(core_ptr, *trap_state, *pc, 0);"); tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(),32)); From 417076f8e6a7662974493e6c462660bd4443a01c Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sat, 23 Sep 2023 11:30:58 +0200 Subject: [PATCH 148/184] stops jit block creation in case of ECALL and EBREAK --- gen_input/templates/tcc/CORENAME.cpp.gtl | 5 +- src/vm/llvm/vm_tgc5c.cpp | 20 +-- src/vm/tcc/vm_tgc5c.cpp | 211 +++++++++++------------ 3 files changed, 117 insertions(+), 119 deletions(-) diff --git a/gen_input/templates/tcc/CORENAME.cpp.gtl b/gen_input/templates/tcc/CORENAME.cpp.gtl index 1a51d40..775b8e7 100644 --- a/gen_input/templates/tcc/CORENAME.cpp.gtl +++ b/gen_input/templates/tcc/CORENAME.cpp.gtl @@ -172,8 +172,8 @@ private: <%instr.behavior.eachLine{%>${it} <%}%> tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,${idx}); - gen_trap_check(tu); return returnValue; } <%}%> @@ -305,9 +305,8 @@ template void vm_impl::gen_wait(tu_builder& tu, unsigned t } template void vm_impl::gen_trap_behavior(tu_builder& tu) { - tu("trap_entry_plugin:"); - this->gen_sync(tu, POST_SYNC, -1); tu("trap_entry:"); + this->gen_sync(tu, POST_SYNC, -1); tu("enter_trap(core_ptr, *trap_state, *pc, 0);"); tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(),32)); tu("return *next_pc;"); diff --git a/src/vm/llvm/vm_tgc5c.cpp b/src/vm/llvm/vm_tgc5c.cpp index c211906..2229db3 100644 --- a/src/vm/llvm/vm_tgc5c.cpp +++ b/src/vm/llvm/vm_tgc5c.cpp @@ -2218,8 +2218,8 @@ private: pc=pc+ 4; this->gen_set_pc(pc, traits::NEXT_PC); this->gen_raise_trap(0, 11); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); - auto returnValue = std::make_tuple(CONT,bb); + bb = this->leave_blk; + auto returnValue = std::make_tuple(TRAP,nullptr); this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 38); @@ -2240,8 +2240,8 @@ private: pc=pc+ 4; this->gen_set_pc(pc, traits::NEXT_PC); this->gen_raise_trap(0, 3); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); - auto returnValue = std::make_tuple(CONT,bb); + bb = this->leave_blk; + auto returnValue = std::make_tuple(TRAP,nullptr); this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 39); @@ -2262,8 +2262,8 @@ private: pc=pc+ 4; this->gen_set_pc(pc, traits::NEXT_PC); this->gen_leave_trap(3); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); - auto returnValue = std::make_tuple(CONT,bb); + bb = this->leave_blk; + auto returnValue = std::make_tuple(TRAP,nullptr); this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 40); @@ -4282,8 +4282,8 @@ private: pc=pc+ 2; this->gen_set_pc(pc, traits::NEXT_PC); this->gen_raise_trap(0, 3); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); - auto returnValue = std::make_tuple(CONT,bb); + bb = this->leave_blk; + auto returnValue = std::make_tuple(TRAP,nullptr); this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 84); @@ -4351,8 +4351,8 @@ private: pc=pc+ 2; this->gen_set_pc(pc, traits::NEXT_PC); this->gen_raise_trap(0, 2); - bb = BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); - auto returnValue = std::make_tuple(CONT,bb); + bb = this->leave_blk; + auto returnValue = std::make_tuple(TRAP,nullptr); this->gen_trap_check(bb); this->gen_sync(POST_SYNC, 86); diff --git a/src/vm/tcc/vm_tgc5c.cpp b/src/vm/tcc/vm_tgc5c.cpp index a94d30a..965b9c7 100644 --- a/src/vm/tcc/vm_tgc5c.cpp +++ b/src/vm/tcc/vm_tgc5c.cpp @@ -357,8 +357,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,0); - gen_trap_check(tu); return returnValue; } @@ -392,8 +392,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,1); - gen_trap_check(tu); return returnValue; } @@ -434,8 +434,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,2); - gen_trap_check(tu); return returnValue; } @@ -462,11 +462,12 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ + auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); auto new_pc = tu.assignment(tu.ext((tu.bitwise_and( (tu.add( tu.load(rs1+ traits::X0, 0), tu.constant((int16_t)sext<12>(imm),16))), - tu.constant(~ 0x1,8))),32,false),32); + addr_mask)),32,false),32); tu.open_if(tu.urem( new_pc, tu.constant(static_cast(traits:: INSTR_ALIGNMENT),32))); @@ -476,9 +477,7 @@ private: tu.store(rd + traits::X0, tu.constant((uint32_t)(PC+ 4),32)); } - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( - new_pc, - tu.constant(~ 0x1,8)),32); + auto PC_val_v = tu.assignment("PC_val", new_pc,32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); tu.close_scope(); @@ -486,8 +485,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,3); - gen_trap_check(tu); return returnValue; } @@ -529,8 +528,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,4); - gen_trap_check(tu); return returnValue; } @@ -572,8 +571,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,5); - gen_trap_check(tu); return returnValue; } @@ -615,8 +614,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,6); - gen_trap_check(tu); return returnValue; } @@ -658,8 +657,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,7); - gen_trap_check(tu); return returnValue; } @@ -701,8 +700,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,8); - gen_trap_check(tu); return returnValue; } @@ -744,8 +743,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,9); - gen_trap_check(tu); return returnValue; } @@ -784,8 +783,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,10); - gen_trap_check(tu); return returnValue; } @@ -824,8 +823,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,11); - gen_trap_check(tu); return returnValue; } @@ -864,8 +863,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,12); - gen_trap_check(tu); return returnValue; } @@ -904,8 +903,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,13); - gen_trap_check(tu); return returnValue; } @@ -944,8 +943,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,14); - gen_trap_check(tu); return returnValue; } @@ -980,8 +979,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,15); - gen_trap_check(tu); return returnValue; } @@ -1016,8 +1015,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,16); - gen_trap_check(tu); return returnValue; } @@ -1052,8 +1051,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,17); - gen_trap_check(tu); return returnValue; } @@ -1090,8 +1089,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,18); - gen_trap_check(tu); return returnValue; } @@ -1128,8 +1127,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,19); - gen_trap_check(tu); return returnValue; } @@ -1166,8 +1165,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,20); - gen_trap_check(tu); return returnValue; } @@ -1204,8 +1203,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,21); - gen_trap_check(tu); return returnValue; } @@ -1242,8 +1241,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,22); - gen_trap_check(tu); return returnValue; } @@ -1280,8 +1279,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,23); - gen_trap_check(tu); return returnValue; } @@ -1318,8 +1317,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,24); - gen_trap_check(tu); return returnValue; } @@ -1356,8 +1355,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,25); - gen_trap_check(tu); return returnValue; } @@ -1394,8 +1393,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,26); - gen_trap_check(tu); return returnValue; } @@ -1432,8 +1431,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,27); - gen_trap_check(tu); return returnValue; } @@ -1470,8 +1469,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,28); - gen_trap_check(tu); return returnValue; } @@ -1510,8 +1509,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,29); - gen_trap_check(tu); return returnValue; } @@ -1548,8 +1547,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,30); - gen_trap_check(tu); return returnValue; } @@ -1586,8 +1585,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,31); - gen_trap_check(tu); return returnValue; } @@ -1624,8 +1623,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,32); - gen_trap_check(tu); return returnValue; } @@ -1664,8 +1663,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,33); - gen_trap_check(tu); return returnValue; } @@ -1704,8 +1703,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,34); - gen_trap_check(tu); return returnValue; } @@ -1742,8 +1741,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,35); - gen_trap_check(tu); return returnValue; } @@ -1780,8 +1779,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,36); - gen_trap_check(tu); return returnValue; } @@ -1810,8 +1809,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,37); - gen_trap_check(tu); return returnValue; } @@ -1829,11 +1828,11 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 11); - auto returnValue = std::make_tuple(CONT); + auto returnValue = std::make_tuple(TRAP); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,38); - gen_trap_check(tu); return returnValue; } @@ -1851,11 +1850,11 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 3); - auto returnValue = std::make_tuple(CONT); + auto returnValue = std::make_tuple(TRAP); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,39); - gen_trap_check(tu); return returnValue; } @@ -1873,11 +1872,11 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_leave_trap(tu, 3); - auto returnValue = std::make_tuple(CONT); + auto returnValue = std::make_tuple(TRAP); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,40); - gen_trap_check(tu); return returnValue; } @@ -1898,8 +1897,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,41); - gen_trap_check(tu); return returnValue; } @@ -1939,8 +1938,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,42); - gen_trap_check(tu); return returnValue; } @@ -1982,8 +1981,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,43); - gen_trap_check(tu); return returnValue; } @@ -2025,8 +2024,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,44); - gen_trap_check(tu); return returnValue; } @@ -2063,8 +2062,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,45); - gen_trap_check(tu); return returnValue; } @@ -2105,8 +2104,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,46); - gen_trap_check(tu); return returnValue; } @@ -2147,8 +2146,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,47); - gen_trap_check(tu); return returnValue; } @@ -2175,8 +2174,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,48); - gen_trap_check(tu); return returnValue; } @@ -2214,8 +2213,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,49); - gen_trap_check(tu); return returnValue; } @@ -2255,8 +2254,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,50); - gen_trap_check(tu); return returnValue; } @@ -2296,8 +2295,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,51); - gen_trap_check(tu); return returnValue; } @@ -2337,8 +2336,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,52); - gen_trap_check(tu); return returnValue; } @@ -2395,8 +2394,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,53); - gen_trap_check(tu); return returnValue; } @@ -2442,8 +2441,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,54); - gen_trap_check(tu); return returnValue; } @@ -2473,7 +2472,7 @@ private: tu.open_if(tu.icmp(ICmpInst::ICMP_NE, tu.load(rs2+ traits::X0, 0), tu.constant( 0,8))); - auto MMIN = tu.assignment(tu.constant( 1<<(static_cast(traits:: XLEN)-1),8),32); + auto MMIN = tu.assignment(tu.constant((uint32_t)1<<(static_cast(traits:: XLEN)-1),32),32); tu.open_if(tu.logical_and( tu.icmp(ICmpInst::ICMP_EQ, tu.load(rs1+ traits::X0, 0), @@ -2503,8 +2502,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,55); - gen_trap_check(tu); return returnValue; } @@ -2550,8 +2549,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,56); - gen_trap_check(tu); return returnValue; } @@ -2585,8 +2584,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,57); - gen_trap_check(tu); return returnValue; } @@ -2617,8 +2616,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,58); - gen_trap_check(tu); return returnValue; } @@ -2648,8 +2647,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,59); - gen_trap_check(tu); return returnValue; } @@ -2685,8 +2684,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,60); - gen_trap_check(tu); return returnValue; } @@ -2707,8 +2706,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,61); - gen_trap_check(tu); return returnValue; } @@ -2737,8 +2736,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,62); - gen_trap_check(tu); return returnValue; } @@ -2772,8 +2771,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,63); - gen_trap_check(tu); return returnValue; } @@ -2805,8 +2804,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,64); - gen_trap_check(tu); return returnValue; } @@ -2839,8 +2838,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,65); - gen_trap_check(tu); return returnValue; } @@ -2862,8 +2861,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,66); - gen_trap_check(tu); return returnValue; } @@ -2892,8 +2891,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,67); - gen_trap_check(tu); return returnValue; } @@ -2930,8 +2929,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,68); - gen_trap_check(tu); return returnValue; } @@ -2960,8 +2959,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,69); - gen_trap_check(tu); return returnValue; } @@ -2990,8 +2989,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,70); - gen_trap_check(tu); return returnValue; } @@ -3020,8 +3019,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,71); - gen_trap_check(tu); return returnValue; } @@ -3050,8 +3049,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,72); - gen_trap_check(tu); return returnValue; } @@ -3080,8 +3079,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,73); - gen_trap_check(tu); return returnValue; } @@ -3108,8 +3107,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,74); - gen_trap_check(tu); return returnValue; } @@ -3141,8 +3140,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,75); - gen_trap_check(tu); return returnValue; } @@ -3174,8 +3173,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,76); - gen_trap_check(tu); return returnValue; } @@ -3211,8 +3210,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,77); - gen_trap_check(tu); return returnValue; } @@ -3247,8 +3246,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,78); - gen_trap_check(tu); return returnValue; } @@ -3282,8 +3281,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,79); - gen_trap_check(tu); return returnValue; } @@ -3304,12 +3303,12 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - if(rs1&&rs1(traits:: RFS)) { - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( - tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0), - tu.constant(~ 0x1,8)),32); - tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); + if(rs1&&rs1(traits:: RFS)){ auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( + tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0), + addr_mask),32); + tu.store(traits::NEXT_PC, PC_val_v); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -3317,8 +3316,8 @@ private: auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,80); - gen_trap_check(tu); return returnValue; } @@ -3339,8 +3338,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,81); - gen_trap_check(tu); return returnValue; } @@ -3376,8 +3375,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,82); - gen_trap_check(tu); return returnValue; } @@ -3402,20 +3401,21 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ + auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); auto new_pc = tu.assignment(tu.load(rs1+ traits::X0, 0),32); tu.store(1 + traits::X0, tu.constant((uint32_t)(PC+ 2),32)); auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( new_pc, - tu.constant(~ 0x1,8)),32); + addr_mask),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } auto returnValue = std::make_tuple(BRANCH); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,83); - gen_trap_check(tu); return returnValue; } @@ -3433,11 +3433,11 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 3); - auto returnValue = std::make_tuple(CONT); + auto returnValue = std::make_tuple(TRAP); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,84); - gen_trap_check(tu); return returnValue; } @@ -3471,8 +3471,8 @@ private: auto returnValue = std::make_tuple(CONT); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,85); - gen_trap_check(tu); return returnValue; } @@ -3490,11 +3490,11 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 2); - auto returnValue = std::make_tuple(CONT); + auto returnValue = std::make_tuple(TRAP); tu.close_scope(); + gen_trap_check(tu); vm_base::gen_sync(tu, POST_SYNC,86); - gen_trap_check(tu); return returnValue; } @@ -3626,9 +3626,8 @@ template void vm_impl::gen_wait(tu_builder& tu, unsigned t } template void vm_impl::gen_trap_behavior(tu_builder& tu) { - tu("trap_entry_plugin:"); - this->gen_sync(tu, POST_SYNC, -1); tu("trap_entry:"); + this->gen_sync(tu, POST_SYNC, -1); tu("enter_trap(core_ptr, *trap_state, *pc, 0);"); tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits::max(),32)); tu("return *next_pc;"); From 5fd226b6706db7bdabec43ddd70c331d4f0ec910 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Mon, 25 Sep 2023 09:44:51 +0200 Subject: [PATCH 149/184] moves pctrace --- CMakeLists.txt | 5 - src/iss/plugin/pctrace.cpp | 228 ------------------------------------- src/iss/plugin/pctrace.h | 104 ----------------- src/main.cpp | 7 +- 4 files changed, 1 insertion(+), 343 deletions(-) delete mode 100644 src/iss/plugin/pctrace.cpp delete mode 100644 src/iss/plugin/pctrace.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 18eb42d..765aafc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,7 +56,6 @@ endif() if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON) list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp - src/iss/plugin/pctrace.cpp ) endif() if(TARGET jsoncpp::jsoncpp) @@ -88,10 +87,6 @@ target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boo if(TARGET jsoncpp::jsoncpp) target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp::jsoncpp) endif() -if(TARGET lz4::lz4) - target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_LZ4) - target_link_libraries(${PROJECT_NAME} PUBLIC lz4::lz4) -endif() if(TARGET RapidJSON) target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON) endif() diff --git a/src/iss/plugin/pctrace.cpp b/src/iss/plugin/pctrace.cpp deleted file mode 100644 index 97f6ee9..0000000 --- a/src/iss/plugin/pctrace.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017 - 2023, 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: - * alex@minres.com - initial implementation - ******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef WITH_LZ4 -#include -#endif - -namespace iss { -namespace plugin { - -using namespace rapidjson; -using namespace std; - -#ifdef WITH_LZ4 -class lz4compress_streambuf: public std::streambuf { -public: - lz4compress_streambuf(const lz4compress_streambuf&) = delete; - lz4compress_streambuf& operator=(const lz4compress_streambuf&) = delete; - lz4compress_streambuf(std::ostream &sink, size_t buf_size) - : sink(sink) - , src_buf(buf_size) - , dest_buf(LZ4F_compressBound(buf_size, nullptr)) - { - auto errCode = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION); - if (LZ4F_isError(errCode) != 0) - throw std::runtime_error(std::string("Failed to create LZ4 context: ") + LZ4F_getErrorName(errCode)); - size_t ret = LZ4F_compressBegin(ctx, &dest_buf.front(), dest_buf.capacity(), nullptr); - if (LZ4F_isError(ret) != 0) - throw std::runtime_error(std::string("Failed to start LZ4 compression: ") + LZ4F_getErrorName(ret)); - setp(src_buf.data(), src_buf.data() + src_buf.size() - 1); - sink.write(dest_buf.data(), ret); - } - - ~lz4compress_streambuf() { - close(); - } - - void close() { - if (closed) - return; - sync(); - auto ret = LZ4F_compressEnd(ctx, dest_buf.data(), dest_buf.capacity(), nullptr); - if (LZ4F_isError(ret) != 0) - throw std::runtime_error(std::string("Failed to finish LZ4 compression: ") + LZ4F_getErrorName(ret)); - sink.write(dest_buf.data(), ret); - LZ4F_freeCompressionContext(ctx); - closed = true; - } - -private: - int_type overflow(int_type ch) override { - compress_and_write(); - *pptr() = static_cast(ch); - pbump(1); - return ch; - } - - int_type sync() override { - compress_and_write(); - return 0; - } - - void compress_and_write() { - if (closed) - throw std::runtime_error("Cannot write to closed stream"); - if(auto orig_size = pptr() - pbase()){ - auto ret = LZ4F_compressUpdate(ctx, dest_buf.data(), dest_buf.capacity(), pbase(), orig_size, nullptr); - if (LZ4F_isError(ret) != 0) - throw std::runtime_error(std::string("LZ4 compression failed: ") + LZ4F_getErrorName(ret)); - if(ret) sink.write(dest_buf.data(), ret); - pbump(-orig_size); - } - } - - std::ostream &sink; - std::vector src_buf; - std::vector dest_buf; - LZ4F_compressionContext_t ctx{ nullptr }; - bool closed{ false }; -}; -#endif - -pctrace::pctrace(std::string const &filename) -: instr_if(nullptr) -, filename(filename) -, reg_dump(getenv("REGDUMP")) -, no_compres(getenv("NOCOMPRES")) -, output("output.trc") -#ifdef WITH_LZ4 -, strbuf( (no_compres || reg_dump)? nullptr: new lz4compress_streambuf(output, 4096)) -, ostr(strbuf.get()) -#endif -{} - -pctrace::~pctrace() { } - -bool pctrace::registration(const char *const version, vm_if& vm) { - instr_if = vm.get_arch()->get_instrumentation_if(); - reg_base_ptr = reinterpret_cast(vm.get_arch()->get_regs_base_ptr()); - - if(!instr_if) return false; - const string core_name = instr_if->core_type_name(); - if (filename.length() > 0) { - ifstream is(filename); - if (is.is_open()) { - try { - IStreamWrapper isw(is); - Document d; - ParseResult ok = d.ParseStream(isw); - if(ok) { - Value& val = d[core_name.c_str()]; - if(val.IsArray()){ - delays.reserve(val.Size()); - for (auto it = val.Begin(); it != val.End(); ++it) { - auto& name = (*it)["name"]; - auto& size = (*it)["size"]; - auto& delay = (*it)["delay"]; - auto& branch = (*it)["branch"]; - if(delay.IsArray()) { - auto dt = delay[0].Get(); - auto dnt = delay[1].Get(); - delays.push_back(instr_desc{size.Get(), dt, dnt, branch.Get()}); - } else if(delay.Is()) { - auto d = delay.Get(); - delays.push_back(instr_desc{size.Get(), d, d, branch.Get()}); - } else - throw runtime_error("JSON parse error"); - - } - } else { - LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<get_instr_word(); - auto call = id==65 || id ==86 || ((id==2 || id==3) && bit_sub<7,5>(instr)!=0) ;//not taking care of tail calls (jalr with loading x6) - bool taken = instr_if->is_branch_taken(); - bool compressed = (instr&0x3)!=0x3; - if (taken) { - delay = entry.taken; - if(entry.taken > 1) - instr_if->update_last_instr_cycles(entry.taken); - } else { - delay = entry.not_taken; - if (entry.not_taken > 1) - instr_if->update_last_instr_cycles(entry.not_taken); - } - if(no_compres|| reg_dump){ - if(reg_dump){ - for(size_t i=0; i< instr_if->get_reg_num(); ++i){ - uint32_t reg_val = *(reg_base_ptr+i); - output << "0x" << std::setfill('0') << std::setw(8) << std::hex << reg_val << " "; - } - output<<"\n" ; - } - else{ - output<get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; - } -} -}//namespace plugin -}//namespace iss diff --git a/src/iss/plugin/pctrace.h b/src/iss/plugin/pctrace.h deleted file mode 100644 index ca5d677..0000000 --- a/src/iss/plugin/pctrace.h +++ /dev/null @@ -1,104 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2017 - 2023, 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 _ISS_PLUGIN_COV_H_ -#define _ISS_PLUGIN_COV_H_ - -#include -#include "iss/instrumentation_if.h" -#include -#include -#include -namespace iss { -namespace plugin { -class lz4compress_streambuf; -class pctrace : public iss::vm_plugin { - struct instr_delay { - std::string instr_name; - size_t size; - size_t not_taken_delay; - size_t taken_delay; - }; - BEGIN_BF_DECL(instr_desc, uint32_t) - BF_FIELD(taken, 24, 8) - BF_FIELD(not_taken, 16, 8) - BF_FIELD(is_branch, 8, 8) - BF_FIELD(size, 0, 8) - instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken, bool branch): instr_desc() { - this->size=size; - this->taken=taken; - this->not_taken=not_taken; - this->is_branch=branch; - } - END_BF_DECL(); - -public: - - pctrace(const pctrace &) = delete; - - pctrace(const pctrace &&) = delete; - - pctrace(std::string const &); - - virtual ~pctrace(); - - pctrace &operator=(const pctrace &) = delete; - - pctrace &operator=(const pctrace &&) = delete; - - bool registration(const char *const version, vm_if &arch) override; - - sync_type get_sync() override { return POST_SYNC; }; - - void callback(instr_info_t) override; - -private: - iss::instrumentation_if *instr_if {nullptr}; - uint32_t* reg_base_ptr {nullptr}; - bool reg_dump {false}; - bool no_compres {false}; - std::ofstream output; - -#ifdef WITH_LZ4 - std::unique_ptr strbuf; - std::ostream ostr; -#endif - std::string filename; - std::vector delays; - bool jumped{false}, first{true}; -}; -} -} - -#endif /* _ISS_PLUGIN_COV_H_ */ diff --git a/src/main.cpp b/src/main.cpp index c476611..1d3d8e9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -44,7 +44,6 @@ #include #include "iss/plugin/cycle_estimate.h" #include "iss/plugin/instruction_count.h" -#include "iss/plugin/pctrace.h" #ifndef WIN32 #include #endif @@ -157,11 +156,7 @@ int main(int argc, char *argv[]) { auto *ce_plugin = new iss::plugin::cycle_estimate(arg); vm->register_plugin(*ce_plugin); plugin_list.push_back(ce_plugin); - } else if (plugin_name == "pctrace") { - auto *plugin = new iss::plugin::pctrace(arg); - vm->register_plugin(*plugin); - plugin_list.push_back(plugin); - } else { + }else { #ifndef WIN32 std::vector a{}; if(arg.length()) From 3fb8fe765ae0a4603b952804811ce075337360f3 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 26 Sep 2023 20:17:16 +0200 Subject: [PATCH 150/184] aligns riscv_hart_msu_vp with riscv_hart_m_p --- src/iss/arch/riscv_hart_msu_vp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index ccf9e31..9627eff 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -286,7 +286,7 @@ public: return m[mode]; } - riscv_hart_msu_vp(); + riscv_hart_msu_vp(feature_config cfg = feature_config{}); virtual ~riscv_hart_msu_vp() = default; void reset(uint64_t address) override; From 2095ac985b3a070a19ddf12dbab51ab21e345514 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 27 Sep 2023 06:19:59 +0200 Subject: [PATCH 151/184] fixes forgotten removal of pctrace in core_complex --- src/sysc/core_complex.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index a11c901..78eb36e 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -50,7 +50,6 @@ #include #include #include -#include // clang-format on @@ -283,10 +282,6 @@ void core_complex::before_end_of_elaboration() { auto *plugin = new iss::plugin::cycle_estimate(filename); cpu->vm->register_plugin(*plugin); plugin_list.push_back(plugin); - } else if (plugin_name == "pctrace") { - auto *plugin = new iss::plugin::pctrace(filename); - cpu->vm->register_plugin(*plugin); - plugin_list.push_back(plugin); } else { #ifndef WIN32 std::array a{{filename.c_str()}}; From b7f023756e0f6c0bb3600ffe59dae96026ad1bbe Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 27 Sep 2023 07:51:49 +0200 Subject: [PATCH 152/184] fixes constructor calls of derived riscv_hart classes --- src/iss/arch/hwl.h | 4 ++-- src/iss/arch/riscv_hart_common.h | 2 ++ src/iss/arch/wt_cache.h | 8 ++++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/iss/arch/hwl.h b/src/iss/arch/hwl.h index 9e954ba..80f0798 100644 --- a/src/iss/arch/hwl.h +++ b/src/iss/arch/hwl.h @@ -46,7 +46,7 @@ public: using this_class = hwl; using reg_t = typename BASE::reg_t; - hwl(); + hwl(feature_config cfg = feature_config{}); virtual ~hwl() = default; protected: @@ -56,7 +56,7 @@ protected: template -inline hwl::hwl() { +inline hwl::hwl(feature_config cfg): BASE(cfg) { for (unsigned addr = 0x800; addr < 0x803; ++addr){ this->register_custom_csr_rd(addr); this->register_custom_csr_wr(addr); diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index 45fc000..4125297 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -226,6 +226,8 @@ struct feature_config { unsigned clic_num_trigger{0}; uint64_t tcm_base{0x10000000}; uint64_t tcm_size{0x8000}; + uint64_t io_address{0xf0000000}; + uint64_t io_addr_mask{0xf0000000}; }; class trap_load_access_fault : public trap_access { diff --git a/src/iss/arch/wt_cache.h b/src/iss/arch/wt_cache.h index 2b3835b..7108b9d 100644 --- a/src/iss/arch/wt_cache.h +++ b/src/iss/arch/wt_cache.h @@ -81,7 +81,7 @@ public: using mem_write_f = typename BASE::mem_write_f; using phys_addr_t = typename BASE::phys_addr_t; - wt_cache(); + wt_cache(feature_config cfg = feature_config{}); virtual ~wt_cache() = default; unsigned size{4096}; @@ -103,7 +103,11 @@ protected: template -inline wt_cache::wt_cache() { +inline wt_cache::wt_cache(feature_config cfg) +:BASE(cfg) +, io_address{cfg.io_address} +, io_addr_mask{cfg.io_addr_mask} +{ auto cb = base_class::replace_mem_access( [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return read_cache(a, l,d);}, [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return write_cache(a, l,d);}); From b97853ff5a681acfb6138f4e46c5da881ec64f3b Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 30 Sep 2023 22:10:24 +0200 Subject: [PATCH 153/184] update plugins to read YAML file --- CMakeLists.txt | 14 +- TGC_C_instr.yaml => TGC5C_instr.yaml | 201 +++++++++++--------- gen_input/templates/CORENAME_instr.yaml.gtl | 4 +- src/iss/plugin/cycle_estimate.cpp | 63 +++--- src/iss/plugin/instruction_count.cpp | 50 ++--- src/iss/plugin/instruction_count.h | 3 +- src/main.cpp | 11 +- 7 files changed, 171 insertions(+), 175 deletions(-) rename TGC_C_instr.yaml => TGC5C_instr.yaml (90%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 765aafc..86197b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,13 +53,9 @@ if(WITH_TCC) list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) endif() -if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON) +if(TARGET yaml-cpp::yaml-cpp) list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp - ) -endif() -if(TARGET jsoncpp::jsoncpp) - list(APPEND LIB_SOURCES src/iss/plugin/instruction_count.cpp ) endif() @@ -84,11 +80,9 @@ if(NOT (DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND)) endif() target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine) -if(TARGET jsoncpp::jsoncpp) - target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp::jsoncpp) -endif() -if(TARGET RapidJSON) - target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON) +if(TARGET yaml-cpp::yaml-cpp) + target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_PLUGINS) + target_link_libraries(${PROJECT_NAME} PUBLIC yaml-cpp::yaml-cpp) endif() if(WITH_LLVM) diff --git a/TGC_C_instr.yaml b/TGC5C_instr.yaml similarity index 90% rename from TGC_C_instr.yaml rename to TGC5C_instr.yaml index e28cb64..8f14fe9 100644 --- a/TGC_C_instr.yaml +++ b/TGC5C_instr.yaml @@ -1,297 +1,297 @@ RV32I: - - LUI: + LUI: encoding: 0b00000000000000000000000000110111 mask: 0b00000000000000000000000001111111 size: 32 branch: false delay: 1 - - AUIPC: + AUIPC: encoding: 0b00000000000000000000000000010111 mask: 0b00000000000000000000000001111111 size: 32 branch: false delay: 1 - - JAL: + JAL: encoding: 0b00000000000000000000000001101111 mask: 0b00000000000000000000000001111111 size: 32 branch: true delay: 1 - - JALR: + JALR: encoding: 0b00000000000000000000000001100111 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: 1 - - BEQ: + delay: [1,1] + BEQ: encoding: 0b00000000000000000000000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: 1 - - BNE: + delay: [1,1] + BNE: encoding: 0b00000000000000000001000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: 1 - - BLT: + delay: [1,1] + BLT: encoding: 0b00000000000000000100000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: 1 - - BGE: + delay: [1,1] + BGE: encoding: 0b00000000000000000101000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: 1 - - BLTU: + delay: [1,1] + BLTU: encoding: 0b00000000000000000110000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: 1 - - BGEU: + delay: [1,1] + BGEU: encoding: 0b00000000000000000111000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: 1 - - LB: + delay: [1,1] + LB: encoding: 0b00000000000000000000000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - LH: + LH: encoding: 0b00000000000000000001000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - LW: + LW: encoding: 0b00000000000000000010000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - LBU: + LBU: encoding: 0b00000000000000000100000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - LHU: + LHU: encoding: 0b00000000000000000101000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - SB: + SB: encoding: 0b00000000000000000000000000100011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - SH: + SH: encoding: 0b00000000000000000001000000100011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - SW: + SW: encoding: 0b00000000000000000010000000100011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - ADDI: + ADDI: encoding: 0b00000000000000000000000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - SLTI: + SLTI: encoding: 0b00000000000000000010000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - SLTIU: + SLTIU: encoding: 0b00000000000000000011000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - XORI: + XORI: encoding: 0b00000000000000000100000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - ORI: + ORI: encoding: 0b00000000000000000110000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - ANDI: + ANDI: encoding: 0b00000000000000000111000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - SLLI: + SLLI: encoding: 0b00000000000000000001000000010011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - SRLI: + SRLI: encoding: 0b00000000000000000101000000010011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - SRAI: + SRAI: encoding: 0b01000000000000000101000000010011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - ADD: + ADD: encoding: 0b00000000000000000000000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - SUB: + SUB: encoding: 0b01000000000000000000000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - SLL: + SLL: encoding: 0b00000000000000000001000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - SLT: + SLT: encoding: 0b00000000000000000010000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - SLTU: + SLTU: encoding: 0b00000000000000000011000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - XOR: + XOR: encoding: 0b00000000000000000100000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - SRL: + SRL: encoding: 0b00000000000000000101000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - SRA: + SRA: encoding: 0b01000000000000000101000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - OR: + OR: encoding: 0b00000000000000000110000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - AND: + AND: encoding: 0b00000000000000000111000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - FENCE: + FENCE: encoding: 0b00000000000000000000000000001111 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - ECALL: + ECALL: encoding: 0b00000000000000000000000001110011 mask: 0b11111111111111111111111111111111 size: 32 branch: false delay: 1 - - EBREAK: + EBREAK: encoding: 0b00000000000100000000000001110011 mask: 0b11111111111111111111111111111111 size: 32 branch: false delay: 1 - - MRET: + MRET: encoding: 0b00110000001000000000000001110011 mask: 0b11111111111111111111111111111111 attributes: [[name:no_cont]] size: 32 branch: false delay: 1 - - WFI: + WFI: encoding: 0b00010000010100000000000001110011 mask: 0b11111111111111111111111111111111 size: 32 branch: false delay: 1 Zicsr: - - CSRRW: + CSRRW: encoding: 0b00000000000000000001000001110011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - CSRRS: + CSRRS: encoding: 0b00000000000000000010000001110011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - CSRRC: + CSRRC: encoding: 0b00000000000000000011000001110011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - CSRRWI: + CSRRWI: encoding: 0b00000000000000000101000001110011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - CSRRSI: + CSRRSI: encoding: 0b00000000000000000110000001110011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 - - CSRRCI: + CSRRCI: encoding: 0b00000000000000000111000001110011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 Zifencei: - - FENCE_I: + FENCE_I: encoding: 0b00000000000000000001000000001111 mask: 0b00000000000000000111000001111111 attributes: [[name:flush]] @@ -299,218 +299,231 @@ Zifencei: branch: false delay: 1 RV32M: - - MUL: + MUL: encoding: 0b00000010000000000000000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - MULH: + MULH: encoding: 0b00000010000000000001000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - MULHSU: + MULHSU: encoding: 0b00000010000000000010000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - MULHU: + MULHU: encoding: 0b00000010000000000011000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - DIV: + DIV: encoding: 0b00000010000000000100000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - DIVU: + DIVU: encoding: 0b00000010000000000101000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - REM: + REM: encoding: 0b00000010000000000110000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 - - REMU: + REMU: encoding: 0b00000010000000000111000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 RV32IC: - - CADDI4SPN: + C__ADDI4SPN: encoding: 0b0000000000000000 mask: 0b1110000000000011 size: 16 branch: false delay: 1 - - CLW: + C__LW: encoding: 0b0100000000000000 mask: 0b1110000000000011 size: 16 branch: false delay: 1 - - CSW: + C__SW: encoding: 0b1100000000000000 mask: 0b1110000000000011 size: 16 branch: false delay: 1 - - CADDI: + C__ADDI: encoding: 0b0000000000000001 mask: 0b1110000000000011 size: 16 branch: false delay: 1 - - CNOP: + C__NOP: encoding: 0b0000000000000001 mask: 0b1110111110000011 size: 16 branch: false delay: 1 - - CJAL: + C__JAL: encoding: 0b0010000000000001 mask: 0b1110000000000011 size: 16 branch: true delay: 1 - - CLI: + C__LI: encoding: 0b0100000000000001 mask: 0b1110000000000011 size: 16 branch: false delay: 1 - - CLUI: + C__LUI: encoding: 0b0110000000000001 mask: 0b1110000000000011 size: 16 branch: false delay: 1 - - CADDI16SP: + C__ADDI16SP: encoding: 0b0110000100000001 mask: 0b1110111110000011 size: 16 branch: false delay: 1 - - CSRLI: + __reserved_clui: + encoding: 0b0110000000000001 + mask: 0b1111000001111111 + size: 16 + branch: false + delay: 1 + C__SRLI: encoding: 0b1000000000000001 mask: 0b1111110000000011 size: 16 branch: false delay: 1 - - CSRAI: + C__SRAI: encoding: 0b1000010000000001 mask: 0b1111110000000011 size: 16 branch: false delay: 1 - - CANDI: + C__ANDI: encoding: 0b1000100000000001 mask: 0b1110110000000011 size: 16 branch: false delay: 1 - - CSUB: + C__SUB: encoding: 0b1000110000000001 mask: 0b1111110001100011 size: 16 branch: false delay: 1 - - CXOR: + C__XOR: encoding: 0b1000110000100001 mask: 0b1111110001100011 size: 16 branch: false delay: 1 - - COR: + C__OR: encoding: 0b1000110001000001 mask: 0b1111110001100011 size: 16 branch: false delay: 1 - - CAND: + C__AND: encoding: 0b1000110001100001 mask: 0b1111110001100011 size: 16 branch: false delay: 1 - - CJ: + C__J: encoding: 0b1010000000000001 mask: 0b1110000000000011 size: 16 branch: true delay: 1 - - CBEQZ: + C__BEQZ: encoding: 0b1100000000000001 mask: 0b1110000000000011 size: 16 branch: true - delay: 1 - - CBNEZ: + delay: [1,1] + C__BNEZ: encoding: 0b1110000000000001 mask: 0b1110000000000011 size: 16 branch: true - delay: 1 - - CSLLI: + delay: [1,1] + C__SLLI: encoding: 0b0000000000000010 mask: 0b1111000000000011 + attributes: [[name:enable, value:1]] size: 16 branch: false delay: 1 - - CLWSP: + C__LWSP: encoding: 0b0100000000000010 mask: 0b1110000000000011 size: 16 branch: false delay: 1 - - CMV: + C__MV: encoding: 0b1000000000000010 mask: 0b1111000000000011 size: 16 branch: false delay: 1 - - CJR: + C__JR: encoding: 0b1000000000000010 mask: 0b1111000001111111 size: 16 branch: true delay: 1 - - CADD: + __reserved_cmv: + encoding: 0b1000000000000010 + mask: 0b1111111111111111 + size: 16 + branch: false + delay: 1 + C__ADD: encoding: 0b1001000000000010 mask: 0b1111000000000011 size: 16 branch: false delay: 1 - - CJALR: + C__JALR: encoding: 0b1001000000000010 mask: 0b1111000001111111 size: 16 branch: true delay: 1 - - CEBREAK: + C__EBREAK: encoding: 0b1001000000000010 mask: 0b1111111111111111 size: 16 branch: false delay: 1 - - CSWSP: + C__SWSP: encoding: 0b1100000000000010 mask: 0b1110000000000011 size: 16 branch: false delay: 1 - - DII: + DII: encoding: 0b0000000000000000 mask: 0b1111111111111111 size: 16 diff --git a/gen_input/templates/CORENAME_instr.yaml.gtl b/gen_input/templates/CORENAME_instr.yaml.gtl index eb344ff..6710a1a 100644 --- a/gen_input/templates/CORENAME_instr.yaml.gtl +++ b/gen_input/templates/CORENAME_instr.yaml.gtl @@ -9,8 +9,8 @@ } instrGroups }%><%getInstructionGroups().each{name, instrList -> %> -${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %> - - ${it.instruction.name}: +${name}: <% instrList.each { %> + ${it.instruction.name}: encoding: ${it.encoding} mask: ${it.mask}<%if(it.attributes.size) {%> attributes: ${it.attributes}<%}%> diff --git a/src/iss/plugin/cycle_estimate.cpp b/src/iss/plugin/cycle_estimate.cpp index 77d4c5b..267c88e 100644 --- a/src/iss/plugin/cycle_estimate.cpp +++ b/src/iss/plugin/cycle_estimate.cpp @@ -33,18 +33,12 @@ ******************************************************************************/ #include "cycle_estimate.h" +#include #include #include -#include -#include -#include -#include -#include -#include #include -using namespace rapidjson; using namespace std; iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name) @@ -61,40 +55,31 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& if(!instr_if) return false; const string core_name = instr_if->core_type_name(); if (config_file_name.length() > 0) { - ifstream is(config_file_name); + std::ifstream is(config_file_name); if (is.is_open()) { try { - IStreamWrapper isw(is); - Document d; - ParseResult ok = d.ParseStream(isw); - if(ok) { - Value& val = d[core_name.c_str()]; - if(val.IsArray()){ - delays.reserve(val.Size()); - for (auto it = val.Begin(); it != val.End(); ++it) { - auto& name = (*it)["name"]; - auto& size = (*it)["size"]; - auto& delay = (*it)["delay"]; - auto& branch = (*it)["branch"]; - if(delay.IsArray()) { - auto dt = delay[0].Get(); - auto dnt = delay[1].Get(); - delays.push_back(instr_desc{size.Get(), dt, dnt, branch.Get()}); - } else if(delay.Is()) { - auto d = delay.Get(); - delays.push_back(instr_desc{size.Get(), d, d, branch.Get()}); - } else - throw runtime_error("JSON parse error"); - } - } else { - LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<(); + auto delay = instr.second["delay"]; + if(delay.IsSequence()) { + res.not_taken = delay[0].as(); + res.taken = delay[1].as(); + } else { + res.not_taken = delay.as(); + res.taken = res.not_taken; + } + delays.push_back(std::move(res)); + } + } + } catch (YAML::ParserException &e) { LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); return false; } diff --git a/src/iss/plugin/instruction_count.cpp b/src/iss/plugin/instruction_count.cpp index 7613b27..01fb45c 100644 --- a/src/iss/plugin/instruction_count.cpp +++ b/src/iss/plugin/instruction_count.cpp @@ -34,6 +34,7 @@ #include "instruction_count.h" #include +#include #include #include @@ -44,8 +45,30 @@ iss::plugin::instruction_count::instruction_count(std::string config_file_name) std::ifstream is(config_file_name); if (is.is_open()) { try { - is >> root; - } catch (Json::RuntimeError &e) { + auto root = YAML::LoadAll(is); + if(root.size()!=1) { + LOG(ERR) << "Too many rro nodes in YAML file " << config_file_name; + } + for (auto p : root[0]) { + auto isa_subset = p.first; + auto instructions = p.second; + for (auto const& instr : instructions) { + instr_delay res; + res.instr_name = instr.first.as(); + res.size = instr.second["encoding"].as().size()-2; // not counting 0b + auto delay = instr.second["delay"]; + if(delay.IsSequence()) { + res.not_taken_delay = delay[0].as(); + res.taken_delay = delay[1].as(); + } else { + res.not_taken_delay = delay.as(); + res.taken_delay = res.not_taken_delay; + } + delays.push_back(std::move(res)); + } + } + rep_counts.resize(delays.size()); + } catch (YAML::ParserException &e) { LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); } } else { @@ -57,7 +80,7 @@ iss::plugin::instruction_count::instruction_count(std::string config_file_name) iss::plugin::instruction_count::~instruction_count() { size_t idx=0; for(auto it:delays){ - if(rep_counts[idx]>0) + if(rep_counts[idx]>0 && it.instr_name.find("__"!=0)) LOG(INFO)<get_instrumentation_if(); if(!instr_if) return false; - const std::string core_name = instr_if->core_type_name(); - Json::Value &val = root[core_name]; - if(!val.isNull() && val.isArray()){ - delays.reserve(val.size()); - for(auto it:val){ - auto name = it["name"]; - auto size = it["size"]; - auto delay = it["delay"]; - if(!name.isString() || !size.isUInt() || !(delay.isUInt() || delay.isArray())) throw std::runtime_error("JSON parse error"); - if(delay.isUInt()){ - const instr_delay entry{name.asCString(), size.asUInt(), delay.asUInt(), 0}; - delays.push_back(entry); - } else { - const instr_delay entry{name.asCString(), size.asUInt(), delay[0].asUInt(), delay[1].asUInt()}; - delays.push_back(entry); - } - } - rep_counts.resize(delays.size()); - } else { - LOG(ERR)<<"plugin instruction_count: could not find an entry for "< -#include #include +#include namespace iss { namespace plugin { @@ -72,7 +72,6 @@ public: void callback(instr_info_t) override; private: - Json::Value root; std::vector delays; std::vector rep_counts; }; diff --git a/src/main.cpp b/src/main.cpp index 1d3d8e9..c93d558 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -73,7 +73,7 @@ int main(int argc, char *argv[]) { ("mem,m", po::value(), "the memory input file") ("plugin,p", po::value>(), "plugin to activate") ("backend", po::value()->default_value("interp"), "the ISS backend to use, options are: interp, tcc") - ("isa", po::value()->default_value("tgc5c"), "isa to use for simulation"); + ("isa", po::value()->default_value("tgc5c"), "core or isa name to use for simulation, use '?' to get list"); // clang-format on auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); try { @@ -124,7 +124,7 @@ int main(int argc, char *argv[]) { std::tie(cpu, vm) = f.create(isa_opt+"|"+clim["backend"].as(), clim["gdb-port"].as()); } else { auto base_isa = isa_opt.substr(0, 5); - if(base_isa=="tgc_d" || base_isa=="tgc_e") { + if(base_isa=="tgc5d" || base_isa=="tgc5e") { isa_opt += "|mu_p_clic_pmp|"+clim["backend"].as(); } else { isa_opt += "|m_p|"+clim["backend"].as(); @@ -148,6 +148,7 @@ int main(int argc, char *argv[]) { plugin_name = opt_val.substr(0, found); arg = opt_val.substr(found + 1, opt_val.size()); } +#if defined(WITH_PLUGINS) if (plugin_name == "ic") { auto *ic_plugin = new iss::plugin::instruction_count(arg); vm->register_plugin(*ic_plugin); @@ -156,8 +157,10 @@ int main(int argc, char *argv[]) { auto *ce_plugin = new iss::plugin::cycle_estimate(arg); vm->register_plugin(*ce_plugin); plugin_list.push_back(ce_plugin); - }else { -#ifndef WIN32 + } else +#endif + { +#if !defined(WIN32) std::vector a{}; if(arg.length()) a.push_back({arg.c_str()}); From b9b165465da738fb6116137b688fce74aa004ab2 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 30 Sep 2023 22:17:18 +0200 Subject: [PATCH 154/184] adds some template updates --- gen_input/{TGC_C.core_desc => TGC5C.core_desc} | 0 gen_input/templates/interp/CORENAME.cpp.gtl | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) rename gen_input/{TGC_C.core_desc => TGC5C.core_desc} (100%) diff --git a/gen_input/TGC_C.core_desc b/gen_input/TGC5C.core_desc similarity index 100% rename from gen_input/TGC_C.core_desc rename to gen_input/TGC5C.core_desc diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index cfb6a76..d92ed44 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -40,10 +40,11 @@ def nativeTypeSize(int size){ #include #include #include -#include #include #include #include +#include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY From ee6a068b067c64c8c1e4f6fa729817efc315713d Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 1 Oct 2023 18:33:14 +0200 Subject: [PATCH 155/184] streamlines backends and reporting --- src/main.cpp | 4 +++- src/vm/interp/vm_tgc5c.cpp | 4 ++-- src/vm/llvm/vm_tgc5c.cpp | 4 ++-- src/vm/tcc/vm_tgc5c.cpp | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c93d558..bd9638c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -118,7 +118,9 @@ int main(int argc, char *argv[]) { iss::cpu_ptr cpu{nullptr}; std::string isa_opt(clim["isa"].as()); if(isa_opt.size()==0 || isa_opt == "?") { - std::cout<<"Available cores: "<(), clim["gdb-port"].as()); diff --git a/src/vm/interp/vm_tgc5c.cpp b/src/vm/interp/vm_tgc5c.cpp index f05220b..4f4e494 100644 --- a/src/vm/interp/vm_tgc5c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -2699,13 +2699,13 @@ volatile std::array dummy = { auto vm = new interp::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - }), + })/*, core_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_mu_p(); auto vm = new interp::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - }) + })*/ }; } } diff --git a/src/vm/llvm/vm_tgc5c.cpp b/src/vm/llvm/vm_tgc5c.cpp index 2229db3..460a9d7 100644 --- a/src/vm/llvm/vm_tgc5c.cpp +++ b/src/vm/llvm/vm_tgc5c.cpp @@ -4549,13 +4549,13 @@ volatile std::array dummy = { auto* vm = new llvm::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - }), + })/*, core_factory::instance().register_creator("tgc5c|mu_p|llvm", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_mu_p(); auto* vm = new llvm::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - }) + })*/ }; } } diff --git a/src/vm/tcc/vm_tgc5c.cpp b/src/vm/tcc/vm_tgc5c.cpp index 965b9c7..3e8511b 100644 --- a/src/vm/tcc/vm_tgc5c.cpp +++ b/src/vm/tcc/vm_tgc5c.cpp @@ -3655,13 +3655,13 @@ volatile std::array dummy = { auto vm = new tcc::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - }), + })/*, core_factory::instance().register_creator("tgc5c|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_mu_p(); auto vm = new tcc::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - }) + })*/ }; } } From 9180ad1f9c0af678e6080b3fd0db6727213a99eb Mon Sep 17 00:00:00 2001 From: Stanislaw Kaushanski Date: Fri, 6 Oct 2023 21:39:48 +0200 Subject: [PATCH 156/184] debugger memory accesses should never lead to traps --- src/iss/arch/riscv_hart_m_p.h | 4 ++-- src/iss/arch/riscv_hart_msu_vp.h | 4 ++-- src/iss/arch/riscv_hart_mu_p.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 935c774..26e327d 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -682,7 +682,7 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce } else { res = hart_mem_rd_delegate( phys_addr, length, data); } - if (unlikely(res != iss::Ok)){ + if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)){ this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; } @@ -775,7 +775,7 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc } else { res = write_mem( phys_addr, length, data); } - if (unlikely(res != iss::Ok)) { + if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index 9627eff..56c7209 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -636,7 +636,7 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ } } auto res = read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); - if (unlikely(res != iss::Ok)){ + if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)){ this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; } @@ -734,7 +734,7 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access } } auto res = write_mem(paddr, length, data); - if (unlikely(res != iss::Ok)) { + if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 48cf106..33089af 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -850,7 +850,7 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc } else { res = hart_mem_rd_delegate( phys_addr, length, data); } - if (unlikely(res != iss::Ok)){ + if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)){ this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault fault_data=addr; } @@ -951,7 +951,7 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac } else { res = hart_mem_wr_delegate( phys_addr, length, data); } - if (unlikely(res != iss::Ok)) { + if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault) fault_data=addr; } From ae4322c1b967e7d9e98ff30a3cb7bd94476e9ada Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 15 Oct 2023 09:03:31 +0200 Subject: [PATCH 157/184] =?UTF-8?q?=E2=80=9Esrc/main.cpp=E2=80=9C=20=C3=A4?= =?UTF-8?q?ndern?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.cpp | 444 +++++++++++++++++++++++++-------------------------- 1 file changed, 222 insertions(+), 222 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bd9638c..03a68d0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,222 +1,222 @@ -/******************************************************************************* - * Copyright (C) 2017, 2018 MINRES Technologies GmbH - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *******************************************************************************/ - -#include -#include -#include -#include - -#include -#include -#include "iss/arch/tgc_mapper.h" -#ifdef WITH_LLVM -#include -#endif -#include -#include "iss/plugin/cycle_estimate.h" -#include "iss/plugin/instruction_count.h" -#ifndef WIN32 -#include -#endif -#if defined(HAS_LUA) -#include -#endif - -namespace po = boost::program_options; - -int main(int argc, char *argv[]) { - /* - * Define and parse the program options - */ - po::variables_map clim; - po::options_description desc("Options"); - // clang-format off - desc.add_options() - ("help,h", "Print help message") - ("verbose,v", po::value()->default_value(4), "Sets logging verbosity") - ("logfile,l", po::value(), "Sets default log file.") - ("disass,d", po::value()->implicit_value(""), "Enables disassembly") - ("gdb-port,g", po::value()->default_value(0), "enable gdb server and specify port to use") - ("instructions,i", po::value()->default_value(std::numeric_limits::max()), "max. number of instructions to simulate") - ("reset,r", po::value(), "reset address") - ("dump-ir", "dump the intermediate representation") - ("elf,f", po::value>(), "ELF file(s) to load") - ("mem,m", po::value(), "the memory input file") - ("plugin,p", po::value>(), "plugin to activate") - ("backend", po::value()->default_value("interp"), "the ISS backend to use, options are: interp, tcc") - ("isa", po::value()->default_value("tgc5c"), "core or isa name to use for simulation, use '?' to get list"); - // clang-format on - auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); - try { - po::store(parsed, clim); // can throw - // --help option - if (clim.count("help")) { - std::cout << "DBT-RISE-RiscV simulator for RISC-V" << std::endl << desc << std::endl; - return 0; - } - po::notify(clim); // throws on error, so do after help in case - } catch (po::error &e) { - // there are problems - std::cerr << "ERROR: " << e.what() << std::endl << std::endl; - std::cerr << desc << std::endl; - return 1; - } - std::vector args = collect_unrecognized(parsed.options, po::include_positional); - - LOGGER(DEFAULT)::print_time() = false; - LOGGER(connection)::print_time() = false; - auto l = logging::as_log_level(clim["verbose"].as()); - LOGGER(DEFAULT)::reporting_level() = l; - LOGGER(connection)::reporting_level() = l; - if (clim.count("logfile")) { - // configure the connection logger - auto f = fopen(clim["logfile"].as().c_str(), "w"); - LOG_OUTPUT(DEFAULT)::stream() = f; - LOG_OUTPUT(connection)::stream() = f; - } - - std::vector plugin_list; - auto res = 0; - try { -#ifdef WITH_LLVM - // application code comes here // - iss::init_jit_debug(argc, argv); -#endif - bool dump = clim.count("dump-ir"); - auto & f = iss::core_factory::instance(); - // instantiate the simulator - iss::vm_ptr vm{nullptr}; - iss::cpu_ptr cpu{nullptr}; - std::string isa_opt(clim["isa"].as()); - if(isa_opt.size()==0 || isa_opt == "?") { - auto list = f.get_names(); - std::sort(std::begin(list), std::end(list)); - std::cout<<"Available implementations (core|platform|backend):\n - "<(), clim["gdb-port"].as()); - } else { - auto base_isa = isa_opt.substr(0, 5); - if(base_isa=="tgc5d" || base_isa=="tgc5e") { - isa_opt += "|mu_p_clic_pmp|"+clim["backend"].as(); - } else { - isa_opt += "|m_p|"+clim["backend"].as(); - } - std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as()); - } - if(!cpu ){ - LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " <()<< std::endl; - return 127; - } - if(!vm ){ - LOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " <()<< std::endl; - return 127; - } - if (clim.count("plugin")) { - for (std::string const& opt_val : clim["plugin"].as>()) { - std::string plugin_name=opt_val; - std::string arg{""}; - std::size_t found = opt_val.find('='); - if (found != std::string::npos) { - plugin_name = opt_val.substr(0, found); - arg = opt_val.substr(found + 1, opt_val.size()); - } -#if defined(WITH_PLUGINS) - if (plugin_name == "ic") { - auto *ic_plugin = new iss::plugin::instruction_count(arg); - vm->register_plugin(*ic_plugin); - plugin_list.push_back(ic_plugin); - } else if (plugin_name == "ce") { - auto *ce_plugin = new iss::plugin::cycle_estimate(arg); - vm->register_plugin(*ce_plugin); - plugin_list.push_back(ce_plugin); - } else -#endif - { -#if !defined(WIN32) - std::vector a{}; - if(arg.length()) - a.push_back({arg.c_str()}); - iss::plugin::loader l(plugin_name, {{"initPlugin"}}); - auto* plugin = l.call_function("initPlugin", a.size(), a.data()); - if(plugin){ - vm->register_plugin(*plugin); - plugin_list.push_back(plugin); - } else -#endif - { - LOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl; - return 127; - } - } - } - } - if (clim.count("disass")) { - vm->setDisassEnabled(true); - LOGGER(disass)::reporting_level() = logging::INFO; - LOGGER(disass)::print_time() = false; - auto file_name = clim["disass"].as(); - if (file_name.length() > 0) { - LOG_OUTPUT(disass)::stream() = fopen(file_name.c_str(), "w"); - LOGGER(disass)::print_severity() = false; - } - } - uint64_t start_address = 0; - if (clim.count("mem")) - vm->get_arch()->load_file(clim["mem"].as()); - if (clim.count("elf")) - for (std::string input : clim["elf"].as>()) { - auto start_addr = vm->get_arch()->load_file(input); - if (start_addr.second) start_address = start_addr.first; - } - for (std::string input : args) { - auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files - if (start_addr.second) start_address = start_addr.first; - } - if (clim.count("reset")) { - auto str = clim["reset"].as(); - start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), nullptr, 16) : std::stoull(str, nullptr, 10); - } - vm->reset(start_address); - auto cycles = clim["instructions"].as(); - res = vm->start(cycles, dump); - } catch (std::exception &e) { - LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" - << std::endl; - res = 2; - } - // cleanup to let plugins report of needed - for (auto *p : plugin_list) { - delete p; - } - return res; -} +/******************************************************************************* + * Copyright (C) 2017, 2018 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include "iss/arch/tgc_mapper.h" +#ifdef WITH_LLVM +#include +#endif +#include +#include "iss/plugin/cycle_estimate.h" +#include "iss/plugin/instruction_count.h" +#ifndef WIN32 +#include +#endif +#if defined(HAS_LUA) +#include +#endif + +namespace po = boost::program_options; + +int main(int argc, char *argv[]) { + /* + * Define and parse the program options + */ + po::variables_map clim; + po::options_description desc("Options"); + // clang-format off + desc.add_options() + ("help,h", "Print help message") + ("verbose,v", po::value()->default_value(4), "Sets logging verbosity") + ("logfile,l", po::value(), "Sets default log file.") + ("disass,d", po::value()->implicit_value(""), "Enables disassembly") + ("gdb-port,g", po::value()->default_value(0), "enable gdb server and specify port to use") + ("instructions,i", po::value()->default_value(std::numeric_limits::max()), "max. number of instructions to simulate") + ("reset,r", po::value(), "reset address") + ("dump-ir", "dump the intermediate representation") + ("elf,f", po::value>(), "ELF file(s) to load") + ("mem,m", po::value(), "the memory input file") + ("plugin,p", po::value>(), "plugin to activate") + ("backend", po::value()->default_value("interp"), "the ISS backend to use, options are: interp, tcc") + ("isa", po::value()->default_value("tgc5c"), "core or isa name to use for simulation, use '?' to get list"); + // clang-format on + auto parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); + try { + po::store(parsed, clim); // can throw + // --help option + if (clim.count("help")) { + std::cout << "DBT-RISE-TGC simulator for TGC RISC-V cores" << std::endl << desc << std::endl; + return 0; + } + po::notify(clim); // throws on error, so do after help in case + } catch (po::error &e) { + // there are problems + std::cerr << "ERROR: " << e.what() << std::endl << std::endl; + std::cerr << desc << std::endl; + return 1; + } + std::vector args = collect_unrecognized(parsed.options, po::include_positional); + + LOGGER(DEFAULT)::print_time() = false; + LOGGER(connection)::print_time() = false; + auto l = logging::as_log_level(clim["verbose"].as()); + LOGGER(DEFAULT)::reporting_level() = l; + LOGGER(connection)::reporting_level() = l; + if (clim.count("logfile")) { + // configure the connection logger + auto f = fopen(clim["logfile"].as().c_str(), "w"); + LOG_OUTPUT(DEFAULT)::stream() = f; + LOG_OUTPUT(connection)::stream() = f; + } + + std::vector plugin_list; + auto res = 0; + try { +#ifdef WITH_LLVM + // application code comes here // + iss::init_jit_debug(argc, argv); +#endif + bool dump = clim.count("dump-ir"); + auto & f = iss::core_factory::instance(); + // instantiate the simulator + iss::vm_ptr vm{nullptr}; + iss::cpu_ptr cpu{nullptr}; + std::string isa_opt(clim["isa"].as()); + if(isa_opt.size()==0 || isa_opt == "?") { + auto list = f.get_names(); + std::sort(std::begin(list), std::end(list)); + std::cout<<"Available implementations (core|platform|backend):\n - "<(), clim["gdb-port"].as()); + } else { + auto base_isa = isa_opt.substr(0, 5); + if(base_isa=="tgc5d" || base_isa=="tgc5e") { + isa_opt += "|mu_p_clic_pmp|"+clim["backend"].as(); + } else { + isa_opt += "|m_p|"+clim["backend"].as(); + } + std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as()); + } + if(!cpu ){ + LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " <()<< std::endl; + return 127; + } + if(!vm ){ + LOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " <()<< std::endl; + return 127; + } + if (clim.count("plugin")) { + for (std::string const& opt_val : clim["plugin"].as>()) { + std::string plugin_name=opt_val; + std::string arg{""}; + std::size_t found = opt_val.find('='); + if (found != std::string::npos) { + plugin_name = opt_val.substr(0, found); + arg = opt_val.substr(found + 1, opt_val.size()); + } +#if defined(WITH_PLUGINS) + if (plugin_name == "ic") { + auto *ic_plugin = new iss::plugin::instruction_count(arg); + vm->register_plugin(*ic_plugin); + plugin_list.push_back(ic_plugin); + } else if (plugin_name == "ce") { + auto *ce_plugin = new iss::plugin::cycle_estimate(arg); + vm->register_plugin(*ce_plugin); + plugin_list.push_back(ce_plugin); + } else +#endif + { +#if !defined(WIN32) + std::vector a{}; + if(arg.length()) + a.push_back({arg.c_str()}); + iss::plugin::loader l(plugin_name, {{"initPlugin"}}); + auto* plugin = l.call_function("initPlugin", a.size(), a.data()); + if(plugin){ + vm->register_plugin(*plugin); + plugin_list.push_back(plugin); + } else +#endif + { + LOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl; + return 127; + } + } + } + } + if (clim.count("disass")) { + vm->setDisassEnabled(true); + LOGGER(disass)::reporting_level() = logging::INFO; + LOGGER(disass)::print_time() = false; + auto file_name = clim["disass"].as(); + if (file_name.length() > 0) { + LOG_OUTPUT(disass)::stream() = fopen(file_name.c_str(), "w"); + LOGGER(disass)::print_severity() = false; + } + } + uint64_t start_address = 0; + if (clim.count("mem")) + vm->get_arch()->load_file(clim["mem"].as()); + if (clim.count("elf")) + for (std::string input : clim["elf"].as>()) { + auto start_addr = vm->get_arch()->load_file(input); + if (start_addr.second) start_address = start_addr.first; + } + for (std::string input : args) { + auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files + if (start_addr.second) start_address = start_addr.first; + } + if (clim.count("reset")) { + auto str = clim["reset"].as(); + start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), nullptr, 16) : std::stoull(str, nullptr, 10); + } + vm->reset(start_address); + auto cycles = clim["instructions"].as(); + res = vm->start(cycles, dump); + } catch (std::exception &e) { + LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" + << std::endl; + res = 2; + } + // cleanup to let plugins report of needed + for (auto *p : plugin_list) { + delete p; + } + return res; +} From aa12e93177eadbf5e4131a9768056c1b14e7fa8c Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 18 Oct 2023 11:17:20 +0200 Subject: [PATCH 158/184] adds RPATH setting to install --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 86197b5..fed2f4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,6 +115,7 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME} ############################################################################### # ############################################################################### +set(CMAKE_INSTALL_RPATH $ORIGIN/../${CMAKE_INSTALL_LIBDIR}) project(tgc-sim) find_package(Boost COMPONENTS program_options thread REQUIRED) From 74ff1d455a43d83929c28017a31f14247077dfa8 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 20 Oct 2023 20:38:59 +0200 Subject: [PATCH 159/184] fixes install routine --- CMakeLists.txt | 2 ++ src/iss/plugin/cycle_estimate.cpp | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fed2f4b..59e613c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ endif() # library files FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp) FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp) +FILE(GLOB GEN_YAML_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.yaml) list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES}) foreach(FILEPATH ${GEN_ISS_SOURCES}) get_filename_component(CORE ${FILEPATH} NAME_WE) @@ -112,6 +113,7 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME} FILES_MATCHING # install only matched files PATTERN "*.h" # select header files ) +install(FILES ${GEN_YAML_SOURCES} DESTINATION share/tgc-vp) ############################################################################### # ############################################################################### diff --git a/src/iss/plugin/cycle_estimate.cpp b/src/iss/plugin/cycle_estimate.cpp index 267c88e..b389cb4 100644 --- a/src/iss/plugin/cycle_estimate.cpp +++ b/src/iss/plugin/cycle_estimate.cpp @@ -1,3 +1,4 @@ + /******************************************************************************* * Copyright (C) 2017 - 2023, MINRES Technologies GmbH * All rights reserved. @@ -60,7 +61,7 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& try { auto root = YAML::LoadAll(is); if(root.size()!=1) { - LOG(ERR) << "Too many rro nodes in YAML file " << config_file_name; + LOG(ERR) << "Too many root nodes in YAML file " << config_file_name; } for (auto p : root[0]) { auto isa_subset = p.first; @@ -97,7 +98,7 @@ void iss::plugin::cycle_estimate::callback(instr_info_t instr_info) { auto entry = delays[instr_info.instr_id]; bool taken = instr_if->is_branch_taken(); if (taken && (entry.taken > 1)) - instr_if->update_last_instr_cycles(entry.taken); - else if (entry.not_taken > 1) - instr_if->update_last_instr_cycles(entry.not_taken); + instr_if->update_last_instr_cycles(entry.taken); + else if (entry.not_taken > 1) + instr_if->update_last_instr_cycles(entry.not_taken); } From 3a86f4f9de436172a6c4427686127fb81b6244e6 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 21 Oct 2023 17:19:24 +0200 Subject: [PATCH 160/184] does some cleanup of generated files --- .settings/org.eclipse.cdt.codan.core.prefs | 73 -------------- .settings/org.eclipse.cdt.core.prefs | 13 --- .../org.eclipse.cdt.managedbuilder.core.prefs | 37 -------- .../instr/TGC5C_instr.yaml | 94 ++++++++++++++++++- gen_input/templates/CORENAME_instr.yaml.gtl | 3 +- 5 files changed, 95 insertions(+), 125 deletions(-) delete mode 100644 .settings/org.eclipse.cdt.codan.core.prefs delete mode 100644 .settings/org.eclipse.cdt.core.prefs delete mode 100644 .settings/org.eclipse.cdt.managedbuilder.core.prefs rename TGC5C_instr.yaml => contrib/instr/TGC5C_instr.yaml (89%) diff --git a/.settings/org.eclipse.cdt.codan.core.prefs b/.settings/org.eclipse.cdt.codan.core.prefs deleted file mode 100644 index 067d6fd..0000000 --- a/.settings/org.eclipse.cdt.codan.core.prefs +++ /dev/null @@ -1,73 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.cdt.codan.checkers.errnoreturn=Warning -org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false} -org.eclipse.cdt.codan.checkers.errreturnvalue=Error -org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"} -org.eclipse.cdt.codan.checkers.nocommentinside=-Error -org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"} -org.eclipse.cdt.codan.checkers.nolinecomment=-Error -org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"} -org.eclipse.cdt.codan.checkers.noreturn=Error -org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false} -org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error -org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"} -org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error -org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"} -org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning -org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"} -org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error -org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"} -org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning -org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false} -org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning -org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error -org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"} -org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning -org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true} -org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error -org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"} -org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"} -org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"} -org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error -org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"} -org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error -org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"} -org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error -org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"} -org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error -org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"} -org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"} -org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info -org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning -org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"} -org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error -org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"} -org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error -org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"} -org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error -org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"} -org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning -org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"} -org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning -org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"} -org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning -org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning -org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false} -org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning -org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false} -org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"} -org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true} -org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true} -org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")} -org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"} diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs deleted file mode 100644 index 7982989..0000000 --- a/.settings/org.eclipse.cdt.core.prefs +++ /dev/null @@ -1,13 +0,0 @@ -eclipse.preferences.version=1 -environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true -environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LLVM_HOME/delimiter=\: -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LLVM_HOME/operation=append -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LLVM_HOME/value=/usr/lib/llvm-6.0 -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/appendContributed=true -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/delimiter=\: -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/operation=append -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/value=/usr/lib/llvm-6.0 -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true -environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true diff --git a/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/.settings/org.eclipse.cdt.managedbuilder.core.prefs deleted file mode 100644 index f299fce..0000000 --- a/.settings/org.eclipse.cdt.managedbuilder.core.prefs +++ /dev/null @@ -1,37 +0,0 @@ -eclipse.preferences.version=1 -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPLUS_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPLUS_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/C_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/C_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPLUS_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPLUS_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/C_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/C_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/appendContributed=true -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPLUS_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPLUS_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/C_INCLUDE_PATH/delimiter=\: -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/C_INCLUDE_PATH/operation=remove -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true -environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/LIBRARY_PATH/delimiter=\: -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/LIBRARY_PATH/operation=remove -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LIBRARY_PATH/delimiter=\: -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LIBRARY_PATH/operation=remove -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/appendContributed=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/LIBRARY_PATH/delimiter=\: -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/LIBRARY_PATH/operation=remove -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true -environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true diff --git a/TGC5C_instr.yaml b/contrib/instr/TGC5C_instr.yaml similarity index 89% rename from TGC5C_instr.yaml rename to contrib/instr/TGC5C_instr.yaml index 8f14fe9..6ea4d78 100644 --- a/TGC5C_instr.yaml +++ b/contrib/instr/TGC5C_instr.yaml @@ -1,246 +1,289 @@ RV32I: LUI: + index: 0 encoding: 0b00000000000000000000000000110111 mask: 0b00000000000000000000000001111111 size: 32 branch: false delay: 1 AUIPC: + index: 1 encoding: 0b00000000000000000000000000010111 mask: 0b00000000000000000000000001111111 size: 32 branch: false delay: 1 JAL: + index: 2 encoding: 0b00000000000000000000000001101111 mask: 0b00000000000000000000000001111111 size: 32 branch: true delay: 1 JALR: + index: 3 encoding: 0b00000000000000000000000001100111 mask: 0b00000000000000000111000001111111 size: 32 branch: true delay: [1,1] BEQ: + index: 4 encoding: 0b00000000000000000000000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true delay: [1,1] BNE: + index: 5 encoding: 0b00000000000000000001000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true delay: [1,1] BLT: + index: 6 encoding: 0b00000000000000000100000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true delay: [1,1] BGE: + index: 7 encoding: 0b00000000000000000101000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true delay: [1,1] BLTU: + index: 8 encoding: 0b00000000000000000110000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true delay: [1,1] BGEU: + index: 9 encoding: 0b00000000000000000111000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true delay: [1,1] LB: + index: 10 encoding: 0b00000000000000000000000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 LH: + index: 11 encoding: 0b00000000000000000001000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 LW: + index: 12 encoding: 0b00000000000000000010000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 LBU: + index: 13 encoding: 0b00000000000000000100000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 LHU: + index: 14 encoding: 0b00000000000000000101000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 SB: + index: 15 encoding: 0b00000000000000000000000000100011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 SH: + index: 16 encoding: 0b00000000000000000001000000100011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 SW: + index: 17 encoding: 0b00000000000000000010000000100011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 ADDI: + index: 18 encoding: 0b00000000000000000000000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 SLTI: + index: 19 encoding: 0b00000000000000000010000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 SLTIU: + index: 20 encoding: 0b00000000000000000011000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 XORI: + index: 21 encoding: 0b00000000000000000100000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 ORI: + index: 22 encoding: 0b00000000000000000110000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 ANDI: + index: 23 encoding: 0b00000000000000000111000000010011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 SLLI: + index: 24 encoding: 0b00000000000000000001000000010011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 SRLI: + index: 25 encoding: 0b00000000000000000101000000010011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 SRAI: + index: 26 encoding: 0b01000000000000000101000000010011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 ADD: + index: 27 encoding: 0b00000000000000000000000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 SUB: + index: 28 encoding: 0b01000000000000000000000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 SLL: + index: 29 encoding: 0b00000000000000000001000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 SLT: + index: 30 encoding: 0b00000000000000000010000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 SLTU: + index: 31 encoding: 0b00000000000000000011000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 XOR: + index: 32 encoding: 0b00000000000000000100000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 SRL: + index: 33 encoding: 0b00000000000000000101000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 SRA: + index: 34 encoding: 0b01000000000000000101000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 OR: + index: 35 encoding: 0b00000000000000000110000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 AND: + index: 36 encoding: 0b00000000000000000111000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 FENCE: + index: 37 encoding: 0b00000000000000000000000000001111 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 ECALL: + index: 38 encoding: 0b00000000000000000000000001110011 mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] size: 32 branch: false delay: 1 EBREAK: + index: 39 encoding: 0b00000000000100000000000001110011 mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] size: 32 branch: false delay: 1 MRET: + index: 40 encoding: 0b00110000001000000000000001110011 mask: 0b11111111111111111111111111111111 attributes: [[name:no_cont]] @@ -248,6 +291,7 @@ RV32I: branch: false delay: 1 WFI: + index: 41 encoding: 0b00010000010100000000000001110011 mask: 0b11111111111111111111111111111111 size: 32 @@ -255,36 +299,42 @@ RV32I: delay: 1 Zicsr: CSRRW: + index: 42 encoding: 0b00000000000000000001000001110011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 CSRRS: + index: 43 encoding: 0b00000000000000000010000001110011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 CSRRC: + index: 44 encoding: 0b00000000000000000011000001110011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 CSRRWI: + index: 45 encoding: 0b00000000000000000101000001110011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 CSRRSI: + index: 46 encoding: 0b00000000000000000110000001110011 mask: 0b00000000000000000111000001111111 size: 32 branch: false delay: 1 CSRRCI: + index: 47 encoding: 0b00000000000000000111000001110011 mask: 0b00000000000000000111000001111111 size: 32 @@ -292,6 +342,7 @@ Zicsr: delay: 1 Zifencei: FENCE_I: + index: 48 encoding: 0b00000000000000000001000000001111 mask: 0b00000000000000000111000001111111 attributes: [[name:flush]] @@ -300,175 +351,207 @@ Zifencei: delay: 1 RV32M: MUL: + index: 49 encoding: 0b00000010000000000000000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 MULH: + index: 50 encoding: 0b00000010000000000001000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 MULHSU: + index: 51 encoding: 0b00000010000000000010000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 MULHU: + index: 52 encoding: 0b00000010000000000011000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 DIV: + index: 53 encoding: 0b00000010000000000100000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 DIVU: + index: 54 encoding: 0b00000010000000000101000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 REM: + index: 55 encoding: 0b00000010000000000110000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 REMU: + index: 56 encoding: 0b00000010000000000111000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false delay: 1 -RV32IC: +Zca: C__ADDI4SPN: + index: 57 encoding: 0b0000000000000000 mask: 0b1110000000000011 size: 16 branch: false delay: 1 C__LW: + index: 58 encoding: 0b0100000000000000 mask: 0b1110000000000011 size: 16 branch: false delay: 1 C__SW: + index: 59 encoding: 0b1100000000000000 mask: 0b1110000000000011 size: 16 branch: false delay: 1 C__ADDI: + index: 60 encoding: 0b0000000000000001 mask: 0b1110000000000011 size: 16 branch: false delay: 1 C__NOP: + index: 61 encoding: 0b0000000000000001 mask: 0b1110111110000011 size: 16 branch: false delay: 1 C__JAL: + index: 62 encoding: 0b0010000000000001 mask: 0b1110000000000011 + attributes: [[name:enable, value:1]] size: 16 branch: true delay: 1 C__LI: + index: 63 encoding: 0b0100000000000001 mask: 0b1110000000000011 size: 16 branch: false delay: 1 C__LUI: + index: 64 encoding: 0b0110000000000001 mask: 0b1110000000000011 size: 16 branch: false delay: 1 C__ADDI16SP: + index: 65 encoding: 0b0110000100000001 mask: 0b1110111110000011 size: 16 branch: false delay: 1 __reserved_clui: + index: 66 encoding: 0b0110000000000001 mask: 0b1111000001111111 size: 16 branch: false delay: 1 C__SRLI: + index: 67 encoding: 0b1000000000000001 mask: 0b1111110000000011 + attributes: [[name:enable, value:1]] size: 16 branch: false delay: 1 C__SRAI: + index: 68 encoding: 0b1000010000000001 mask: 0b1111110000000011 + attributes: [[name:enable, value:1]] size: 16 branch: false delay: 1 C__ANDI: + index: 69 encoding: 0b1000100000000001 mask: 0b1110110000000011 size: 16 branch: false delay: 1 C__SUB: + index: 70 encoding: 0b1000110000000001 mask: 0b1111110001100011 size: 16 branch: false delay: 1 C__XOR: + index: 71 encoding: 0b1000110000100001 mask: 0b1111110001100011 size: 16 branch: false delay: 1 C__OR: + index: 72 encoding: 0b1000110001000001 mask: 0b1111110001100011 size: 16 branch: false delay: 1 C__AND: + index: 73 encoding: 0b1000110001100001 mask: 0b1111110001100011 size: 16 branch: false delay: 1 C__J: + index: 74 encoding: 0b1010000000000001 mask: 0b1110000000000011 size: 16 branch: true delay: 1 C__BEQZ: + index: 75 encoding: 0b1100000000000001 mask: 0b1110000000000011 size: 16 branch: true delay: [1,1] C__BNEZ: + index: 76 encoding: 0b1110000000000001 mask: 0b1110000000000011 size: 16 branch: true delay: [1,1] C__SLLI: + index: 77 encoding: 0b0000000000000010 mask: 0b1111000000000011 attributes: [[name:enable, value:1]] @@ -476,54 +559,63 @@ RV32IC: branch: false delay: 1 C__LWSP: + index: 78 encoding: 0b0100000000000010 mask: 0b1110000000000011 size: 16 branch: false delay: 1 C__MV: + index: 79 encoding: 0b1000000000000010 mask: 0b1111000000000011 size: 16 branch: false delay: 1 C__JR: + index: 80 encoding: 0b1000000000000010 mask: 0b1111000001111111 size: 16 branch: true delay: 1 __reserved_cmv: + index: 81 encoding: 0b1000000000000010 mask: 0b1111111111111111 size: 16 branch: false delay: 1 C__ADD: + index: 82 encoding: 0b1001000000000010 mask: 0b1111000000000011 size: 16 branch: false delay: 1 C__JALR: + index: 83 encoding: 0b1001000000000010 mask: 0b1111000001111111 size: 16 branch: true delay: 1 C__EBREAK: + index: 84 encoding: 0b1001000000000010 mask: 0b1111111111111111 size: 16 branch: false delay: 1 C__SWSP: + index: 85 encoding: 0b1100000000000010 mask: 0b1110000000000011 size: 16 branch: false delay: 1 DII: + index: 86 encoding: 0b0000000000000000 mask: 0b1111111111111111 size: 16 diff --git a/gen_input/templates/CORENAME_instr.yaml.gtl b/gen_input/templates/CORENAME_instr.yaml.gtl index 6710a1a..d9fdcbf 100644 --- a/gen_input/templates/CORENAME_instr.yaml.gtl +++ b/gen_input/templates/CORENAME_instr.yaml.gtl @@ -8,9 +8,10 @@ instrGroups[groupName]+=it; } instrGroups -}%><%getInstructionGroups().each{name, instrList -> %> +}%><%int index = 0; getInstructionGroups().each{name, instrList -> %> ${name}: <% instrList.each { %> ${it.instruction.name}: + index: ${index++} encoding: ${it.encoding} mask: ${it.mask}<%if(it.attributes.size) {%> attributes: ${it.attributes}<%}%> From 82c26acfc871c0ba82a69481f8383733ad174509 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 21 Oct 2023 17:26:03 +0200 Subject: [PATCH 161/184] does some cleanup of the directory structure --- CMakeLists.txt | 2 +- contrib/{ => pa}/.gitignore | 0 contrib/{ => pa}/README.md | 4 ++-- contrib/{ => pa}/build.tcl | 0 contrib/{ => pa}/hello.dis | 0 contrib/{ => pa}/hello.elf | Bin contrib/{ => pa}/minres.png | Bin contrib/{ => pa}/tgc_import.cc | 0 contrib/{ => pa}/tgc_import.tcl | 0 contrib/{ => pa}/tgc_import_tb.tcl | 0 10 files changed, 3 insertions(+), 3 deletions(-) rename contrib/{ => pa}/.gitignore (100%) rename contrib/{ => pa}/README.md (96%) rename contrib/{ => pa}/build.tcl (100%) rename contrib/{ => pa}/hello.dis (100%) rename contrib/{ => pa}/hello.elf (100%) rename contrib/{ => pa}/minres.png (100%) rename contrib/{ => pa}/tgc_import.cc (100%) rename contrib/{ => pa}/tgc_import.tcl (100%) rename contrib/{ => pa}/tgc_import_tb.tcl (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 59e613c..42448ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ endif() # library files FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp) FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp) -FILE(GLOB GEN_YAML_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.yaml) +FILE(GLOB GEN_YAML_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/contrib/instr/*.yaml) list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES}) foreach(FILEPATH ${GEN_ISS_SOURCES}) get_filename_component(CORE ${FILEPATH} NAME_WE) diff --git a/contrib/.gitignore b/contrib/pa/.gitignore similarity index 100% rename from contrib/.gitignore rename to contrib/pa/.gitignore diff --git a/contrib/README.md b/contrib/pa/README.md similarity index 96% rename from contrib/README.md rename to contrib/pa/README.md index c65d9f6..3c1c287 100644 --- a/contrib/README.md +++ b/contrib/pa/README.md @@ -19,7 +19,7 @@ setenv CXX $COWAREHOME/SLS/linux/common/bin/g++ cmake -S . -B build/PA -DCMAKE_BUILD_TYPE=Debug -DUSE_CWR_SYSTEMC=ON -DBUILD_SHARED_LIBS=ON \ -DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=${TGFS_INSTALL_ROOT} cmake --build build/PA --target install -j16 -cd dbt-rise-tgc/contrib +cd dbt-rise-tgc/contrib/pa # import the TGC core itself pct tgc_import_tb.tcl ``` @@ -37,7 +37,7 @@ export CXX=$COWAREHOME/SLS/linux/common/bin/g++ cmake -S . -B build/PA -DCMAKE_BUILD_TYPE=Debug -DUSE_CWR_SYSTEMC=ON -DBUILD_SHARED_LIBS=ON \ -DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=${TGFS_INSTALL_ROOT} cmake --build build/PA --target install -j16 -cd dbt-rise-tgc/contrib +cd dbt-rise-tgc/contrib/pa # import the TGC core itself pct tgc_import_tb.tcl ``` \ No newline at end of file diff --git a/contrib/build.tcl b/contrib/pa/build.tcl similarity index 100% rename from contrib/build.tcl rename to contrib/pa/build.tcl diff --git a/contrib/hello.dis b/contrib/pa/hello.dis similarity index 100% rename from contrib/hello.dis rename to contrib/pa/hello.dis diff --git a/contrib/hello.elf b/contrib/pa/hello.elf similarity index 100% rename from contrib/hello.elf rename to contrib/pa/hello.elf diff --git a/contrib/minres.png b/contrib/pa/minres.png similarity index 100% rename from contrib/minres.png rename to contrib/pa/minres.png diff --git a/contrib/tgc_import.cc b/contrib/pa/tgc_import.cc similarity index 100% rename from contrib/tgc_import.cc rename to contrib/pa/tgc_import.cc diff --git a/contrib/tgc_import.tcl b/contrib/pa/tgc_import.tcl similarity index 100% rename from contrib/tgc_import.tcl rename to contrib/pa/tgc_import.tcl diff --git a/contrib/tgc_import_tb.tcl b/contrib/pa/tgc_import_tb.tcl similarity index 100% rename from contrib/tgc_import_tb.tcl rename to contrib/pa/tgc_import_tb.tcl From 4c3a7386b0481dc117fef9e3639748d60e72a4c7 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 22 Oct 2023 08:51:08 +0200 Subject: [PATCH 162/184] updates generated files --- contrib/instr/.gitignore | 1 + src/vm/interp/vm_tgc5c.cpp | 13 ++++++------- src/vm/tcc/vm_tgc5c.cpp | 23 +++++++++++------------ 3 files changed, 18 insertions(+), 19 deletions(-) create mode 100644 contrib/instr/.gitignore diff --git a/contrib/instr/.gitignore b/contrib/instr/.gitignore new file mode 100644 index 0000000..88b59f2 --- /dev/null +++ b/contrib/instr/.gitignore @@ -0,0 +1 @@ +/*.yaml \ No newline at end of file diff --git a/src/vm/interp/vm_tgc5c.cpp b/src/vm/interp/vm_tgc5c.cpp index 4f4e494..d5d635c 100644 --- a/src/vm/interp/vm_tgc5c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -36,10 +36,11 @@ #include #include #include -#include #include #include #include +#include +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY @@ -2522,8 +2523,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction { if(rs1 && rs1 < traits::RFS) { - uint32_t addr_mask = (uint32_t)- 2; - *NEXT_PC = *(X+rs1 % traits::RFS) & addr_mask; + *NEXT_PC = *(X+rs1 % traits::RFS) & ~ 0x1; this->core.reg.last_branch = 1; } else { @@ -2589,10 +2589,9 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co raise(0, 2); } else { - uint32_t addr_mask = (uint32_t)- 2; uint32_t new_pc = *(X+rs1); *(X+1) = (uint32_t)(*PC + 2); - *NEXT_PC = new_pc & addr_mask; + *NEXT_PC = new_pc & ~ 0x1; this->core.reg.last_branch = 1; } } @@ -2699,13 +2698,13 @@ volatile std::array dummy = { auto vm = new interp::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - })/*, + }), core_factory::instance().register_creator("tgc5c|mu_p|interp", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_mu_p(); auto vm = new interp::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - })*/ + }) }; } } diff --git a/src/vm/tcc/vm_tgc5c.cpp b/src/vm/tcc/vm_tgc5c.cpp index 3e8511b..23a0060 100644 --- a/src/vm/tcc/vm_tgc5c.cpp +++ b/src/vm/tcc/vm_tgc5c.cpp @@ -3303,12 +3303,12 @@ private: pc=pc+ 2; gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); - if(rs1&&rs1(traits:: RFS)){ auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); - auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( - tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0), - addr_mask),32); - tu.store(traits::NEXT_PC, PC_val_v); - tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); + if(rs1&&rs1(traits:: RFS)) { + auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( + tu.load(rs1%static_cast(traits:: RFS)+ traits::X0, 0), + tu.constant(~ 0x1,8)),32); + tu.store(traits::NEXT_PC, PC_val_v); + tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } else{ this->gen_raise_trap(tu, 0, 2); @@ -3401,13 +3401,12 @@ private: this->gen_raise_trap(tu, 0, 2); } else{ - auto addr_mask = tu.assignment(tu.constant((uint32_t)- 2,32),32); auto new_pc = tu.assignment(tu.load(rs1+ traits::X0, 0),32); tu.store(1 + traits::X0, tu.constant((uint32_t)(PC+ 2),32)); auto PC_val_v = tu.assignment("PC_val", tu.bitwise_and( new_pc, - addr_mask),32); + tu.constant(~ 0x1,8)),32); tu.store(traits::NEXT_PC, PC_val_v); tu.store(traits::LAST_BRANCH, tu.constant(2U, 2)); } @@ -3433,7 +3432,7 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 3); - auto returnValue = std::make_tuple(TRAP); + auto returnValue = std::make_tuple(CONT); tu.close_scope(); gen_trap_check(tu); @@ -3490,7 +3489,7 @@ private: gen_set_pc(tu, pc, traits::NEXT_PC); tu.open_scope(); this->gen_raise_trap(tu, 0, 2); - auto returnValue = std::make_tuple(TRAP); + auto returnValue = std::make_tuple(CONT); tu.close_scope(); gen_trap_check(tu); @@ -3655,13 +3654,13 @@ volatile std::array dummy = { auto vm = new tcc::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - })/*, + }), core_factory::instance().register_creator("tgc5c|mu_p|tcc", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_mu_p(); auto vm = new tcc::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - })*/ + }) }; } } From 9371a09b71dd3e850d89b35fe1f93ff0813a689d Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sun, 22 Oct 2023 15:10:55 +0200 Subject: [PATCH 163/184] adds asmjit --- CMakeLists.txt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 765aafc..56955b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,11 @@ if(WITH_LLVM) src/vm/llvm/fp_impl.cpp ) endif() - +if(WITH_ASMJIT) + list(APPEND LIB_SOURCES + src/vm/asmjit/vm_tgc5c.cpp + ) +endif() # library files FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp) FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp) @@ -52,7 +56,10 @@ if(WITH_TCC) FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/tcc/vm_*.cpp) list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) endif() - +if(WITH_ASMJIT) + FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/asmjit/vm_*.cpp) + list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES}) +endif() if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON) list(APPEND LIB_SOURCES src/iss/plugin/cycle_estimate.cpp @@ -185,6 +192,10 @@ if(BUILD_TESTING) add_test(NAME tgc-sim-llvm COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm) endif() + if(WITH_ASMJIT) + add_test(NAME tgc-sim-asmjit + COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend asmjit) + endif() endif() ############################################################################### # From 60c926c921a8403b58a1ebee4eee47fbb48416a7 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Sun, 22 Oct 2023 15:11:20 +0200 Subject: [PATCH 164/184] adds asmjit --- gen_input/templates/asmjit/CORENAME.cpp.gtl | 280 ++ src/vm/asmjit/helper_func.h | 474 +++ src/vm/asmjit/vm_tgc5c.cpp | 3786 +++++++++++++++++++ 3 files changed, 4540 insertions(+) create mode 100644 gen_input/templates/asmjit/CORENAME.cpp.gtl create mode 100644 src/vm/asmjit/helper_func.h create mode 100644 src/vm/asmjit/vm_tgc5c.cpp diff --git a/gen_input/templates/asmjit/CORENAME.cpp.gtl b/gen_input/templates/asmjit/CORENAME.cpp.gtl new file mode 100644 index 0000000..ad40e74 --- /dev/null +++ b/gen_input/templates/asmjit/CORENAME.cpp.gtl @@ -0,0 +1,280 @@ +/******************************************************************************* + * Copyright (C) 2017, 2023 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef FMT_HEADER_ONLY +#define FMT_HEADER_ONLY +#endif +#include + +#include +#include + +namespace iss { +namespace asmjit { + + +namespace ${coreDef.name.toLowerCase()} { +using namespace ::asmjit; +using namespace iss::arch; +using namespace iss::debugger; + +template class vm_impl : public iss::asmjit::vm_base { +public: + using traits = arch::traits; + using super = typename iss::asmjit::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 mem_type_e = typename super::mem_type_e; + using addr_t = typename super::addr_t; + + vm_impl(); + + vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); + + void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } + + target_adapter_if *accquire_target_adapter(server_if *srv) override { + debugger_if::dbg_enabled = true; + if (vm_base::tgt_adapter == nullptr) + vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return vm_base::tgt_adapter; + } + +protected: + using vm_base::get_reg_ptr; + using this_class = vm_impl; + using compile_func = continuation_e (this_class::*)(virt_addr_t&, code_word_t, jit_holder&); + + continuation_e gen_single_inst_behavior(virt_addr_t&, unsigned int &, jit_holder&) override; + inline const char *name(size_t index){return traits::reg_aliases.at(index);} + + template::type> + inline S sext(U from) { + auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; + + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> + /* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */ + {${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%> + }}; + + /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> + /* instruction ${idx}: ${instr.name} */ + continuation_e __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\\n${instr.name}_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, ${idx}); + pc=pc+ ${instr.length/8}; + + gen_instr_prologue(jh, pc.val); + cc.comment("\\n//behavior:"); + /*generate behavior*/ + <%instr.behavior.eachLine{%>${it} + <%}%> + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, ${idx}); + return returnValue; + } + <%}%> + /**************************************************************************** + * end opcode definitions + ****************************************************************************/ + continuation_e illegal_intruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) { + + return BRANCH; + } + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; + } +}; + +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; +} + +template vm_impl::vm_impl() { this(new ARCH()); } + +template +vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) +: vm_base(core, core_id, cluster_id) { + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr: instr_descr){ + root->instrs.push_back(instr); + } + populate_decoding_tree(root); +} + +template +continuation_e +vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, jit_holder& jh) { + enum {TRAP_ID=1<<16}; + code_word_t instr = 0; + phys_addr_t paddr(pc); + auto *const data = (uint8_t *)&instr; + if(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); + auto res = this->core.read(paddr, 4, data); + if (res != iss::Ok) + throw trap_access(TRAP_ID, pc.val); + if (instr == 0x0000006f || (instr&0xffff)==0xa001) + throw simulation_stopped(0); // 'J 0' or 'C.J 0' + ++inst_cnt; + auto f = decode_instr(root, instr); + if (f == nullptr) + f = &this_class::illegal_intruction; + return (this->*f)(pc, instr, jh); +} + + + +} // namespace ${coreDef.name.toLowerCase()} + +template <> +std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { + auto ret = new ${coreDef.name.toLowerCase()}::vm_impl(*core, dump); + if (port != 0) debugger::server::run_server(ret, port); + return std::unique_ptr(ret); +} +} // namespace asmjit +} // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto* vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto* vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} diff --git a/src/vm/asmjit/helper_func.h b/src/vm/asmjit/helper_func.h new file mode 100644 index 0000000..1abd7dd --- /dev/null +++ b/src/vm/asmjit/helper_func.h @@ -0,0 +1,474 @@ + + +x86::Mem get_reg_ptr(jit_holder& jh, unsigned idx){ + + x86::Gp tmp_ptr = jh.cc.newUIntPtr("tmp_ptr"); + jh.cc.mov(tmp_ptr, jh.regs_base_ptr); + jh.cc.add(tmp_ptr, traits::reg_byte_offsets[idx]); + switch(traits::reg_bit_widths[idx]){ + case 8: + return x86::ptr_8(tmp_ptr); + case 16: + return x86::ptr_16(tmp_ptr); + case 32: + return x86::ptr_32(tmp_ptr); + case 64: + return x86::ptr_64(tmp_ptr); + default: + throw std::runtime_error("Invalid reg size in get_reg_ptr"); + } +} +x86::Gp get_reg_for(jit_holder& jh, unsigned idx){ + //can check for regs in jh and return them instead of creating new ones + switch(traits::reg_bit_widths[idx]){ + case 8: + return jh.cc.newInt8(); + case 16: + return jh.cc.newInt16(); + case 32: + return jh.cc.newInt32(); + case 64: + return jh.cc.newInt64(); + default: + throw std::runtime_error("Invalid reg size in get_reg_ptr"); + } +} +x86::Gp get_reg_for(jit_holder& jh, unsigned size, bool is_signed){ + if(is_signed) + switch(size){ + case 8: + return jh.cc.newInt8(); + case 16: + return jh.cc.newInt16(); + case 32: + return jh.cc.newInt32(); + case 64: + return jh.cc.newInt64(); + default: + throw std::runtime_error("Invalid reg size in get_reg_ptr"); + } + else + switch(size){ + case 8: + return jh.cc.newUInt8(); + case 16: + return jh.cc.newUInt16(); + case 32: + return jh.cc.newUInt32(); + case 64: + return jh.cc.newUInt64(); + default: + throw std::runtime_error("Invalid reg size in get_reg_ptr"); + } +} +inline x86::Gp load_reg_from_mem(jit_holder& jh, unsigned idx){ + auto ptr = get_reg_ptr(jh, idx); + auto reg = get_reg_for(jh, idx); + jh.cc.mov(reg, ptr); + return reg; +} +inline void write_reg_to_mem(jit_holder& jh, x86::Gp reg, unsigned idx){ + auto ptr = get_reg_ptr(jh, idx); + jh.cc.mov(ptr, reg); +} + +void gen_instr_prologue(jit_holder& jh, addr_t pc){ + auto& cc = jh.cc; + + cc.comment("\n//(*icount)++;"); + cc.inc(get_reg_ptr(jh, traits::ICOUNT)); + + cc.comment("\n//*pc=*next_pc;"); + cc.mov(get_reg_ptr(jh, traits::PC), jh.next_pc); + + cc.comment("\n//*trap_state=*pending_trap;"); + cc.mov(get_reg_ptr(jh, traits::PENDING_TRAP), jh.trap_state); + + cc.comment("\n//increment *next_pc"); + cc.mov(jh.next_pc, pc); + +} +void gen_instr_epilogue(jit_holder& jh){ + auto& cc = jh.cc; + + cc.comment("\n//if(*trap_state!=0) goto trap_entry;"); + cc.test(jh.trap_state, jh.trap_state); + cc.jnz(jh.trap_entry); + + //Does this need to be done after every single instruction? + cc.comment("\n//write back regs to mem"); + write_reg_to_mem(jh, jh.pc, traits::PC); + write_reg_to_mem(jh, jh.next_pc, traits::NEXT_PC); + write_reg_to_mem(jh, jh.trap_state, traits::TRAP_STATE); + + +} +void gen_block_prologue(jit_holder& jh) override{ + + jh.pc = load_reg_from_mem(jh, traits::PC); + jh.next_pc = load_reg_from_mem(jh, traits::NEXT_PC); + jh.trap_state = load_reg_from_mem(jh, traits::TRAP_STATE); +} +void gen_block_epilogue(jit_holder& jh) override{ + x86::Compiler& cc = jh.cc; + cc.comment("\n//return *next_pc;"); + cc.ret(jh.next_pc); + + cc.bind(jh.trap_entry); + cc.comment("\n//enter_trap(core_ptr, *trap_state, *pc, 0);"); + + x86::Gp current_trap_state = get_reg_for(jh, traits::TRAP_STATE); + cc.mov(current_trap_state, get_reg_ptr(jh, traits::TRAP_STATE)); + + x86::Gp current_pc = get_reg_for(jh, traits::PC); + cc.mov(current_pc, get_reg_ptr(jh, traits::PC)); + + x86::Gp instr = cc.newInt32("instr"); + cc.mov(instr, 0); + InvokeNode* call_enter_trap; + cc.invoke(&call_enter_trap, &enter_trap, FuncSignatureT()); + call_enter_trap->setArg(0, jh.arch_if_ptr); + call_enter_trap->setArg(1, current_trap_state); + call_enter_trap->setArg(2, current_pc); + call_enter_trap->setArg(3, instr); + cc.comment("\n//*last_branch = std::numeric_limits::max();"); + cc.mov(get_reg_ptr(jh,traits::LAST_BRANCH), std::numeric_limits::max()); + cc.comment("\n//return *next_pc;"); + cc.ret(jh.next_pc); + +} +//TODO implement + +void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) { + jh.cc.comment("//gen_raise"); +} +void gen_wait(jit_holder& jh, unsigned type) { + jh.cc.comment("//gen_wait"); +} +void gen_leave(jit_holder& jh, unsigned lvl){ + jh.cc.comment("//gen_leave"); +} + +enum operation {add, sub, band, bor, bxor, shl, sar , shr}; + +template ::value || std::is_same::value>> +x86::Gp gen_operation(jit_holder& jh, operation op, x86::Gp a, T b){ + x86::Compiler& cc = jh.cc; + switch (op) { + case add: { cc.add(a, b); break; } + case sub: { cc.sub(a, b); break; } + case band: { cc.and_(a, b); break; } + case bor: { cc.or_(a, b); break; } + case bxor: { cc.xor_(a, b); break; } + case shl: { cc.shl(a, b); break; } + case sar: { cc.sar(a, b); break; } + case shr: { cc.shr(a, b); break; } + default: throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (operation)", op)); + } + return a; +} + +enum three_operand_operation{imul, mul, idiv, div, srem, urem}; + +x86::Gp gen_operation(jit_holder& jh, three_operand_operation op, x86::Gp a, x86::Gp b){ + x86::Compiler& cc = jh.cc; + switch (op) { + case imul: { + x86::Gp dummy = cc.newInt64(); + cc.imul(dummy, a.r64(), b.r64()); + return a; + } + case mul: { + x86::Gp dummy = cc.newInt64(); + cc.mul(dummy, a.r64(), b.r64()); + return a; + } + case idiv: { + x86::Gp dummy = cc.newInt64(); + cc.mov(dummy, 0); + cc.idiv(dummy, a.r64(), b.r64()); + return a; + } + case div: { + x86::Gp dummy = cc.newInt64(); + cc.mov(dummy, 0); + cc.div(dummy, a.r64(), b.r64()); + return a; + } + case srem:{ + x86::Gp rem = cc.newInt32(); + cc.mov(rem, 0); + auto a_reg = cc.newInt32(); + cc.mov(a_reg, a.r32()); + cc.idiv(rem, a_reg, b.r32()); + return rem; + } + case urem:{ + x86::Gp rem = cc.newInt32(); + cc.mov(rem, 0); + auto a_reg = cc.newInt32(); + cc.mov(a_reg, a.r32()); + cc.div(rem, a_reg, b.r32()); + return rem; + } + + default: throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (three_operand)", op)); + } + return a; +} +template ::value>> +x86::Gp gen_operation(jit_holder& jh, three_operand_operation op, x86::Gp a, T b){ + x86::Gp b_reg = jh.cc.newInt32(); +/* switch(a.size()){ + case 1: b_reg = jh.cc.newInt8(); break; + case 2: b_reg = jh.cc.newInt16(); break; + case 4: b_reg = jh.cc.newInt32(); break; + case 8: b_reg = jh.cc.newInt64(); break; + default: throw std::runtime_error(fmt::format("Invalid size ({}) in gen operation", a.size())); + } */ + jh.cc.mov(b_reg, b); + return gen_operation(jh, op, a, b_reg); +} +enum comparison_operation{land, lor, eq, ne, lt, ltu, gt, gtu, lte, lteu, gte, gteu}; + +template ::value || std::is_same::value>> +x86::Gp gen_operation(jit_holder& jh, comparison_operation op, x86::Gp a, T b){ + x86::Compiler& cc = jh.cc; + x86::Gp tmp = cc.newInt8(); + cc.mov(tmp,1); + Label label_then = cc.newLabel(); + cc.cmp(a,b); + switch (op) { + case eq: cc.je(label_then); break; + case ne: cc.jne(label_then); break; + case lt: cc.jl(label_then); break; + case ltu: cc.jb(label_then); break; + case gt: cc.jg(label_then); break; + case gtu: cc.ja(label_then); break; + case lte: cc.jle(label_then); break; + case lteu: cc.jbe(label_then); break; + case gte: cc.jge(label_then); break; + case gteu: cc.jae(label_then); break; + case land: { + Label label_false = cc.newLabel(); + cc.cmp(a, 0); + cc.je(label_false); + auto b_reg = cc.newInt8(); + cc.mov(b_reg, b); + cc.cmp(b_reg, 0); + cc.je(label_false); + cc.jmp(label_then); + cc.bind(label_false); + break; + } + case lor: { + cc.cmp(a, 0); + cc.jne(label_then); + auto b_reg = cc.newInt8(); + cc.mov(b_reg, b); + cc.cmp(b_reg, 0); + cc.jne(label_then); + break; + } + default: throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (comparison)", op)); + } + cc.mov(tmp,0); + cc.bind(label_then); + return tmp; +} +enum binary_operation{lnot, inc, dec, bnot, neg}; + +x86::Gp gen_operation(jit_holder& jh, binary_operation op, x86::Gp a){ + x86::Compiler& cc = jh.cc; + switch (op) { + case lnot: throw std::runtime_error("Current operation not supported in gen_operation(lnot)"); + case inc: { cc.inc(a); break; } + case dec: { cc.dec(a); break; } + case bnot: { cc.not_(a); break; } + case neg: { cc.neg(a); break; } + default: throw std::runtime_error(fmt::format("Current operation {} not supported in gen_operation (unary)", op)); + } + return a; +} + +/* template +inline typename std::enable_if_t::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) const { + auto val_reg = get_reg_for(jh, sizeof(val)*8); + auto tmp = get_reg_for(jh, size); + jh.cc.mov(val_reg, val); + if(is_signed) jh.cc.movsx(tmp, val_reg); + else jh.cc.movzx(tmp,val_reg); + return tmp; +} + +template +inline typename std::enable_if_t::value, x86::Gp> gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) const { + auto val_reg = get_reg_for(jh, sizeof(val)*8); + auto tmp = get_reg_for(jh, size); + jh.cc.mov(val_reg, val); + if(is_signed) jh.cc.movsx(tmp, val_reg); + else jh.cc.movzx(tmp,val_reg); + return tmp; +} */ +template ::value>> +inline x86::Gp gen_ext(jit_holder& jh, T val, unsigned size, bool is_signed) { + auto val_reg = get_reg_for(jh, sizeof(val)*8); + jh.cc.mov(val_reg, val); + return gen_ext(jh, val_reg, size, is_signed); +} +//explicit Gp size cast +inline x86::Gp gen_ext(jit_holder& jh, x86::Gp val, unsigned size, bool is_signed) { + auto& cc = jh.cc; + if(is_signed){ + switch(val.size()){ + case 1: cc.cbw(val); break; + case 2: cc.cwde(val); break; + case 4: cc.cdqe(val); break; + case 8: break; + default: throw std::runtime_error("Invalid register size in gen_ext"); + } + } + switch(size){ + case 8: cc.and_(val,std::numeric_limits::max()); return val.r8(); + case 16: cc.and_(val,std::numeric_limits::max()); return val.r16(); + case 32: cc.and_(val,std::numeric_limits::max()); return val.r32(); + case 64: cc.and_(val,std::numeric_limits::max()); return val.r64(); + case 128: return val.r64(); + default: throw std::runtime_error("Invalid size in gen_ext"); + } +} + +inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, uint32_t length){ + x86::Compiler& cc = jh.cc; + auto ret_reg = cc.newInt32(); + + auto mem_type_reg = cc.newInt32(); + cc.mov(mem_type_reg, type); + + auto space_reg = cc.newInt32(); + cc.mov(space_reg, static_cast(iss::address_type::VIRTUAL)); + + auto val_ptr = cc.newUIntPtr(); + cc.mov(val_ptr, read_mem_buf); + + InvokeNode* invokeNode; + uint64_t mask = 0; + x86::Gp val_reg = cc.newInt64(); + + switch(length){ + case 1:{ + cc.invoke(&invokeNode, &read_mem1, FuncSignatureT()); + mask = std::numeric_limits::max(); + break; + } + case 2:{ + cc.invoke(&invokeNode, &read_mem2, FuncSignatureT()); + mask = std::numeric_limits::max(); + break; + } + case 4:{ + cc.invoke(&invokeNode, &read_mem4, FuncSignatureT()); + mask = std::numeric_limits::max(); + break; + } + case 8:{ + cc.invoke(&invokeNode, &read_mem8, FuncSignatureT()); + mask = std::numeric_limits::max(); + break; + } + default: throw std::runtime_error(fmt::format("Invalid length ({}) in gen_read_mem",length)); + } + + invokeNode->setRet(0, ret_reg); + invokeNode->setArg(0, jh.arch_if_ptr); + invokeNode->setArg(1, space_reg); + invokeNode->setArg(2, mem_type_reg); + invokeNode->setArg(3, addr); + invokeNode->setArg(4, val_ptr); + + cc.mov(val_reg, x86::ptr_64(val_ptr)); + cc.and_(val_reg, mask); + cc.cmp(ret_reg,0); + cc.jne(jh.trap_entry); + return val_reg; +} +inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp length){ + uint32_t length_val = 0; + auto length_ptr = jh.cc.newIntPtr(); + jh.cc.mov(length_ptr, &length_val); + jh.cc.mov(x86::ptr_32(length_ptr),length); + + return gen_read_mem(jh, type, addr, length); +} +inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp length){ + auto addr_reg = jh.cc.newInt64(); + jh.cc.mov(addr_reg, addr); + + uint32_t length_val = 0; + auto length_ptr = jh.cc.newIntPtr(); + jh.cc.mov(length_ptr, &length_val); + jh.cc.mov(x86::ptr_32(length_ptr),length); + + return gen_read_mem(jh, type, addr_reg, length_val); +} +inline x86::Gp gen_read_mem(jit_holder& jh, mem_type_e type, uint64_t addr, uint32_t length){ + auto addr_reg = jh.cc.newInt64(); + jh.cc.mov(addr_reg, addr); + + return gen_read_mem(jh, type, addr_reg, length); +} +inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, int64_t val){ + auto val_reg = jh.cc.newInt64(); + jh.cc.mov(val_reg, val); + gen_write_mem(jh, type, addr, val_reg); + +} +inline void gen_write_mem(jit_holder& jh, mem_type_e type, x86::Gp addr, x86::Gp val){ + x86::Compiler& cc = jh.cc; + + auto mem_type_reg = cc.newInt32(); + jh.cc.mov(mem_type_reg, type); + auto space_reg = cc.newInt32(); + jh.cc.mov(space_reg, static_cast(iss::address_type::VIRTUAL)); + auto ret_reg = cc.newInt32(); + InvokeNode* invokeNode; + + if(val.isGpb()){ + cc.invoke(&invokeNode, &write_mem1, FuncSignatureT()); + } + else if(val.isGpw()){ + cc.invoke(&invokeNode, &write_mem2, FuncSignatureT()); + } + else if(val.isGpd()){ + cc.invoke(&invokeNode, &write_mem4, FuncSignatureT()); + } + else if(val.isGpq()){ + cc.invoke(&invokeNode, &write_mem8, FuncSignatureT()); + } + else throw std::runtime_error("Invalid register size in gen_write_mem"); + + invokeNode->setRet(0,ret_reg); + invokeNode->setArg(0, jh.arch_if_ptr); + invokeNode->setArg(1, space_reg); + invokeNode->setArg(2, mem_type_reg); + invokeNode->setArg(3, addr); + invokeNode->setArg(4, val); + + cc.cmp(ret_reg,0); + cc.jne(jh.trap_entry); + +} +inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, x86::Gp val){ + auto addr_reg = jh.cc.newInt64(); + jh.cc.mov(addr_reg, addr); + gen_write_mem(jh, type, addr_reg, val); +} +inline void gen_write_mem(jit_holder& jh, mem_type_e type, uint64_t addr, int64_t val){ + auto val_reg = jh.cc.newInt64(); + jh.cc.mov(val_reg, val); + + auto addr_reg = jh.cc.newInt64(); + jh.cc.mov(addr_reg, addr); + gen_write_mem(jh, type, addr_reg, val_reg); + +} \ No newline at end of file diff --git a/src/vm/asmjit/vm_tgc5c.cpp b/src/vm/asmjit/vm_tgc5c.cpp new file mode 100644 index 0000000..c50aedc --- /dev/null +++ b/src/vm/asmjit/vm_tgc5c.cpp @@ -0,0 +1,3786 @@ +/******************************************************************************* + * Copyright (C) 2017, 2023 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef FMT_HEADER_ONLY +#define FMT_HEADER_ONLY +#endif +#include + +#include +#include + +namespace iss { +namespace asmjit { + + +namespace tgc5c { +using namespace ::asmjit; +using namespace iss::arch; +using namespace iss::debugger; + +template class vm_impl : public iss::asmjit::vm_base { +public: + using traits = arch::traits; + using super = typename iss::asmjit::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 mem_type_e = typename super::mem_type_e; + using addr_t = typename super::addr_t; + + vm_impl(); + + vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); + + void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } + + target_adapter_if *accquire_target_adapter(server_if *srv) override { + debugger_if::dbg_enabled = true; + if (vm_base::tgt_adapter == nullptr) + vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return vm_base::tgt_adapter; + } + +protected: + using vm_base::get_reg_ptr; + using this_class = vm_impl; + using compile_func = continuation_e (this_class::*)(virt_addr_t&, code_word_t, jit_holder&); + + continuation_e gen_single_inst_behavior(virt_addr_t&, unsigned int &, jit_holder&) override; + inline const char *name(size_t index){return traits::reg_aliases.at(index);} + + template::type> + inline S sext(U from) { + auto mask = (1ULL< instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) : value(value){} + }; + + decoding_tree_node* root {nullptr}; + + const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */ + /* instruction LUI, encoding '0b00000000000000000000000000110111' */ + {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, + /* instruction AUIPC, encoding '0b00000000000000000000000000010111' */ + {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, + /* instruction JAL, encoding '0b00000000000000000000000001101111' */ + {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, + /* instruction JALR, encoding '0b00000000000000000000000001100111' */ + {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, + /* instruction BEQ, encoding '0b00000000000000000000000001100011' */ + {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, + /* instruction BNE, encoding '0b00000000000000000001000001100011' */ + {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, + /* instruction BLT, encoding '0b00000000000000000100000001100011' */ + {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, + /* instruction BGE, encoding '0b00000000000000000101000001100011' */ + {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, + /* instruction BLTU, encoding '0b00000000000000000110000001100011' */ + {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, + /* instruction BGEU, encoding '0b00000000000000000111000001100011' */ + {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, + /* instruction LB, encoding '0b00000000000000000000000000000011' */ + {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, + /* instruction LH, encoding '0b00000000000000000001000000000011' */ + {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, + /* instruction LW, encoding '0b00000000000000000010000000000011' */ + {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, + /* instruction LBU, encoding '0b00000000000000000100000000000011' */ + {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, + /* instruction LHU, encoding '0b00000000000000000101000000000011' */ + {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, + /* instruction SB, encoding '0b00000000000000000000000000100011' */ + {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, + /* instruction SH, encoding '0b00000000000000000001000000100011' */ + {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, + /* instruction SW, encoding '0b00000000000000000010000000100011' */ + {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, + /* instruction ADDI, encoding '0b00000000000000000000000000010011' */ + {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, + /* instruction SLTI, encoding '0b00000000000000000010000000010011' */ + {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, + /* instruction SLTIU, encoding '0b00000000000000000011000000010011' */ + {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, + /* instruction XORI, encoding '0b00000000000000000100000000010011' */ + {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, + /* instruction ORI, encoding '0b00000000000000000110000000010011' */ + {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, + /* instruction ANDI, encoding '0b00000000000000000111000000010011' */ + {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, + /* instruction SLLI, encoding '0b00000000000000000001000000010011' */ + {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, + /* instruction SRLI, encoding '0b00000000000000000101000000010011' */ + {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, + /* instruction SRAI, encoding '0b01000000000000000101000000010011' */ + {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, + /* instruction ADD, encoding '0b00000000000000000000000000110011' */ + {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, + /* instruction SUB, encoding '0b01000000000000000000000000110011' */ + {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, + /* instruction SLL, encoding '0b00000000000000000001000000110011' */ + {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, + /* instruction SLT, encoding '0b00000000000000000010000000110011' */ + {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, + /* instruction SLTU, encoding '0b00000000000000000011000000110011' */ + {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, + /* instruction XOR, encoding '0b00000000000000000100000000110011' */ + {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, + /* instruction SRL, encoding '0b00000000000000000101000000110011' */ + {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, + /* instruction SRA, encoding '0b01000000000000000101000000110011' */ + {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, + /* instruction OR, encoding '0b00000000000000000110000000110011' */ + {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, + /* instruction AND, encoding '0b00000000000000000111000000110011' */ + {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, + /* instruction FENCE, encoding '0b00000000000000000000000000001111' */ + {32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, &this_class::__fence}, + /* instruction ECALL, encoding '0b00000000000000000000000001110011' */ + {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, + /* instruction EBREAK, encoding '0b00000000000100000000000001110011' */ + {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, + /* instruction MRET, encoding '0b00110000001000000000000001110011' */ + {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, + /* instruction WFI, encoding '0b00010000010100000000000001110011' */ + {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, + /* instruction CSRRW, encoding '0b00000000000000000001000001110011' */ + {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, + /* instruction CSRRS, encoding '0b00000000000000000010000001110011' */ + {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, + /* instruction CSRRC, encoding '0b00000000000000000011000001110011' */ + {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, + /* instruction CSRRWI, encoding '0b00000000000000000101000001110011' */ + {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, + /* instruction CSRRSI, encoding '0b00000000000000000110000001110011' */ + {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, + /* instruction CSRRCI, encoding '0b00000000000000000111000001110011' */ + {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, + /* instruction FENCE_I, encoding '0b00000000000000000001000000001111' */ + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, + /* instruction MUL, encoding '0b00000010000000000000000000110011' */ + {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, + /* instruction MULH, encoding '0b00000010000000000001000000110011' */ + {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, + /* instruction MULHSU, encoding '0b00000010000000000010000000110011' */ + {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, + /* instruction MULHU, encoding '0b00000010000000000011000000110011' */ + {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, + /* instruction DIV, encoding '0b00000010000000000100000000110011' */ + {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, + /* instruction DIVU, encoding '0b00000010000000000101000000110011' */ + {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, + /* instruction REM, encoding '0b00000010000000000110000000110011' */ + {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, + /* instruction REMU, encoding '0b00000010000000000111000000110011' */ + {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, + /* instruction C__ADDI4SPN, encoding '0b0000000000000000' */ + {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c__addi4spn}, + /* instruction C__LW, encoding '0b0100000000000000' */ + {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c__lw}, + /* instruction C__SW, encoding '0b1100000000000000' */ + {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c__sw}, + /* instruction C__ADDI, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c__addi}, + /* instruction C__NOP, encoding '0b0000000000000001' */ + {16, 0b0000000000000001, 0b1110111110000011, &this_class::__c__nop}, + /* instruction C__JAL, encoding '0b0010000000000001' */ + {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c__jal}, + /* instruction C__LI, encoding '0b0100000000000001' */ + {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c__li}, + /* instruction C__LUI, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c__lui}, + /* instruction C__ADDI16SP, encoding '0b0110000100000001' */ + {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c__addi16sp}, + /* instruction __reserved_clui, encoding '0b0110000000000001' */ + {16, 0b0110000000000001, 0b1111000001111111, &this_class::____reserved_clui}, + /* instruction C__SRLI, encoding '0b1000000000000001' */ + {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c__srli}, + /* instruction C__SRAI, encoding '0b1000010000000001' */ + {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c__srai}, + /* instruction C__ANDI, encoding '0b1000100000000001' */ + {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c__andi}, + /* instruction C__SUB, encoding '0b1000110000000001' */ + {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c__sub}, + /* instruction C__XOR, encoding '0b1000110000100001' */ + {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c__xor}, + /* instruction C__OR, encoding '0b1000110001000001' */ + {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c__or}, + /* instruction C__AND, encoding '0b1000110001100001' */ + {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c__and}, + /* instruction C__J, encoding '0b1010000000000001' */ + {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c__j}, + /* instruction C__BEQZ, encoding '0b1100000000000001' */ + {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c__beqz}, + /* instruction C__BNEZ, encoding '0b1110000000000001' */ + {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c__bnez}, + /* instruction C__SLLI, encoding '0b0000000000000010' */ + {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c__slli}, + /* instruction C__LWSP, encoding '0b0100000000000010' */ + {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c__lwsp}, + /* instruction C__MV, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c__mv}, + /* instruction C__JR, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c__jr}, + /* instruction __reserved_cmv, encoding '0b1000000000000010' */ + {16, 0b1000000000000010, 0b1111111111111111, &this_class::____reserved_cmv}, + /* instruction C__ADD, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c__add}, + /* instruction C__JALR, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c__jalr}, + /* instruction C__EBREAK, encoding '0b1001000000000010' */ + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c__ebreak}, + /* instruction C__SWSP, encoding '0b1100000000000010' */ + {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c__swsp}, + /* instruction DII, encoding '0b0000000000000000' */ + {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, + }}; + + /* instruction definitions */ + /* instruction 0: LUI */ + continuation_e __lui(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nLUI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 0); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + (uint32_t)((int32_t)imm)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 0); + return returnValue; + } + + /* instruction 1: AUIPC */ + continuation_e __auipc(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,20>(instr) << 12)); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nAUIPC_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 1); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + (uint32_t)(PC+(int32_t)imm)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 1); + return returnValue; + } + + /* instruction 2: JAL */ + continuation_e __jal(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint32_t imm = ((bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (bit_sub<31,1>(instr) << 20)); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nJAL_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 2); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ gen_raise(jh, 0, 0); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + (uint32_t)(PC+ 4)); + } + auto PC_val_v = (uint32_t)(PC+(int32_t)sext<21>(imm)); + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + } + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 2); + return returnValue; + } + + /* instruction 3: JALR */ + continuation_e __jalr(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nJALR_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 3); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto addr_mask = (uint32_t)- 2; + auto new_pc = gen_ext(jh, + (gen_operation(jh, band, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, (int16_t)sext<12>(imm), 64, true)) + ), gen_ext(jh, addr_mask, 64, false)) + ), 32, true); + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, urem, + new_pc, static_cast(traits::INSTR_ALIGNMENT)) + ,0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + gen_raise(jh, 0, 0); + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + (uint32_t)(PC+ 4)); + } + auto PC_val_v = new_pc; + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + cc.bind(label_merge); + } + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 3); + return returnValue; + } + + /* instruction 4: BEQ */ + continuation_e __beq(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nBEQ_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 4); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, eq, + load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2)) + ,0); + cc.je(label_merge); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ gen_raise(jh, 0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + } + cc.bind(label_merge); + } + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 4); + return returnValue; + } + + /* instruction 5: BNE */ + continuation_e __bne(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nBNE_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 5); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, ne, + load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2)) + ,0); + cc.je(label_merge); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ gen_raise(jh, 0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + } + cc.bind(label_merge); + } + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 5); + return returnValue; + } + + /* instruction 6: BLT */ + continuation_e __blt(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nBLT_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 6); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, lt, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 32, false), gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 32, false)) + ,0); + cc.je(label_merge); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ gen_raise(jh, 0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + } + cc.bind(label_merge); + } + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 6); + return returnValue; + } + + /* instruction 7: BGE */ + continuation_e __bge(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nBGE_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 7); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, gte, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 32, false), gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 32, false)) + ,0); + cc.je(label_merge); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ gen_raise(jh, 0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + } + cc.bind(label_merge); + } + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 7); + return returnValue; + } + + /* instruction 8: BLTU */ + continuation_e __bltu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nBLTU_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 8); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, ltu, + load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2)) + ,0); + cc.je(label_merge); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ gen_raise(jh, 0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + } + cc.bind(label_merge); + } + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 8); + return returnValue; + } + + /* instruction 9: BGEU */ + continuation_e __bgeu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (bit_sub<31,1>(instr) << 12)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nBGEU_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 9); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, gteu, + load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2)) + ,0); + cc.je(label_merge); + { + if(imm%static_cast(traits::INSTR_ALIGNMENT)){ gen_raise(jh, 0, 0); + } + else{ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<13>(imm)); + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + } + cc.bind(label_merge); + } + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 9); + return returnValue; + } + + /* instruction 10: LB */ + continuation_e __lb(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nLB_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 10); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto load_address = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, (int16_t)sext<12>(imm), 64, true)) + ), 32, true); + auto res = gen_ext(jh, + gen_read_mem(jh, traits::MEM, load_address, 1), 8, false); + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + res, 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 10); + return returnValue; + } + + /* instruction 11: LH */ + continuation_e __lh(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nLH_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 11); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto load_address = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, (int16_t)sext<12>(imm), 64, true)) + ), 32, true); + auto res = gen_ext(jh, + gen_read_mem(jh, traits::MEM, load_address, 2), 16, false); + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + res, 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 11); + return returnValue; + } + + /* instruction 12: LW */ + continuation_e __lw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nLW_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 12); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto load_address = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, (int16_t)sext<12>(imm), 64, true)) + ), 32, true); + auto res = gen_ext(jh, + gen_read_mem(jh, traits::MEM, load_address, 4), 32, false); + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + res, 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 12); + return returnValue; + } + + /* instruction 13: LBU */ + continuation_e __lbu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nLBU_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 13); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto load_address = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, (int16_t)sext<12>(imm), 64, true)) + ), 32, true); + auto res = gen_read_mem(jh, traits::MEM, load_address, 1); + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + res, 32, false)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 13); + return returnValue; + } + + /* instruction 14: LHU */ + continuation_e __lhu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nLHU_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 14); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto load_address = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, (int16_t)sext<12>(imm), 64, true)) + ), 32, true); + auto res = gen_read_mem(jh, traits::MEM, load_address, 2); + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + res, 32, false)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 14); + return returnValue; + } + + /* instruction 15: SB */ + continuation_e __sb(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSB_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 15); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto store_address = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, (int16_t)sext<12>(imm), 64, true)) + ), 32, true); + gen_write_mem(jh, traits::MEM, + store_address, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 8, false)); + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 15); + return returnValue; + } + + /* instruction 16: SH */ + continuation_e __sh(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSH_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 16); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto store_address = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, (int16_t)sext<12>(imm), 64, true)) + ), 32, true); + gen_write_mem(jh, traits::MEM, + store_address, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 16, false)); + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 16); + return returnValue; + } + + /* instruction 17: SW */ + continuation_e __sw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<7,5>(instr)) | (bit_sub<25,7>(instr) << 5)); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSW_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 17); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto store_address = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, (int16_t)sext<12>(imm), 64, true)) + ), 32, true); + gen_write_mem(jh, traits::MEM, + store_address, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 32, false)); + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 17); + return returnValue; + } + + /* instruction 18: ADDI */ + continuation_e __addi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nADDI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 18); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, (int16_t)sext<12>(imm), 64, true)) + ), 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 18); + return returnValue; + } + + /* instruction 19: SLTI */ + continuation_e __slti(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSLTI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 19); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + { + auto label_then = cc.newLabel(); + auto label_merge = cc.newLabel(); + auto tmp_reg = get_reg_for(jh, 1); + cc.cmp(gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 32, true), (int16_t)sext<12>(imm)); + cc.jl(label_then); + cc.mov(tmp_reg, 0); + cc.jmp(label_merge); + cc.bind(label_then); + cc.mov(tmp_reg, 1); + cc.bind(label_merge); + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, tmp_reg + , 32, false) + ); + } + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 19); + return returnValue; + } + + /* instruction 20: SLTIU */ + continuation_e __sltiu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSLTIU_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 20); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + { + auto label_then = cc.newLabel(); + auto label_merge = cc.newLabel(); + auto tmp_reg = get_reg_for(jh, 1); + cc.cmp(load_reg_from_mem(jh, traits::X0 + rs1), (uint32_t)((int16_t)sext<12>(imm))); + cc.jb(label_then); + cc.mov(tmp_reg, 0); + cc.jmp(label_merge); + cc.bind(label_then); + cc.mov(tmp_reg, 1); + cc.bind(label_merge); + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, tmp_reg + , 32, false) + ); + } + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 20); + return returnValue; + } + + /* instruction 21: XORI */ + continuation_e __xori(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nXORI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 21); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_operation(jh, bxor, + load_reg_from_mem(jh, traits::X0 + rs1), (uint32_t)((int16_t)sext<12>(imm))) + ); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 21); + return returnValue; + } + + /* instruction 22: ORI */ + continuation_e __ori(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nORI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 22); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_operation(jh, bor, + load_reg_from_mem(jh, traits::X0 + rs1), (uint32_t)((int16_t)sext<12>(imm))) + ); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 22); + return returnValue; + } + + /* instruction 23: ANDI */ + continuation_e __andi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nANDI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 23); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_operation(jh, band, + load_reg_from_mem(jh, traits::X0 + rs1), (uint32_t)((int16_t)sext<12>(imm))) + ); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 23); + return returnValue; + } + + /* instruction 24: SLLI */ + continuation_e __slli(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSLLI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 24); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_operation(jh, shl, + load_reg_from_mem(jh, traits::X0 + rs1), gen_ext(jh, shamt, 32, false)) + ); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 24); + return returnValue; + } + + /* instruction 25: SRLI */ + continuation_e __srli(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSRLI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 25); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_operation(jh, shr, + load_reg_from_mem(jh, traits::X0 + rs1), gen_ext(jh, shamt, 32, false)) + ); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 25); + return returnValue; + } + + /* instruction 26: SRAI */ + continuation_e __srai(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t shamt = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSRAI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 26); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_operation(jh, sar, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 32, true), gen_ext(jh, shamt, 32, false)) + ), 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 26); + return returnValue; + } + + /* instruction 27: ADD */ + continuation_e __add(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nADD_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 27); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs2), 64, false)) + ), 32, false)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 27); + return returnValue; + } + + /* instruction 28: SUB */ + continuation_e __sub(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSUB_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 28); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_operation(jh, sub, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs2), 64, false)) + ), 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 28); + return returnValue; + } + + /* instruction 29: SLL */ + continuation_e __sll(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSLL_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 29); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, gen_operation(jh, shl, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), (gen_operation(jh, band, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs2), 64, false), (static_cast(traits::XLEN)- 1)) + )) + , 32, false)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 29); + return returnValue; + } + + /* instruction 30: SLT */ + continuation_e __slt(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSLT_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 30); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + { + auto label_then = cc.newLabel(); + auto label_merge = cc.newLabel(); + auto tmp_reg = get_reg_for(jh, 1); + cc.cmp(gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 32, true), gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 32, true)); + cc.jl(label_then); + cc.mov(tmp_reg, 0); + cc.jmp(label_merge); + cc.bind(label_then); + cc.mov(tmp_reg, 1); + cc.bind(label_merge); + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, tmp_reg + , 32, false) + ); + } + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 30); + return returnValue; + } + + /* instruction 31: SLTU */ + continuation_e __sltu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSLTU_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 31); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + { + auto label_then = cc.newLabel(); + auto label_merge = cc.newLabel(); + auto tmp_reg = get_reg_for(jh, 1); + cc.cmp(load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2)); + cc.jb(label_then); + cc.mov(tmp_reg, 0); + cc.jmp(label_merge); + cc.bind(label_then); + cc.mov(tmp_reg, 1); + cc.bind(label_merge); + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, tmp_reg + , 32, false) + ); + } + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 31); + return returnValue; + } + + /* instruction 32: XOR */ + continuation_e __xor(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nXOR_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 32); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_operation(jh, bxor, + load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2)) + ); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 32); + return returnValue; + } + + /* instruction 33: SRL */ + continuation_e __srl(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSRL_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 33); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, gen_operation(jh, shr, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), (gen_operation(jh, band, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs2), 64, false), (static_cast(traits::XLEN)- 1)) + )) + , 32, false)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 33); + return returnValue; + } + + /* instruction 34: SRA */ + continuation_e __sra(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nSRA_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 34); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_ext(jh, gen_operation(jh, sar, + gen_ext(jh, gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 32, true), 64, true), (gen_operation(jh, band, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs2), 64, false), (static_cast(traits::XLEN)- 1)) + )) + , 32, true)), 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 34); + return returnValue; + } + + /* instruction 35: OR */ + continuation_e __or(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nOR_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 35); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_operation(jh, bor, + load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2)) + ); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 35); + return returnValue; + } + + /* instruction 36: AND */ + continuation_e __and(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nAND_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 36); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_operation(jh, band, + load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2)) + ); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 36); + return returnValue; + } + + /* instruction 37: FENCE */ + continuation_e __fence(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t succ = ((bit_sub<20,4>(instr))); + uint8_t pred = ((bit_sub<24,4>(instr))); + uint8_t fm = ((bit_sub<28,4>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nFENCE_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 37); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + gen_write_mem(jh, traits::FENCE, + static_cast(traits::fence), + (uint8_t)pred<< 4|succ); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 37); + return returnValue; + } + + /* instruction 38: ECALL */ + continuation_e __ecall(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nECALL_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 38); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + gen_raise(jh, 0, 11); + auto returnValue = TRAP; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 38); + return returnValue; + } + + /* instruction 39: EBREAK */ + continuation_e __ebreak(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nEBREAK_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 39); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + gen_raise(jh, 0, 3); + auto returnValue = TRAP; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 39); + return returnValue; + } + + /* instruction 40: MRET */ + continuation_e __mret(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nMRET_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 40); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + gen_leave(jh, 3); + auto returnValue = TRAP; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 40); + return returnValue; + } + + /* instruction 41: WFI */ + continuation_e __wfi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nWFI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 41); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + gen_wait(jh, 1); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 41); + return returnValue; + } + + /* instruction 42: CSRRW */ + continuation_e __csrrw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nCSRRW_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 42); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto xrs1 = load_reg_from_mem(jh, traits::X0 + rs1); + if(rd!= 0){ auto xrd = gen_read_mem(jh, traits::CSR, csr, 4); + gen_write_mem(jh, traits::CSR, + csr, + xrs1); + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + xrd); + } + else{ + gen_write_mem(jh, traits::CSR, + csr, + xrs1); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 42); + return returnValue; + } + + /* instruction 43: CSRRS */ + continuation_e __csrrs(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nCSRRS_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 43); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto xrd = gen_read_mem(jh, traits::CSR, csr, 4); + auto xrs1 = load_reg_from_mem(jh, traits::X0 + rs1); + if(rs1!= 0) { + gen_write_mem(jh, traits::CSR, + csr, + gen_operation(jh, bor, + xrd, xrs1) + ); + } + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + xrd); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 43); + return returnValue; + } + + /* instruction 44: CSRRC */ + continuation_e __csrrc(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nCSRRC_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 44); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto xrd = gen_read_mem(jh, traits::CSR, csr, 4); + auto xrs1 = load_reg_from_mem(jh, traits::X0 + rs1); + if(rs1!= 0) { + gen_write_mem(jh, traits::CSR, + csr, + gen_operation(jh, band, + xrd, gen_operation(jh, bnot, xrs1)) + ); + } + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + xrd); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 44); + return returnValue; + } + + /* instruction 45: CSRRWI */ + continuation_e __csrrwi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nCSRRWI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 45); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto xrd = gen_read_mem(jh, traits::CSR, csr, 4); + gen_write_mem(jh, traits::CSR, + csr, + (uint32_t)zimm); + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + xrd); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 45); + return returnValue; + } + + /* instruction 46: CSRRSI */ + continuation_e __csrrsi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nCSRRSI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 46); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto xrd = gen_read_mem(jh, traits::CSR, csr, 4); + if(zimm!= 0) { + gen_write_mem(jh, traits::CSR, + csr, + gen_operation(jh, bor, + xrd, (uint32_t)zimm) + ); + } + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + xrd); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 46); + return returnValue; + } + + /* instruction 47: CSRRCI */ + continuation_e __csrrci(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t zimm = ((bit_sub<15,5>(instr))); + uint16_t csr = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nCSRRCI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 47); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto xrd = gen_read_mem(jh, traits::CSR, csr, 4); + if(zimm!= 0) { + gen_write_mem(jh, traits::CSR, + csr, + gen_operation(jh, band, + xrd, ~ ((uint32_t)zimm)) + ); + } + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + xrd); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 47); + return returnValue; + } + + /* instruction 48: FENCE_I */ + continuation_e __fence_i(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nFENCE_I_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 48); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + gen_write_mem(jh, traits::FENCE, + static_cast(traits::fencei), + imm); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 48); + return returnValue; + } + + /* instruction 49: MUL */ + continuation_e __mul(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nMUL_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 49); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto res = gen_ext(jh, + (gen_operation(jh, imul, + gen_ext(jh, gen_ext(jh, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 32, true), 64, true), 128, true), gen_ext(jh, gen_ext(jh, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 32, true), 64, true), 128, true)) + ), 64, true); + if(rd!=0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + res, 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 49); + return returnValue; + } + + /* instruction 50: MULH */ + continuation_e __mulh(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nMULH_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 50); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto res = gen_ext(jh, + (gen_operation(jh, imul, + gen_ext(jh, gen_ext(jh, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 32, true), 64, true), 128, true), gen_ext(jh, gen_ext(jh, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 32, true), 64, true), 128, true)) + ), 64, true); + if(rd!=0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_operation(jh, sar, + res, gen_ext(jh, static_cast(traits::XLEN), 64, false)) + ), 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 50); + return returnValue; + } + + /* instruction 51: MULHSU */ + continuation_e __mulhsu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nMULHSU_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 51); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto res = gen_ext(jh, + (gen_operation(jh, imul, + gen_ext(jh, gen_ext(jh, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 32, true), 64, true), 128, true), gen_ext(jh, gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 64, false), 128, false)) + ), 64, true); + if(rd!=0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_operation(jh, sar, + res, gen_ext(jh, static_cast(traits::XLEN), 64, false)) + ), 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 51); + return returnValue; + } + + /* instruction 52: MULHU */ + continuation_e __mulhu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nMULHU_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 52); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto res = gen_ext(jh, + (gen_operation(jh, mul, + gen_ext(jh, gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 64, false), 128, false), gen_ext(jh, gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 64, false), 128, false)) + ), 64, false); + if(rd!=0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_operation(jh, shr, + res, gen_ext(jh, static_cast(traits::XLEN), 64, false)) + ), 32, false)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 52); + return returnValue; + } + + /* instruction 53: DIV */ + continuation_e __div(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nDIV_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 53); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto dividend = gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 32, false); + auto divisor = gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 32, false); + if(rd!= 0){ auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, ne, + divisor, gen_ext(jh, 0, 32, false)) + ,0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + auto MMIN = ((uint32_t)1)<<(static_cast(traits::XLEN)-1); + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, land, + gen_operation(jh, eq, + load_reg_from_mem(jh, traits::X0 + rs1), MMIN) + , gen_operation(jh, eq, + divisor, gen_ext(jh, - 1, 32, true)) + ) + ,0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + MMIN); + } + cc.jmp(label_merge); + cc.bind(label_else); + { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_operation(jh, idiv, + gen_ext(jh, dividend, 64, true), gen_ext(jh, divisor, 64, true)) + ), 32, true)); + } + cc.bind(label_merge); + } + cc.jmp(label_merge); + cc.bind(label_else); + { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + (uint32_t)- 1); + } + cc.bind(label_merge); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 53); + return returnValue; + } + + /* instruction 54: DIVU */ + continuation_e __divu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nDIVU_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 54); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, ne, + load_reg_from_mem(jh, traits::X0 + rs2), gen_ext(jh, 0, 32, false)) + ,0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + if(rd!=0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_operation(jh, div, + load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2)) + ), 32, false)); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + (uint32_t)- 1); + } + } + cc.bind(label_merge); + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 54); + return returnValue; + } + + /* instruction 55: REM */ + continuation_e __rem(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nREM_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 55); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, ne, + load_reg_from_mem(jh, traits::X0 + rs2), gen_ext(jh, 0, 32, false)) + ,0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + auto MMIN = (uint32_t)1<<(static_cast(traits::XLEN)-1); + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, land, + gen_operation(jh, eq, + load_reg_from_mem(jh, traits::X0 + rs1), MMIN) + , gen_operation(jh, eq, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 32, false), gen_ext(jh, - 1, 32, true)) + ) + ,0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + if(rd!=0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, 0, 32, false) + ); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_operation(jh, srem, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1), 32, false), gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 32, false)) + ), 32, true)); + } + } + cc.bind(label_merge); + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + load_reg_from_mem(jh, traits::X0 + rs1)); + } + } + cc.bind(label_merge); + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 55); + return returnValue; + } + + /* instruction 56: REMU */ + continuation_e __remu(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint8_t rs2 = ((bit_sub<20,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nREMU_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 56); + pc=pc+ 4; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rs1>=static_cast(traits::RFS)||rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, ne, + load_reg_from_mem(jh, traits::X0 + rs2), gen_ext(jh, 0, 32, false)) + ,0); + auto label_else = cc.newLabel(); + cc.je(label_else); + { + if(rd!=0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_operation(jh, urem, + load_reg_from_mem(jh, traits::X0 + rs1), load_reg_from_mem(jh, traits::X0 + rs2)) + ); + } + } + cc.jmp(label_merge); + cc.bind(label_else); + { + if(rd!=0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + load_reg_from_mem(jh, traits::X0 + rs1)); + } + } + cc.bind(label_merge); + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 56); + return returnValue; + } + + /* instruction 57: C__ADDI4SPN */ + continuation_e __c__addi4spn(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<2,3>(instr))); + uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__ADDI4SPN_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 57); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(imm) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd+ 8), + gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + 2), 64, false), gen_ext(jh, imm, 64, false)) + ), 32, false)); + } + else{ + gen_raise(jh, 0, 2); + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 57); + return returnValue; + } + + /* instruction 58: C__LW */ + continuation_e __c__lw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__LW_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 58); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + auto offs = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1+ 8), 64, false), gen_ext(jh, uimm, 64, false)) + ), 32, false); + cc.mov(get_reg_ptr(jh, traits::X0+ rd+ 8), + gen_ext(jh, + gen_ext(jh, + gen_read_mem(jh, traits::MEM, offs, 4), 32, false), 32, true)); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 58); + return returnValue; + } + + /* instruction 59: C__SW */ + continuation_e __c__sw(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__SW_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 59); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + auto offs = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1+ 8), 64, false), gen_ext(jh, uimm, 64, false)) + ), 32, false); + gen_write_mem(jh, traits::MEM, + offs, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2+ 8), 32, false)); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 59); + return returnValue; + } + + /* instruction 60: C__ADDI */ + continuation_e __c__addi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__ADDI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 60); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rs1!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rs1), + gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs1), 64, false), gen_ext(jh, (int8_t)sext<6>(imm), 64, true)) + ), 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 60); + return returnValue; + } + + /* instruction 61: C__NOP */ + continuation_e __c__nop(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__NOP_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 61); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 61); + return returnValue; + } + + /* instruction 62: C__JAL */ + continuation_e __c__jal(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__JAL_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 62); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + cc.mov(get_reg_ptr(jh, traits::X0+ 1), + (uint32_t)(PC+ 2)); + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<12>(imm)); + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 62); + return returnValue; + } + + /* instruction 63: C__LI */ + continuation_e __c__li(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__LI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 63); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + (uint32_t)((int8_t)sext<6>(imm))); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 63); + return returnValue; + } + + /* instruction 64: C__LUI */ + continuation_e __c__lui(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__LUI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 64); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(imm== 0||rd>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + (uint32_t)((int32_t)sext<18>(imm))); + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 64); + return returnValue; + } + + /* instruction 65: C__ADDI16SP */ + continuation_e __c__addi16sp(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__ADDI16SP_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 65); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(nzimm) { + cc.mov(get_reg_ptr(jh, traits::X0+ 2), + gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + 2), 64, false), gen_ext(jh, (int16_t)sext<10>(nzimm), 64, true)) + ), 32, true)); + } + else{ + gen_raise(jh, 0, 2); + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 65); + return returnValue; + } + + /* instruction 66: __reserved_clui */ + continuation_e ____reserved_clui(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\n__reserved_clui_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 66); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + gen_raise(jh, 0, 2); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 66); + return returnValue; + } + + /* instruction 67: C__SRLI */ + continuation_e __c__srli(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__SRLI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 67); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + cc.mov(get_reg_ptr(jh, traits::X0+ rs1+ 8), + gen_operation(jh, shr, + load_reg_from_mem(jh, traits::X0 + rs1+ 8), gen_ext(jh, shamt, 32, false)) + ); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 67); + return returnValue; + } + + /* instruction 68: C__SRAI */ + continuation_e __c__srai(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t shamt = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__SRAI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 68); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(shamt){ cc.mov(get_reg_ptr(jh, traits::X0+ rs1+ 8), + gen_ext(jh, + (gen_operation(jh, sar, + (gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1+ 8), 32, false)), gen_ext(jh, shamt, 32, false)) + ), 32, true)); + } + else{ + if(static_cast(traits::XLEN)== 128){ cc.mov(get_reg_ptr(jh, traits::X0+ rs1+ 8), + gen_ext(jh, + (gen_operation(jh, sar, + (gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs1+ 8), 32, false)), gen_ext(jh, 64, 32, false)) + ), 32, true)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 68); + return returnValue; + } + + /* instruction 69: C__ANDI */ + continuation_e __c__andi(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__ANDI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 69); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + cc.mov(get_reg_ptr(jh, traits::X0+ rs1+ 8), + gen_ext(jh, + (gen_operation(jh, band, + load_reg_from_mem(jh, traits::X0 + rs1+ 8), gen_ext(jh, (int8_t)sext<6>(imm), 32, true)) + ), 32, true)); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 69); + return returnValue; + } + + /* instruction 70: C__SUB */ + continuation_e __c__sub(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__SUB_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 70); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + cc.mov(get_reg_ptr(jh, traits::X0+ rd+ 8), + gen_ext(jh, + (gen_operation(jh, sub, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rd+ 8), 64, false), gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs2+ 8), 64, false)) + ), 32, true)); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 70); + return returnValue; + } + + /* instruction 71: C__XOR */ + continuation_e __c__xor(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__XOR_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 71); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + cc.mov(get_reg_ptr(jh, traits::X0+ rd+ 8), + gen_operation(jh, bxor, + load_reg_from_mem(jh, traits::X0 + rd+ 8), load_reg_from_mem(jh, traits::X0 + rs2+ 8)) + ); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 71); + return returnValue; + } + + /* instruction 72: C__OR */ + continuation_e __c__or(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__OR_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 72); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + cc.mov(get_reg_ptr(jh, traits::X0+ rd+ 8), + gen_operation(jh, bor, + load_reg_from_mem(jh, traits::X0 + rd+ 8), load_reg_from_mem(jh, traits::X0 + rs2+ 8)) + ); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 72); + return returnValue; + } + + /* instruction 73: C__AND */ + continuation_e __c__and(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,3>(instr))); + uint8_t rd = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__AND_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 73); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + cc.mov(get_reg_ptr(jh, traits::X0+ rd+ 8), + gen_operation(jh, band, + load_reg_from_mem(jh, traits::X0 + rd+ 8), load_reg_from_mem(jh, traits::X0 + rs2+ 8)) + ); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 73); + return returnValue; + } + + /* instruction 74: C__J */ + continuation_e __c__j(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__J_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 74); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<12>(imm)); + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 74); + return returnValue; + } + + /* instruction 75: C__BEQZ */ + continuation_e __c__beqz(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__BEQZ_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 75); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, eq, + load_reg_from_mem(jh, traits::X0 + rs1+ 8), gen_ext(jh, 0, 32, false)) + ,0); + cc.je(label_merge); + { + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<9>(imm)); + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + cc.bind(label_merge); + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 75); + return returnValue; + } + + /* instruction 76: C__BNEZ */ + continuation_e __c__bnez(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); + uint8_t rs1 = ((bit_sub<7,3>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__BNEZ_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 76); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + auto label_merge = cc.newLabel(); + cc.cmp(gen_operation(jh, ne, + load_reg_from_mem(jh, traits::X0 + rs1+ 8), gen_ext(jh, 0, 32, false)) + ,0); + cc.je(label_merge); + { + auto PC_val_v = (uint32_t)(PC+(int16_t)sext<9>(imm)); + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + cc.bind(label_merge); + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 76); + return returnValue; + } + + /* instruction 77: C__SLLI */ + continuation_e __c__slli(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t nzuimm = ((bit_sub<2,5>(instr))); + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__SLLI_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 77); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rs1!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rs1), + gen_operation(jh, shl, + load_reg_from_mem(jh, traits::X0 + rs1), gen_ext(jh, nzuimm, 32, false)) + ); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 77); + return returnValue; + } + + /* instruction 78: C__LWSP */ + continuation_e __c__lwsp(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__LWSP_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 78); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)||rd== 0) { + gen_raise(jh, 0, 2); + } + else{ + auto offs = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + 2), 64, false), gen_ext(jh, uimm, 64, false)) + ), 32, false); + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + gen_ext(jh, + gen_read_mem(jh, traits::MEM, offs, 4), 32, false), 32, true)); + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 78); + return returnValue; + } + + /* instruction 79: C__MV */ + continuation_e __c__mv(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__MV_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 79); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + load_reg_from_mem(jh, traits::X0 + rs2)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 79); + return returnValue; + } + + /* instruction 80: C__JR */ + continuation_e __c__jr(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__JR_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 80); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs1&&rs1(traits::RFS)) { + auto PC_val_v = gen_operation(jh, band, + load_reg_from_mem(jh, traits::X0 + rs1%static_cast(traits::RFS)), gen_ext(jh, ~ 0x1, 32, false)) + ; + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + else{ + gen_raise(jh, 0, 2); + } + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 80); + return returnValue; + } + + /* instruction 81: __reserved_cmv */ + continuation_e ____reserved_cmv(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\n__reserved_cmv_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 81); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + gen_raise(jh, 0, 2); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 81); + return returnValue; + } + + /* instruction 82: C__ADD */ + continuation_e __c__add(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t rd = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__ADD_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 82); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rd>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + if(rd!= 0) { + cc.mov(get_reg_ptr(jh, traits::X0+ rd), + gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rd), 64, false), gen_ext(jh, load_reg_from_mem(jh, traits::X0 + rs2), 64, false)) + ), 32, false)); + } + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 82); + return returnValue; + } + + /* instruction 83: C__JALR */ + continuation_e __c__jalr(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs1 = ((bit_sub<7,5>(instr))); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__JALR_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 83); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs1>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto new_pc = load_reg_from_mem(jh, traits::X0 + rs1); + cc.mov(get_reg_ptr(jh, traits::X0+ 1), + (uint32_t)(PC+ 2)); + auto PC_val_v = gen_operation(jh, band, + new_pc, gen_ext(jh, ~ 0x1, 32, false)) + ; + cc.mov(jh.next_pc, PC_val_v); + cc.mov(get_reg_ptr(jh, traits::LAST_BRANCH), 32U); + } + auto returnValue = BRANCH; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 83); + return returnValue; + } + + /* instruction 84: C__EBREAK */ + continuation_e __c__ebreak(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__EBREAK_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 84); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + gen_raise(jh, 0, 3); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 84); + return returnValue; + } + + /* instruction 85: C__SWSP */ + continuation_e __c__swsp(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + uint8_t rs2 = ((bit_sub<2,5>(instr))); + uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nC__SWSP_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 85); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + if(rs2>=static_cast(traits::RFS)) { + gen_raise(jh, 0, 2); + } + else{ + auto offs = gen_ext(jh, + (gen_operation(jh, add, + gen_ext(jh, load_reg_from_mem(jh, traits::X0 + 2), 64, false), gen_ext(jh, uimm, 64, false)) + ), 32, false); + gen_write_mem(jh, traits::MEM, + offs, + gen_ext(jh, + load_reg_from_mem(jh, traits::X0 + rs2), 32, false)); + } + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 85); + return returnValue; + } + + /* instruction 86: DII */ + continuation_e __dii(virt_addr_t& pc, code_word_t instr, jit_holder& jh){ + uint64_t PC = pc.val; + if(this->disass_enabled){ + /* generate disass */ + } + x86::Compiler& cc = jh.cc; + //ideally only do this if necessary (someone / plugin needs it) + cc.mov(jh.pc,PC); + cc.comment(fmt::format("\nDII_{:#x}:",pc.val).c_str()); + this->gen_sync(jh, PRE_SYNC, 86); + pc=pc+ 2; + + gen_instr_prologue(jh, pc.val); + cc.comment("\n//behavior:"); + /*generate behavior*/ + gen_raise(jh, 0, 2); + auto returnValue = CONT; + + gen_instr_epilogue(jh); + this->gen_sync(jh, POST_SYNC, 86); + return returnValue; + } + + /**************************************************************************** + * end opcode definitions + ****************************************************************************/ + continuation_e illegal_intruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) { + + return BRANCH; + } + //decoding functionality + + void populate_decoding_tree(decoding_tree_node* root){ + //create submask + for(auto instr: root->instrs){ + root->submask &= instr.mask; + } + //put each instr according to submask&encoding into children + for(auto instr: root->instrs){ + bool foundMatch = false; + for(auto child: root->children){ + //use value as identifying trait + if(child->value == (instr.value&root->submask)){ + child->instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch){ + decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask); + child->instrs.push_back(instr); + root->children.push_back(child); + } + } + root->instrs.clear(); + //call populate_decoding_tree for all children + if(root->children.size() >1) + for(auto child: root->children){ + populate_decoding_tree(child); + } + else{ + //sort instrs by value of the mask, this works bc we want to have the least restrictive one last + std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } + } + compile_func decode_instr(decoding_tree_node* node, code_word_t word){ + if(!node->children.size()){ + if(node->instrs.size() == 1) return node->instrs[0].op; + for(auto instr : node->instrs){ + if((instr.mask&word) == instr.value) return instr.op; + } + } + else{ + for(auto child : node->children){ + if (child->value == (node->submask&word)){ + return decode_instr(child, word); + } + } + } + return nullptr; + } +}; + +template void debug_fn(CODE_WORD instr) { + volatile CODE_WORD x = instr; + instr = 2 * x; +} + +template vm_impl::vm_impl() { this(new ARCH()); } + +template +vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) +: vm_base(core, core_id, cluster_id) { + root = new decoding_tree_node(std::numeric_limits::max()); + for(auto instr: instr_descr){ + root->instrs.push_back(instr); + } + populate_decoding_tree(root); +} + +template +continuation_e +vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, jit_holder& jh) { + enum {TRAP_ID=1<<16}; + code_word_t instr = 0; + phys_addr_t paddr(pc); + auto *const data = (uint8_t *)&instr; + if(this->core.has_mmu()) + paddr = this->core.virt2phys(pc); + auto res = this->core.read(paddr, 4, data); + if (res != iss::Ok) + throw trap_access(TRAP_ID, pc.val); + if (instr == 0x0000006f || (instr&0xffff)==0xa001) + throw simulation_stopped(0); // 'J 0' or 'C.J 0' + ++inst_cnt; + auto f = decode_instr(root, instr); + if (f == nullptr) + f = &this_class::illegal_intruction; + return (this->*f)(pc, instr, jh); +} + + + +} // namespace tgc5c + +template <> +std::unique_ptr create(arch::tgc5c *core, unsigned short port, bool dump) { + auto ret = new tgc5c::vm_impl(*core, dump); + if (port != 0) debugger::server::run_server(ret, port); + return std::unique_ptr(ret); +} +} // namespace asmjit +} // namespace iss + +#include +#include +#include +namespace iss { +namespace { +volatile std::array dummy = { + core_factory::instance().register_creator("tgc5c|m_p|asmjit", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_m_p(); + auto* vm = new asmjit::tgc5c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }), + core_factory::instance().register_creator("tgc5c|mu_p|asmjit", [](unsigned port, void*) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + auto* vm = new asmjit::tgc5c::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + return {cpu_ptr{cpu}, vm_ptr{vm}}; + }) +}; +} +} From bf4a6deb86f7626f08248e30a3e2cf03b330e488 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 22 Oct 2023 23:19:09 +0200 Subject: [PATCH 165/184] fixes dump-ir handling --- src/sysc/core_complex.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 78eb36e..0689b59 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -126,7 +127,7 @@ public: core_wrapper(core_complex *owner) : owner(owner) { } void reset(uint64_t addr){vm->reset(addr);} - inline void start(){vm->start();} + inline void start(bool dump = false){vm->start(std::numeric_limits::max(), dump);} inline std::pair load_file(std::string const& name){ iss::arch_if* cc = cpu->get_arch_if(); return cc->load_file(name);}; @@ -379,7 +380,7 @@ void core_complex::run() { } quantum_keeper.reset(); cpu->set_interrupt_execution(false); - cpu->start(); + cpu->start(dump_ir); } while (cpu->get_interrupt_execution()); sc_stop(); } From b7478965ab65ea14eb5c72c88b89528dcf18e265 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 23 Oct 2023 10:18:25 +0200 Subject: [PATCH 166/184] adds asmjit backend registration for SystemC --- gen_input/templates/asmjit/CORENAME.cpp.gtl | 2 +- src/sysc/register_tgc_c.cpp | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/gen_input/templates/asmjit/CORENAME.cpp.gtl b/gen_input/templates/asmjit/CORENAME.cpp.gtl index ad40e74..3cede3c 100644 --- a/gen_input/templates/asmjit/CORENAME.cpp.gtl +++ b/gen_input/templates/asmjit/CORENAME.cpp.gtl @@ -37,7 +37,7 @@ #include #include #include - +#include #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY #endif diff --git a/src/sysc/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp index 7ea4d5b..da2f72d 100644 --- a/src/sysc/register_tgc_c.cpp +++ b/src/sysc/register_tgc_c.cpp @@ -71,4 +71,21 @@ volatile std::array tgc_init = { }; } #endif +#if defined(WITH_ASMJIT) +namespace asmjit { +using namespace sysc; +volatile std::array tgc_init = { + iss_factory::instance().register_creator("tgc5c|m_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("tgc5c|mu_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }) +}; +} +#endif } From b86d7a517d2ad1ade0f1386555a99057660279ef Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 25 Oct 2023 17:13:52 +0200 Subject: [PATCH 167/184] adds dynamic cycle estimation --- contrib/instr/TGC5C_instr.yaml | 48 +-- contrib/instr/TGC5C_slow.yaml | 624 ++++++++++++++++++++++++++++++ src/iss/plugin/cycle_estimate.cpp | 40 +- src/iss/plugin/cycle_estimate.h | 26 +- 4 files changed, 685 insertions(+), 53 deletions(-) create mode 100644 contrib/instr/TGC5C_slow.yaml diff --git a/contrib/instr/TGC5C_instr.yaml b/contrib/instr/TGC5C_instr.yaml index 6ea4d78..ef9ab64 100644 --- a/contrib/instr/TGC5C_instr.yaml +++ b/contrib/instr/TGC5C_instr.yaml @@ -27,84 +27,84 @@ RV32I: mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: [1,1] + delay: [1,2] BEQ: index: 4 encoding: 0b00000000000000000000000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: [1,1] + delay: [1,2] BNE: index: 5 encoding: 0b00000000000000000001000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: [1,1] + delay: [1,2] BLT: index: 6 encoding: 0b00000000000000000100000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: [1,1] + delay: [1,2] BGE: index: 7 encoding: 0b00000000000000000101000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: [1,1] + delay: [1,2] BLTU: index: 8 encoding: 0b00000000000000000110000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: [1,1] + delay: [1,2] BGEU: index: 9 encoding: 0b00000000000000000111000001100011 mask: 0b00000000000000000111000001111111 size: 32 branch: true - delay: [1,1] + delay: [1,2] LB: index: 10 encoding: 0b00000000000000000000000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 2 LH: index: 11 encoding: 0b00000000000000000001000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 2 LW: index: 12 encoding: 0b00000000000000000010000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 2 LBU: index: 13 encoding: 0b00000000000000000100000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 2 LHU: index: 14 encoding: 0b00000000000000000101000000000011 mask: 0b00000000000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 2 SB: index: 15 encoding: 0b00000000000000000000000000100011 @@ -356,56 +356,56 @@ RV32M: mask: 0b11111110000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 2 MULH: index: 50 encoding: 0b00000010000000000001000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 2 MULHSU: index: 51 encoding: 0b00000010000000000010000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 2 MULHU: index: 52 encoding: 0b00000010000000000011000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 2 DIV: index: 53 encoding: 0b00000010000000000100000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 17 DIVU: index: 54 encoding: 0b00000010000000000101000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 17 REM: index: 55 encoding: 0b00000010000000000110000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 17 REMU: index: 56 encoding: 0b00000010000000000111000000110011 mask: 0b11111110000000000111000001111111 size: 32 branch: false - delay: 1 + delay: 17 Zca: C__ADDI4SPN: index: 57 @@ -420,7 +420,7 @@ Zca: mask: 0b1110000000000011 size: 16 branch: false - delay: 1 + delay: 2 C__SW: index: 59 encoding: 0b1100000000000000 @@ -542,14 +542,14 @@ Zca: mask: 0b1110000000000011 size: 16 branch: true - delay: [1,1] + delay: [1,2] C__BNEZ: index: 76 encoding: 0b1110000000000001 mask: 0b1110000000000011 size: 16 branch: true - delay: [1,1] + delay: [1,2] C__SLLI: index: 77 encoding: 0b0000000000000010 @@ -564,7 +564,7 @@ Zca: mask: 0b1110000000000011 size: 16 branch: false - delay: 1 + delay: 2 C__MV: index: 79 encoding: 0b1000000000000010 diff --git a/contrib/instr/TGC5C_slow.yaml b/contrib/instr/TGC5C_slow.yaml new file mode 100644 index 0000000..658b18a --- /dev/null +++ b/contrib/instr/TGC5C_slow.yaml @@ -0,0 +1,624 @@ + +RV32I: + LUI: + index: 0 + encoding: 0b00000000000000000000000000110111 + mask: 0b00000000000000000000000001111111 + size: 32 + branch: false + delay: 1 + AUIPC: + index: 1 + encoding: 0b00000000000000000000000000010111 + mask: 0b00000000000000000000000001111111 + size: 32 + branch: false + delay: 1 + JAL: + index: 2 + encoding: 0b00000000000000000000000001101111 + mask: 0b00000000000000000000000001111111 + size: 32 + branch: true + delay: 1 + JALR: + index: 3 + encoding: 0b00000000000000000000000001100111 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,2] + BEQ: + index: 4 + encoding: 0b00000000000000000000000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,2] + BNE: + index: 5 + encoding: 0b00000000000000000001000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,2] + BLT: + index: 6 + encoding: 0b00000000000000000100000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,2] + BGE: + index: 7 + encoding: 0b00000000000000000101000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,2] + BLTU: + index: 8 + encoding: 0b00000000000000000110000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,2] + BGEU: + index: 9 + encoding: 0b00000000000000000111000001100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: true + delay: [1,2] + LB: + index: 10 + encoding: 0b00000000000000000000000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 2 + LH: + index: 11 + encoding: 0b00000000000000000001000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 2 + LW: + index: 12 + encoding: 0b00000000000000000010000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 2 + LBU: + index: 13 + encoding: 0b00000000000000000100000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 2 + LHU: + index: 14 + encoding: 0b00000000000000000101000000000011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 2 + SB: + index: 15 + encoding: 0b00000000000000000000000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SH: + index: 16 + encoding: 0b00000000000000000001000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SW: + index: 17 + encoding: 0b00000000000000000010000000100011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ADDI: + index: 18 + encoding: 0b00000000000000000000000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLTI: + index: 19 + encoding: 0b00000000000000000010000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLTIU: + index: 20 + encoding: 0b00000000000000000011000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + XORI: + index: 21 + encoding: 0b00000000000000000100000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ORI: + index: 22 + encoding: 0b00000000000000000110000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ANDI: + index: 23 + encoding: 0b00000000000000000111000000010011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLLI: + index: 24 + encoding: 0b00000000000000000001000000010011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: "u_24:20" + SRLI: + index: 25 + encoding: 0b00000000000000000101000000010011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: "u_24:20" + SRAI: + index: 26 + encoding: 0b01000000000000000101000000010011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: "u_24:20" + ADD: + index: 27 + encoding: 0b00000000000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SUB: + index: 28 + encoding: 0b01000000000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLL: + index: 29 + encoding: 0b00000000000000000001000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: "X_24:20" + SLT: + index: 30 + encoding: 0b00000000000000000010000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SLTU: + index: 31 + encoding: 0b00000000000000000011000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + XOR: + index: 32 + encoding: 0b00000000000000000100000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + SRL: + index: 33 + encoding: 0b00000000000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: "X_24:20" + SRA: + index: 34 + encoding: 0b01000000000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: "X_24:20" + OR: + index: 35 + encoding: 0b00000000000000000110000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + AND: + index: 36 + encoding: 0b00000000000000000111000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 1 + FENCE: + index: 37 + encoding: 0b00000000000000000000000000001111 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + ECALL: + index: 38 + encoding: 0b00000000000000000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + EBREAK: + index: 39 + encoding: 0b00000000000100000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + MRET: + index: 40 + encoding: 0b00110000001000000000000001110011 + mask: 0b11111111111111111111111111111111 + attributes: [[name:no_cont]] + size: 32 + branch: false + delay: 1 + WFI: + index: 41 + encoding: 0b00010000010100000000000001110011 + mask: 0b11111111111111111111111111111111 + size: 32 + branch: false + delay: 1 +Zicsr: + CSRRW: + index: 42 + encoding: 0b00000000000000000001000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRS: + index: 43 + encoding: 0b00000000000000000010000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRC: + index: 44 + encoding: 0b00000000000000000011000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRWI: + index: 45 + encoding: 0b00000000000000000101000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRSI: + index: 46 + encoding: 0b00000000000000000110000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 + CSRRCI: + index: 47 + encoding: 0b00000000000000000111000001110011 + mask: 0b00000000000000000111000001111111 + size: 32 + branch: false + delay: 1 +Zifencei: + FENCE_I: + index: 48 + encoding: 0b00000000000000000001000000001111 + mask: 0b00000000000000000111000001111111 + attributes: [[name:flush]] + size: 32 + branch: false + delay: 1 +RV32M: + MUL: + index: 49 + encoding: 0b00000010000000000000000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 32 + MULH: + index: 50 + encoding: 0b00000010000000000001000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 32 + MULHSU: + index: 51 + encoding: 0b00000010000000000010000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 32 + MULHU: + index: 52 + encoding: 0b00000010000000000011000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 32 + DIV: + index: 53 + encoding: 0b00000010000000000100000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 33 + DIVU: + index: 54 + encoding: 0b00000010000000000101000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 33 + REM: + index: 55 + encoding: 0b00000010000000000110000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 33 + REMU: + index: 56 + encoding: 0b00000010000000000111000000110011 + mask: 0b11111110000000000111000001111111 + size: 32 + branch: false + delay: 33 +Zca: + C__ADDI4SPN: + index: 57 + encoding: 0b0000000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__LW: + index: 58 + encoding: 0b0100000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 2 + C__SW: + index: 59 + encoding: 0b1100000000000000 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__ADDI: + index: 60 + encoding: 0b0000000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__NOP: + index: 61 + encoding: 0b0000000000000001 + mask: 0b1110111110000011 + size: 16 + branch: false + delay: 1 + C__JAL: + index: 62 + encoding: 0b0010000000000001 + mask: 0b1110000000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: true + delay: 1 + C__LI: + index: 63 + encoding: 0b0100000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__LUI: + index: 64 + encoding: 0b0110000000000001 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + C__ADDI16SP: + index: 65 + encoding: 0b0110000100000001 + mask: 0b1110111110000011 + size: 16 + branch: false + delay: 1 + __reserved_clui: + index: 66 + encoding: 0b0110000000000001 + mask: 0b1111000001111111 + size: 16 + branch: false + delay: 1 + C__SRLI: + index: 67 + encoding: 0b1000000000000001 + mask: 0b1111110000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: "u_12:12*16+u_6:2" + C__SRAI: + index: 68 + encoding: 0b1000010000000001 + mask: 0b1111110000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: "u_12:12*16+u_6:2" + C__ANDI: + index: 69 + encoding: 0b1000100000000001 + mask: 0b1110110000000011 + size: 16 + branch: false + delay: 1 + C__SUB: + index: 70 + encoding: 0b1000110000000001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__XOR: + index: 71 + encoding: 0b1000110000100001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__OR: + index: 72 + encoding: 0b1000110001000001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__AND: + index: 73 + encoding: 0b1000110001100001 + mask: 0b1111110001100011 + size: 16 + branch: false + delay: 1 + C__J: + index: 74 + encoding: 0b1010000000000001 + mask: 0b1110000000000011 + size: 16 + branch: true + delay: 1 + C__BEQZ: + index: 75 + encoding: 0b1100000000000001 + mask: 0b1110000000000011 + size: 16 + branch: true + delay: [1,2] + C__BNEZ: + index: 76 + encoding: 0b1110000000000001 + mask: 0b1110000000000011 + size: 16 + branch: true + delay: [1,2] + C__SLLI: + index: 77 + encoding: 0b0000000000000010 + mask: 0b1111000000000011 + attributes: [[name:enable, value:1]] + size: 16 + branch: false + delay: "u_12:12*16+u_6:2" + C__LWSP: + index: 78 + encoding: 0b0100000000000010 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 2 + C__MV: + index: 79 + encoding: 0b1000000000000010 + mask: 0b1111000000000011 + size: 16 + branch: false + delay: 1 + C__JR: + index: 80 + encoding: 0b1000000000000010 + mask: 0b1111000001111111 + size: 16 + branch: true + delay: 1 + __reserved_cmv: + index: 81 + encoding: 0b1000000000000010 + mask: 0b1111111111111111 + size: 16 + branch: false + delay: 1 + C__ADD: + index: 82 + encoding: 0b1001000000000010 + mask: 0b1111000000000011 + size: 16 + branch: false + delay: 1 + C__JALR: + index: 83 + encoding: 0b1001000000000010 + mask: 0b1111000001111111 + size: 16 + branch: true + delay: 1 + C__EBREAK: + index: 84 + encoding: 0b1001000000000010 + mask: 0b1111111111111111 + size: 16 + branch: false + delay: 1 + C__SWSP: + index: 85 + encoding: 0b1100000000000010 + mask: 0b1110000000000011 + size: 16 + branch: false + delay: 1 + DII: + index: 86 + encoding: 0b0000000000000000 + mask: 0b1111111111111111 + size: 16 + branch: false + delay: 1 + diff --git a/src/iss/plugin/cycle_estimate.cpp b/src/iss/plugin/cycle_estimate.cpp index b389cb4..705b976 100644 --- a/src/iss/plugin/cycle_estimate.cpp +++ b/src/iss/plugin/cycle_estimate.cpp @@ -1,4 +1,3 @@ - /******************************************************************************* * Copyright (C) 2017 - 2023, MINRES Technologies GmbH * All rights reserved. @@ -34,6 +33,7 @@ ******************************************************************************/ #include "cycle_estimate.h" +#include #include #include @@ -48,11 +48,12 @@ iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name) { } -iss::plugin::cycle_estimate::~cycle_estimate() { -} +iss::plugin::cycle_estimate::~cycle_estimate() = default; bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& vm) { instr_if = vm.get_arch()->get_instrumentation_if(); + assert(instr_if && "No instrumentation interface available but callback executed"); + reg_base_ptr = reinterpret_cast(vm.get_arch()->get_regs_base_ptr()); if(!instr_if) return false; const string core_name = instr_if->core_type_name(); if (config_file_name.length() > 0) { @@ -67,17 +68,23 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& auto isa_subset = p.first; auto instructions = p.second; for (auto const& instr : instructions) { - instr_desc res; + auto idx = instr.second["index"].as(); + if(delays.size()<=idx) + delays.resize(idx+1); + auto& res = delays[idx]; res.is_branch = instr.second["branch"].as(); auto delay = instr.second["delay"]; if(delay.IsSequence()) { res.not_taken = delay[0].as(); res.taken = delay[1].as(); } else { - res.not_taken = delay.as(); - res.taken = res.not_taken; + try { + res.not_taken = delay.as(); + res.taken = res.not_taken; + } catch (const YAML::BadConversion& e) { + res.f = iss::plugin::calculator(reg_base_ptr, delay.as()); + } } - delays.push_back(std::move(res)); } } } catch (YAML::ParserException &e) { @@ -90,15 +97,18 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& } } return true; - } void iss::plugin::cycle_estimate::callback(instr_info_t instr_info) { - assert(instr_if && "No instrumentation interface available but callback executed"); - auto entry = delays[instr_info.instr_id]; - bool taken = instr_if->is_branch_taken(); - if (taken && (entry.taken > 1)) - instr_if->update_last_instr_cycles(entry.taken); - else if (entry.not_taken > 1) - instr_if->update_last_instr_cycles(entry.not_taken); + size_t instr_id = instr_info.instr_id; + auto entry = delays[instr_id]; + if(instr_info.phase_id==PRE_SYNC) { + if(entry.f) + current_delay = entry.f(instr_if->get_instr_word()); + } else { + if(!entry.f) + current_delay = instr_if->is_branch_taken()? entry.taken: entry.not_taken; + if(current_delay>1) + instr_if->update_last_instr_cycles(current_delay); + } } diff --git a/src/iss/plugin/cycle_estimate.h b/src/iss/plugin/cycle_estimate.h index 079a805..7fc1b46 100644 --- a/src/iss/plugin/cycle_estimate.h +++ b/src/iss/plugin/cycle_estimate.h @@ -40,24 +40,20 @@ #include #include #include +#include namespace iss { namespace plugin { class cycle_estimate: public vm_plugin { - BEGIN_BF_DECL(instr_desc, uint32_t) - BF_FIELD(taken, 24, 8) - BF_FIELD(not_taken, 16, 8) - BF_FIELD(is_branch, 8, 8) - BF_FIELD(size, 0, 8) - instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken, bool branch): instr_desc() { - this->size=size; - this->taken=taken; - this->not_taken=not_taken; - this->is_branch=branch; - } - END_BF_DECL(); + struct instr_desc { + size_t size; + bool is_branch; + unsigned not_taken; + unsigned taken; + std::function f; + }; public: cycle_estimate() = delete; @@ -76,13 +72,15 @@ public: bool registration(const char *const version, vm_if &arch) override; - sync_type get_sync() override { return POST_SYNC; }; + sync_type get_sync() override { return ALL_SYNC; }; void callback(instr_info_t instr_info) override; private: - iss::instrumentation_if *instr_if; + iss::instrumentation_if *instr_if{nullptr}; + uint32_t* reg_base_ptr {nullptr}; std::vector delays; + unsigned current_delay{0}; struct pair_hash { size_t operator()(const std::pair &p) const { std::hash hash; From 980c8031c30cc42f75525d0f796486e77c907da4 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Wed, 25 Oct 2023 20:37:10 +0200 Subject: [PATCH 168/184] fixes tohost behavior of SC wrapper and cycle-estimate plugin --- src/iss/plugin/cycle_estimate.cpp | 3 ++- src/iss/plugin/cycle_estimate.h | 9 ++++--- src/sysc/sc_core_adapter.h | 45 ++++++++++++++++++++++++++----- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/iss/plugin/cycle_estimate.cpp b/src/iss/plugin/cycle_estimate.cpp index 705b976..f5bac69 100644 --- a/src/iss/plugin/cycle_estimate.cpp +++ b/src/iss/plugin/cycle_estimate.cpp @@ -101,7 +101,7 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& void iss::plugin::cycle_estimate::callback(instr_info_t instr_info) { size_t instr_id = instr_info.instr_id; - auto entry = delays[instr_id]; + auto& entry = instr_idget_instr_word()); @@ -110,5 +110,6 @@ void iss::plugin::cycle_estimate::callback(instr_info_t instr_info) { current_delay = instr_if->is_branch_taken()? entry.taken: entry.not_taken; if(current_delay>1) instr_if->update_last_instr_cycles(current_delay); + current_delay = 1; } } diff --git a/src/iss/plugin/cycle_estimate.h b/src/iss/plugin/cycle_estimate.h index 7fc1b46..07cdd61 100644 --- a/src/iss/plugin/cycle_estimate.h +++ b/src/iss/plugin/cycle_estimate.h @@ -48,10 +48,10 @@ namespace plugin { class cycle_estimate: public vm_plugin { struct instr_desc { - size_t size; - bool is_branch; - unsigned not_taken; - unsigned taken; + size_t size{0}; + bool is_branch{false}; + unsigned not_taken{1}; + unsigned taken{1}; std::function f; }; @@ -79,6 +79,7 @@ public: private: iss::instrumentation_if *instr_if{nullptr}; uint32_t* reg_base_ptr {nullptr}; + instr_desc illegal_desc{}; std::vector delays; unsigned current_delay{0}; struct pair_hash { diff --git a/src/sysc/sc_core_adapter.h b/src/sysc/sc_core_adapter.h index bbd1465..4b937ac 100644 --- a/src/sysc/sc_core_adapter.h +++ b/src/sysc/sc_core_adapter.h @@ -70,14 +70,43 @@ public: if (addr.access && iss::access_type::DEBUG) return owner->write_mem_dbg(addr.val, length, data) ? iss::Ok : iss::Err; else { - auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err; - // clear MTIP on mtimecmp write - if (addr.val == 0x2004000) { - reg_t val; - this->read_csr(iss::arch::mip, val); - if (val & (1ULL << 7)) this->write_csr(iss::arch::mip, val & ~(1ULL << 7)); + auto tohost_upper = (sizeof(reg_t) == 4 && addr.val == (this->tohost + 4)) || + (sizeof(reg_t) == 8 && addr.val == this->tohost); + auto tohost_lower = (sizeof(reg_t) == 4 && addr.val == this->tohost) || + (sizeof(reg_t)== 64 && addr.val == this->tohost); + if (tohost_lower || tohost_upper) { + if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { + switch (hostvar >> 48) { + case 0: + if (hostvar != 0x1) { + SCCINFO(owner->name()) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar + << "), stopping simulation"; + } else { + SCCINFO(owner->name()) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar + << "), stopping simulation"; + } + this->reg.trap_state=std::numeric_limits::max(); + this->interrupt_sim=hostvar; +#ifndef WITH_TCC + throw(iss::simulation_stopped(hostvar)); +#endif + break; + default: + break; + } + } else if (tohost_lower) + to_host_wr_cnt++; + return iss::Ok; + } else { + auto res = owner->write_mem(addr.val, length, data) ? iss::Ok : iss::Err; + // clear MTIP on mtimecmp write + if (addr.val == 0x2004000) { + reg_t val; + this->read_csr(iss::arch::mip, val); + if (val & (1ULL << 7)) this->write_csr(iss::arch::mip, val & ~(1ULL << 7)); + } + return res; } - return res; } } @@ -146,6 +175,8 @@ public: private: sysc::tgfs::core_complex *const owner; sc_core::sc_event wfi_evt; + uint64_t hostvar; + unsigned to_host_wr_cnt = 0; }; } #endif /* _SYSC_SC_CORE_ADAPTER_H_ */ From 09db0cd35d1324c81f697af7e6abfb902f64d96f Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 26 Oct 2023 06:50:54 +0200 Subject: [PATCH 169/184] fixes LLVM backend registration for SystemC --- gen_input/templates/CORENAME_sysc.cpp.gtl | 34 +++++++++++++++++++++++ src/sysc/register_tgc_c.cpp | 17 ++++++++++++ src/vm/llvm/vm_tgc5c.cpp | 4 +-- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/gen_input/templates/CORENAME_sysc.cpp.gtl b/gen_input/templates/CORENAME_sysc.cpp.gtl index 3ef2df9..dc0d730 100644 --- a/gen_input/templates/CORENAME_sysc.cpp.gtl +++ b/gen_input/templates/CORENAME_sysc.cpp.gtl @@ -54,6 +54,23 @@ volatile std::array ${coreDef.name.toLowerCase()}_init = { }) }; } +#if defined(WITH_LLVM) +namespace llvm { +using namespace sysc; +volatile std::array ${coreDef.name.toLowerCase()}_init = { + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }) +}; +} +#endif #if defined(WITH_TCC) namespace tcc { using namespace sysc; @@ -71,4 +88,21 @@ volatile std::array ${coreDef.name.toLowerCase()}_init = { }; } #endif +#if defined(WITH_ASMJIT) +namespace asmjit { +using namespace sysc; +volatile std::array ${coreDef.name.toLowerCase()}_init = { + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }) +}; +} +#endif } diff --git a/src/sysc/register_tgc_c.cpp b/src/sysc/register_tgc_c.cpp index da2f72d..9771ddf 100644 --- a/src/sysc/register_tgc_c.cpp +++ b/src/sysc/register_tgc_c.cpp @@ -54,6 +54,23 @@ volatile std::array tgc_init = { }) }; } +#if defined(WITH_LLVM) +namespace llvm { +using namespace sysc; +volatile std::array tgc_init = { + iss_factory::instance().register_creator("tgc5c|m_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }), + iss_factory::instance().register_creator("tgc5c|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + }) +}; +} +#endif #if defined(WITH_TCC) namespace tcc { using namespace sysc; diff --git a/src/vm/llvm/vm_tgc5c.cpp b/src/vm/llvm/vm_tgc5c.cpp index 460a9d7..2229db3 100644 --- a/src/vm/llvm/vm_tgc5c.cpp +++ b/src/vm/llvm/vm_tgc5c.cpp @@ -4549,13 +4549,13 @@ volatile std::array dummy = { auto* vm = new llvm::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - })/*, + }), core_factory::instance().register_creator("tgc5c|mu_p|llvm", [](unsigned port, void*) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_mu_p(); auto* vm = new llvm::tgc5c::vm_impl(*cpu, false); if (port != 0) debugger::server::run_server(vm, port); return {cpu_ptr{cpu}, vm_ptr{vm}}; - })*/ + }) }; } } From e6f11081eba931b8d2a783939fa13f60448e6404 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 27 Oct 2023 21:12:49 +0200 Subject: [PATCH 170/184] fixes quantum and quantum break handling --- src/sysc/core_complex.cpp | 30 +++++++++++++++++++++--------- src/sysc/core_complex.h | 14 +++++++++----- src/sysc/sc_core_adapter.h | 10 ++++++++-- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 0689b59..faa878a 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -391,7 +391,10 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, if (lut_entry.get_granted_access() != tlm::tlm_dmi::DMI_ACCESS_NONE && addr + length <= lut_entry.get_end_address() + 1) { auto offset = addr - lut_entry.get_start_address(); std::copy(lut_entry.get_dmi_ptr() + offset, lut_entry.get_dmi_ptr() + offset + length, data); - quantum_keeper.inc(lut_entry.get_read_latency()); + if(is_fetch) + ibus_inc+=lut_entry.get_read_latency()/curr_clk; + else + dbus_inc+=lut_entry.get_read_latency()/curr_clk; return true; } else { auto& sckt = is_fetch? ibus : dbus; @@ -409,12 +412,17 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, auto preExt = new tlm::scc::scv::tlm_recording_extension(trc->tr_handle, this); gp.set_extension(preExt); } - sckt->b_transport(gp, delay); - auto incr = delay-quantum_keeper.get_local_time(); - if(is_fetch) - ibus_inc+=incr; - else - dbus_inc+=incr; + auto pre_delay = delay; + dbus->b_transport(gp, delay); + if(pre_delay>delay) { + quantum_keeper.reset(); + } else { + auto incr = (delay-quantum_keeper.get_local_time())/curr_clk; + if(is_fetch) + ibus_inc+=incr; + else + dbus_inc+=incr; + } SCCTRACE(this->name()) << "[local time: "<tr_handle, this); gp.set_extension(preExt); } + auto pre_delay = delay; dbus->b_transport(gp, delay); - dbus_inc+=delay-quantum_keeper.get_local_time(); + if(pre_delay>delay) + quantum_keeper.reset(); + else + dbus_inc+=(delay-quantum_keeper.get_local_time())/curr_clk; SCCTRACE() << "[local time: "<1?mem_incr:1; + } + inline void sync(uint64_t cycle) { auto core_inc = curr_clk * (cycle - last_sync_cycle); - auto incr = std::max(core_inc, std::max(ibus_inc, dbus_inc)); - quantum_keeper.inc(incr); + quantum_keeper.inc(core_inc); if (quantum_keeper.need_sync()) { wait(quantum_keeper.get_local_time()); quantum_keeper.reset(); } last_sync_cycle = cycle; - ibus_inc = sc_core::SC_ZERO_TIME; - dbus_inc = sc_core::SC_ZERO_TIME; } bool read_mem(uint64_t addr, unsigned length, uint8_t *const data, bool is_fetch); @@ -198,7 +202,7 @@ protected: std::vector write_buf; core_wrapper* cpu{nullptr}; sc_core::sc_signal curr_clk; - sc_core::sc_time ibus_inc, dbus_inc; + uint64_t ibus_inc{0}, dbus_inc{0}; core_trace* trc{nullptr}; std::unique_ptr t2t; private: diff --git a/src/sysc/sc_core_adapter.h b/src/sysc/sc_core_adapter.h index 4b937ac..b544791 100644 --- a/src/sysc/sc_core_adapter.h +++ b/src/sysc/sc_core_adapter.h @@ -39,8 +39,13 @@ public: uint64_t get_state() override { return this->state.mstatus.backing.val; } void notify_phase(iss::arch_if::exec_phase p) override { - if (p == iss::arch_if::ISTART) + if (p == iss::arch_if::ISTART && !first) { + auto cycle_incr = owner->get_last_bus_cycles(); + if(cycle_incr>1) + this->instr_if.update_last_instr_cycles(cycle_incr); owner->sync(this->instr_if.get_total_cycles()); + } + first=false; } iss::sync_type needed_sync() const override { return iss::PRE_SYNC; } @@ -175,8 +180,9 @@ public: private: sysc::tgfs::core_complex *const owner; sc_core::sc_event wfi_evt; - uint64_t hostvar; + uint64_t hostvar{std::numeric_limits::max()}; unsigned to_host_wr_cnt = 0; + bool first{true}; }; } #endif /* _SYSC_SC_CORE_ADAPTER_H_ */ From 7001b693ae6cdd14671df5d42bde13b4cfb48028 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 27 Oct 2023 22:14:11 +0200 Subject: [PATCH 171/184] updates templates for SystemC registration --- gen_input/templates/CORENAME_sysc.cpp.gtl | 46 +++++++++++++++++------ src/sysc/core_complex.cpp | 2 +- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/gen_input/templates/CORENAME_sysc.cpp.gtl b/gen_input/templates/CORENAME_sysc.cpp.gtl index dc0d730..238016e 100644 --- a/gen_input/templates/CORENAME_sysc.cpp.gtl +++ b/gen_input/templates/CORENAME_sysc.cpp.gtl @@ -30,18 +30,20 @@ * *******************************************************************************/ -#include "iss_factory.h" +#include #include #include #include -#include "sc_core_adapter.h" -#include "core_complex.h" +#include +#include #include - +<% +def array_count = coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e"? 3 : 2; +%> namespace iss { namespace interp { using namespace sysc; -volatile std::array ${coreDef.name.toLowerCase()}_init = { +volatile std::array ${coreDef.name.toLowerCase()}_init = { iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); @@ -51,13 +53,18 @@ volatile std::array ${coreDef.name.toLowerCase()}_init = { auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; - }) + })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%}%> }; } #if defined(WITH_LLVM) namespace llvm { using namespace sysc; -volatile std::array ${coreDef.name.toLowerCase()}_init = { +volatile std::array ${coreDef.name.toLowerCase()}_init = { iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t { auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); @@ -67,14 +74,19 @@ volatile std::array ${coreDef.name.toLowerCase()}_init = { auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; - }) + })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%}%> }; } #endif #if defined(WITH_TCC) namespace tcc { using namespace sysc; -volatile std::array ${coreDef.name.toLowerCase()}_init = { +volatile std::array ${coreDef.name.toLowerCase()}_init = { iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); @@ -84,14 +96,19 @@ volatile std::array ${coreDef.name.toLowerCase()}_init = { auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; - }) + })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%}%> }; } #endif #if defined(WITH_ASMJIT) namespace asmjit { using namespace sysc; -volatile std::array ${coreDef.name.toLowerCase()}_init = { +volatile std::array ${coreDef.name.toLowerCase()}_init = { iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t { auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); @@ -101,7 +118,12 @@ volatile std::array ${coreDef.name.toLowerCase()}_init = { auto* cc = reinterpret_cast(data); auto* cpu = new sc_core_adapter>(cc); return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; - }) + })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t { + auto* cc = reinterpret_cast(data); + auto* cpu = new sc_core_adapter>(cc); + return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; + })<%}%> }; } #endif diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index faa878a..6c2e2e5 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -148,7 +148,7 @@ public: } else { auto base_isa = type.substr(0, 5); if(base_isa=="tgc5d" || base_isa=="tgc5e") { - std::tie(cpu, vm) = f.create(type + "|mu_p_clic_pmp|" + backend, gdb_port); + std::tie(cpu, vm) = f.create(type + "|mu_p_clic_pmp|" + backend, gdb_port, owner); } else { std::tie(cpu, vm) = f.create(type + "|m_p|" + backend, gdb_port, owner); } From 2bea95c1a7a034cd23f45d210dc4a9b8f269c30e Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 28 Oct 2023 17:06:50 +0200 Subject: [PATCH 172/184] adds option to disable DMI use --- src/sysc/core_complex.cpp | 4 ++-- src/sysc/core_complex.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 6c2e2e5..051b0d7 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -427,7 +427,7 @@ bool core_complex::read_mem(uint64_t addr, unsigned length, uint8_t *const data, if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { return false; } - if (gp.is_dmi_allowed()) { + if (gp.is_dmi_allowed() && !GET_PROP_VALUE(disable_dmi)) { gp.set_command(tlm::TLM_READ_COMMAND); gp.set_address(addr); tlm_dmi_ext dmi_data; @@ -473,7 +473,7 @@ bool core_complex::write_mem(uint64_t addr, unsigned length, const uint8_t *cons if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { return false; } - if (gp.is_dmi_allowed()) { + if (gp.is_dmi_allowed() && !GET_PROP_VALUE(disable_dmi)) { gp.set_command(tlm::TLM_READ_COMMAND); gp.set_address(addr); tlm_dmi_ext dmi_data; diff --git a/src/sysc/core_complex.h b/src/sysc/core_complex.h index e477639..78cbdb5 100644 --- a/src/sysc/core_complex.h +++ b/src/sysc/core_complex.h @@ -94,6 +94,8 @@ public: cci::cci_param enable_disass{"enable_disass", false}; + cci::cci_param disable_dmi{"disable_dmi", false}; + cci::cci_param reset_address{"reset_address", 0ULL}; cci::cci_param core_type{"core_type", "tgc5c"}; @@ -119,6 +121,8 @@ public: scml_property enable_disass{"enable_disass", false}; + scml_property disable_dmi{"disable_dmi", false}; + scml_property reset_address{"reset_address", 0ULL}; scml_property core_type{"core_type", "tgc5c"}; From 2115e9ceaea9540b8998080213b1a79725f5c878 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 29 Oct 2023 14:31:15 +0100 Subject: [PATCH 173/184] adds missing include to templates --- gen_input/templates/interp/CORENAME.cpp.gtl | 1 + 1 file changed, 1 insertion(+) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index d92ed44..6af2995 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -39,6 +39,7 @@ def nativeTypeSize(int size){ #include #include #include +#include #include #include #include From 759061b56916c8cf55bbc52ab372609d3a7d0258 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 29 Oct 2023 17:06:56 +0100 Subject: [PATCH 174/184] applies clang-format changes --- .clang-format | 13 +- softfloat/build/Linux-386-GCC/platform.h | 7 +- softfloat/build/Linux-386-SSE2-GCC/platform.h | 7 +- .../build/Linux-ARM-VFPv2-GCC/platform.h | 7 +- softfloat/build/Linux-x86_64-GCC/platform.h | 7 +- softfloat/build/Win32-MinGW/platform.h | 7 +- softfloat/build/Win32-SSE2-MinGW/platform.h | 7 +- softfloat/build/Win64-MinGW-w64/platform.h | 7 +- .../build/template-FAST_INT64/platform.h | 17 +- .../build/template-not-FAST_INT64/platform.h | 17 +- softfloat/source/8086-SSE/specialize.h | 122 +- softfloat/source/8086/specialize.h | 122 +- .../source/ARM-VFPv2-defaultNaN/specialize.h | 168 +- softfloat/source/ARM-VFPv2/specialize.h | 120 +- softfloat/source/RISCV/specialize.h | 122 +- softfloat/source/include/internals.h | 309 +- softfloat/source/include/opts-GCC.h | 65 +- softfloat/source/include/primitiveTypes.h | 65 +- softfloat/source/include/primitives.h | 384 +- softfloat/source/include/softfloat.h | 479 +- softfloat/source/include/softfloat_types.h | 27 +- src/iss/arch/hwl.h | 71 +- src/iss/arch/riscv_hart_common.h | 67 +- src/iss/arch/riscv_hart_m_p.h | 760 +-- src/iss/arch/riscv_hart_msu_vp.h | 724 +-- src/iss/arch/riscv_hart_mu_p.h | 1014 ++-- src/iss/arch/tgc5c.cpp | 31 +- src/iss/arch/tgc5c.h | 176 +- src/iss/arch/tgc_mapper.h | 21 +- src/iss/arch/wt_cache.h | 93 +- src/iss/debugger/riscv_target_adapter.h | 225 +- src/iss/factory.h | 40 +- src/iss/plugin/cycle_estimate.cpp | 37 +- src/iss/plugin/cycle_estimate.h | 24 +- src/iss/plugin/instruction_count.cpp | 41 +- src/iss/plugin/instruction_count.h | 14 +- src/main.cpp | 87 +- src/sysc/core_complex.cpp | 258 +- src/sysc/core_complex.h | 51 +- src/sysc/iss_factory.h | 40 +- src/sysc/register_tgc_c.cpp | 106 +- src/sysc/sc_core_adapter.h | 113 +- src/sysc/sc_core_adapter_if.h | 9 +- src/vm/asmjit/helper_func.h | 488 +- src/vm/asmjit/vm_tgc5c.cpp | 4317 +++++++------ src/vm/fp_functions.cpp | 372 +- src/vm/fp_functions.h | 8 +- src/vm/interp/vm_tgc5c.cpp | 3140 +++++----- src/vm/llvm/fp_impl.cpp | 94 +- src/vm/llvm/vm_tgc5c.cpp | 5402 ++++++++--------- src/vm/tcc/vm_tgc5c.cpp | 4264 ++++++------- 51 files changed, 11493 insertions(+), 12673 deletions(-) diff --git a/.clang-format b/.clang-format index 0d03f70..a2683b8 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,3 @@ ---- Language: Cpp # BasedOnStyle: LLVM # should be in line with IndentWidth @@ -13,8 +12,8 @@ AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: true -AllowShortLoopsOnASingleLine: true +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false @@ -39,8 +38,8 @@ BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: true BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true -ColumnLimit: 120 -CommentPragmas: '^ IWYU pragma:' +ColumnLimit: 140 +CommentPragmas: '^( IWYU pragma:| @suppress)' ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 0 ContinuationIndentWidth: 4 @@ -76,13 +75,13 @@ PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Right +PointerAlignment: Left ReflowComments: true SortIncludes: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements +SpaceBeforeParens: Never SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false diff --git a/softfloat/build/Linux-386-GCC/platform.h b/softfloat/build/Linux-386-GCC/platform.h index 420aa4e..eb224b1 100644 --- a/softfloat/build/Linux-386-GCC/platform.h +++ b/softfloat/build/Linux-386-GCC/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,7 +47,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #include "opts-GCC.h" - diff --git a/softfloat/build/Linux-386-SSE2-GCC/platform.h b/softfloat/build/Linux-386-SSE2-GCC/platform.h index 420aa4e..eb224b1 100644 --- a/softfloat/build/Linux-386-SSE2-GCC/platform.h +++ b/softfloat/build/Linux-386-SSE2-GCC/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,7 +47,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #include "opts-GCC.h" - diff --git a/softfloat/build/Linux-ARM-VFPv2-GCC/platform.h b/softfloat/build/Linux-ARM-VFPv2-GCC/platform.h index 420aa4e..eb224b1 100644 --- a/softfloat/build/Linux-ARM-VFPv2-GCC/platform.h +++ b/softfloat/build/Linux-ARM-VFPv2-GCC/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,7 +47,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #include "opts-GCC.h" - diff --git a/softfloat/build/Linux-x86_64-GCC/platform.h b/softfloat/build/Linux-x86_64-GCC/platform.h index 92c3044..630cb43 100644 --- a/softfloat/build/Linux-x86_64-GCC/platform.h +++ b/softfloat/build/Linux-x86_64-GCC/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ //#define INLINE inline #define INLINE static @@ -48,10 +48,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC__ #define SOFTFLOAT_BUILTIN_CLZ 1 #define SOFTFLOAT_INTRINSIC_INT128 1 #endif #include "opts-GCC.h" - diff --git a/softfloat/build/Win32-MinGW/platform.h b/softfloat/build/Win32-MinGW/platform.h index 420aa4e..eb224b1 100644 --- a/softfloat/build/Win32-MinGW/platform.h +++ b/softfloat/build/Win32-MinGW/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,7 +47,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #include "opts-GCC.h" - diff --git a/softfloat/build/Win32-SSE2-MinGW/platform.h b/softfloat/build/Win32-SSE2-MinGW/platform.h index 420aa4e..eb224b1 100644 --- a/softfloat/build/Win32-SSE2-MinGW/platform.h +++ b/softfloat/build/Win32-SSE2-MinGW/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,7 +47,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #include "opts-GCC.h" - diff --git a/softfloat/build/Win64-MinGW-w64/platform.h b/softfloat/build/Win64-MinGW-w64/platform.h index 2fccb6c..737a708 100644 --- a/softfloat/build/Win64-MinGW-w64/platform.h +++ b/softfloat/build/Win64-MinGW-w64/platform.h @@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #ifdef __GNUC_STDC_INLINE__ #define INLINE inline #else @@ -47,8 +47,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ #define SOFTFLOAT_BUILTIN_CLZ 1 #define SOFTFLOAT_INTRINSIC_INT128 1 #include "opts-GCC.h" - diff --git a/softfloat/build/template-FAST_INT64/platform.h b/softfloat/build/template-FAST_INT64/platform.h index b63e2a7..b59e6c5 100644 --- a/softfloat/build/template-FAST_INT64/platform.h +++ b/softfloat/build/template-FAST_INT64/platform.h @@ -37,14 +37,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Edit lines marked with `==>'. See "SoftFloat-source.html". /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define LITTLEENDIAN 1 + *----------------------------------------------------------------------------*/ +== > #define LITTLEENDIAN 1 -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define INLINE inline - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define THREAD_LOCAL _Thread_local + /*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ + == > #define INLINE inline + /*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ + == > #define THREAD_LOCAL _Thread_local diff --git a/softfloat/build/template-not-FAST_INT64/platform.h b/softfloat/build/template-not-FAST_INT64/platform.h index b63e2a7..b59e6c5 100644 --- a/softfloat/build/template-not-FAST_INT64/platform.h +++ b/softfloat/build/template-not-FAST_INT64/platform.h @@ -37,14 +37,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Edit lines marked with `==>'. See "SoftFloat-source.html". /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define LITTLEENDIAN 1 + *----------------------------------------------------------------------------*/ +== > #define LITTLEENDIAN 1 -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define INLINE inline - -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -==> #define THREAD_LOCAL _Thread_local + /*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ + == > #define INLINE inline + /*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ + == > #define THREAD_LOCAL _Thread_local diff --git a/softfloat/source/8086-SSE/specialize.h b/softfloat/source/8086-SSE/specialize.h index 5fe119a..23b1632 100644 --- a/softfloat/source/8086-SSE/specialize.h +++ b/softfloat/source/8086-SSE/specialize.h @@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef specialize_h #define specialize_h 1 -#include -#include #include "primitiveTypes.h" #include "softfloat.h" +#include +#include /*---------------------------------------------------------------------------- | Default value for 'softfloat_detectTininess'. @@ -53,21 +53,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #define ui32_fromPosOverflow 0xFFFFFFFF #define ui32_fromNegOverflow 0xFFFFFFFF -#define ui32_fromNaN 0xFFFFFFFF -#define i32_fromPosOverflow (-0x7FFFFFFF - 1) -#define i32_fromNegOverflow (-0x7FFFFFFF - 1) -#define i32_fromNaN (-0x7FFFFFFF - 1) +#define ui32_fromNaN 0xFFFFFFFF +#define i32_fromPosOverflow (-0x7FFFFFFF - 1) +#define i32_fromNegOverflow (-0x7FFFFFFF - 1) +#define i32_fromNaN (-0x7FFFFFFF - 1) /*---------------------------------------------------------------------------- | The values to return on conversions to 64-bit integer formats that raise an | invalid exception. *----------------------------------------------------------------------------*/ -#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define ui64_fromNegOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define i64_fromPosOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNaN (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNegOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF) +#define i64_fromPosOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format @@ -92,7 +92,7 @@ struct commonNaN { | 16-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) +#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts @@ -100,13 +100,13 @@ struct commonNaN { | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr ); +void softfloat_f16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); +uint_fast16_t softfloat_commonNaNToF16UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- @@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast16_t - softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ); +uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. @@ -127,7 +126,7 @@ uint_fast16_t | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) +#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts @@ -135,13 +134,13 @@ uint_fast16_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); +void softfloat_f32UIToCommonNaN(uint_fast32_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); +uint_fast32_t softfloat_commonNaNToF32UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- @@ -149,20 +148,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); +uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 ) +#define defaultNaNF64UI UINT64_C(0xFFF8000000000000) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) +#define softfloat_isSigNaNF64UI(uiA) \ + ((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF))) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts @@ -170,13 +169,13 @@ uint_fast32_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); +void softfloat_f64UIToCommonNaN(uint_fast64_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); +uint_fast64_t softfloat_commonNaNToF64UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- @@ -184,14 +183,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); +uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0xFFFF -#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating @@ -199,7 +197,8 @@ uint_fast64_t | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \ + ((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 @@ -215,16 +214,14 @@ uint_fast64_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80UIToCommonNaN( - uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -235,19 +232,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNExtF80UI( - uint_fast16_t uiA64, - uint_fast64_t uiA0, - uint_fast16_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 ) -#define defaultNaNF128UI0 UINT64_C( 0 ) +#define defaultNaNF128UI64 UINT64_C(0xFFFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating @@ -255,7 +246,8 @@ struct uint128 | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) +#define softfloat_isSigNaNF128UI(uiA64, uiA0) \ + ((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF)))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' @@ -264,15 +256,13 @@ struct uint128 | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ -void - softfloat_f128UIToCommonNaN( - uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNF128UI( - uint_fast64_t uiA64, - uint_fast64_t uiA0, - uint_fast64_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0); #else @@ -304,18 +288,14 @@ struct uint128 | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80MToCommonNaN( - const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); +void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | 'zSPtr'. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values @@ -323,12 +303,7 @@ void | at the location pointed to by 'zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNExtF80M( - const struct extFloat80M *aSPtr, - const struct extFloat80M *bSPtr, - struct extFloat80M *zSPtr - ); +void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. @@ -336,7 +311,7 @@ void #define defaultNaNF128UI96 0xFFFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 -#define defaultNaNF128UI0 0 +#define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN, @@ -346,8 +321,7 @@ void | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); +void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point @@ -355,8 +329,7 @@ void | 'zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by @@ -366,11 +339,8 @@ void | and 'zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNF128M( - const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); +void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr); #endif #endif - diff --git a/softfloat/source/8086/specialize.h b/softfloat/source/8086/specialize.h index 5fe119a..23b1632 100644 --- a/softfloat/source/8086/specialize.h +++ b/softfloat/source/8086/specialize.h @@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef specialize_h #define specialize_h 1 -#include -#include #include "primitiveTypes.h" #include "softfloat.h" +#include +#include /*---------------------------------------------------------------------------- | Default value for 'softfloat_detectTininess'. @@ -53,21 +53,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #define ui32_fromPosOverflow 0xFFFFFFFF #define ui32_fromNegOverflow 0xFFFFFFFF -#define ui32_fromNaN 0xFFFFFFFF -#define i32_fromPosOverflow (-0x7FFFFFFF - 1) -#define i32_fromNegOverflow (-0x7FFFFFFF - 1) -#define i32_fromNaN (-0x7FFFFFFF - 1) +#define ui32_fromNaN 0xFFFFFFFF +#define i32_fromPosOverflow (-0x7FFFFFFF - 1) +#define i32_fromNegOverflow (-0x7FFFFFFF - 1) +#define i32_fromNaN (-0x7FFFFFFF - 1) /*---------------------------------------------------------------------------- | The values to return on conversions to 64-bit integer formats that raise an | invalid exception. *----------------------------------------------------------------------------*/ -#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define ui64_fromNegOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define i64_fromPosOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNaN (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNegOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF) +#define i64_fromPosOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format @@ -92,7 +92,7 @@ struct commonNaN { | 16-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) +#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts @@ -100,13 +100,13 @@ struct commonNaN { | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr ); +void softfloat_f16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); +uint_fast16_t softfloat_commonNaNToF16UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- @@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast16_t - softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ); +uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. @@ -127,7 +126,7 @@ uint_fast16_t | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) +#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts @@ -135,13 +134,13 @@ uint_fast16_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); +void softfloat_f32UIToCommonNaN(uint_fast32_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); +uint_fast32_t softfloat_commonNaNToF32UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- @@ -149,20 +148,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); +uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 ) +#define defaultNaNF64UI UINT64_C(0xFFF8000000000000) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) +#define softfloat_isSigNaNF64UI(uiA) \ + ((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF))) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts @@ -170,13 +169,13 @@ uint_fast32_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); +void softfloat_f64UIToCommonNaN(uint_fast64_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); +uint_fast64_t softfloat_commonNaNToF64UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- @@ -184,14 +183,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); +uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0xFFFF -#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating @@ -199,7 +197,8 @@ uint_fast64_t | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \ + ((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 @@ -215,16 +214,14 @@ uint_fast64_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80UIToCommonNaN( - uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -235,19 +232,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNExtF80UI( - uint_fast16_t uiA64, - uint_fast64_t uiA0, - uint_fast16_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 ) -#define defaultNaNF128UI0 UINT64_C( 0 ) +#define defaultNaNF128UI64 UINT64_C(0xFFFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating @@ -255,7 +246,8 @@ struct uint128 | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) +#define softfloat_isSigNaNF128UI(uiA64, uiA0) \ + ((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF)))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' @@ -264,15 +256,13 @@ struct uint128 | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ -void - softfloat_f128UIToCommonNaN( - uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNF128UI( - uint_fast64_t uiA64, - uint_fast64_t uiA0, - uint_fast64_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0); #else @@ -304,18 +288,14 @@ struct uint128 | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80MToCommonNaN( - const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); +void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | 'zSPtr'. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values @@ -323,12 +303,7 @@ void | at the location pointed to by 'zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNExtF80M( - const struct extFloat80M *aSPtr, - const struct extFloat80M *bSPtr, - struct extFloat80M *zSPtr - ); +void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. @@ -336,7 +311,7 @@ void #define defaultNaNF128UI96 0xFFFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 -#define defaultNaNF128UI0 0 +#define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN, @@ -346,8 +321,7 @@ void | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); +void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point @@ -355,8 +329,7 @@ void | 'zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by @@ -366,11 +339,8 @@ void | and 'zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNF128M( - const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); +void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr); #endif #endif - diff --git a/softfloat/source/ARM-VFPv2-defaultNaN/specialize.h b/softfloat/source/ARM-VFPv2-defaultNaN/specialize.h index 2c481a2..9d8e569 100644 --- a/softfloat/source/ARM-VFPv2-defaultNaN/specialize.h +++ b/softfloat/source/ARM-VFPv2-defaultNaN/specialize.h @@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef specialize_h #define specialize_h 1 -#include -#include #include "primitiveTypes.h" #include "softfloat.h" +#include +#include /*---------------------------------------------------------------------------- | Default value for 'softfloat_detectTininess'. @@ -53,27 +53,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #define ui32_fromPosOverflow 0xFFFFFFFF #define ui32_fromNegOverflow 0 -#define ui32_fromNaN 0 -#define i32_fromPosOverflow 0x7FFFFFFF -#define i32_fromNegOverflow (-0x7FFFFFFF - 1) -#define i32_fromNaN 0 +#define ui32_fromNaN 0 +#define i32_fromPosOverflow 0x7FFFFFFF +#define i32_fromNegOverflow (-0x7FFFFFFF - 1) +#define i32_fromNaN 0 /*---------------------------------------------------------------------------- | The values to return on conversions to 64-bit integer formats that raise an | invalid exception. *----------------------------------------------------------------------------*/ -#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) #define ui64_fromNegOverflow 0 -#define ui64_fromNaN 0 -#define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF ) -#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNaN 0 +#define ui64_fromNaN 0 +#define i64_fromPosOverflow INT64_C(0x7FFFFFFFFFFFFFFF) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN 0 /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format | to another. *----------------------------------------------------------------------------*/ -struct commonNaN { char _unused; }; +struct commonNaN { + char _unused; +}; /*---------------------------------------------------------------------------- | The bit pattern for a default generated 16-bit floating-point NaN. @@ -85,7 +87,7 @@ struct commonNaN { char _unused; }; | 16-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) +#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts @@ -93,13 +95,15 @@ struct commonNaN { char _unused; }; | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -#define softfloat_f16UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x0200) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_f16UIToCommonNaN(uiA, zPtr) \ + if(!((uiA)&0x0200)) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -#define softfloat_commonNaNToF16UI( aPtr ) ((uint_fast16_t) defaultNaNF16UI) +#define softfloat_commonNaNToF16UI(aPtr) ((uint_fast16_t)defaultNaNF16UI) /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- @@ -107,8 +111,7 @@ struct commonNaN { char _unused; }; | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast16_t - softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ); +uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. @@ -120,7 +123,7 @@ uint_fast16_t | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) +#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts @@ -128,13 +131,15 @@ uint_fast16_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -#define softfloat_f32UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x00400000) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_f32UIToCommonNaN(uiA, zPtr) \ + if(!((uiA)&0x00400000)) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -#define softfloat_commonNaNToF32UI( aPtr ) ((uint_fast32_t) defaultNaNF32UI) +#define softfloat_commonNaNToF32UI(aPtr) ((uint_fast32_t)defaultNaNF32UI) /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- @@ -142,20 +147,20 @@ uint_fast16_t | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); +uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 ) +#define defaultNaNF64UI UINT64_C(0x7FF8000000000000) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) +#define softfloat_isSigNaNF64UI(uiA) \ + ((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF))) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts @@ -163,13 +168,15 @@ uint_fast32_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -#define softfloat_f64UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & UINT64_C( 0x0008000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_f64UIToCommonNaN(uiA, zPtr) \ + if(!((uiA)&UINT64_C(0x0008000000000000))) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -#define softfloat_commonNaNToF64UI( aPtr ) ((uint_fast64_t) defaultNaNF64UI) +#define softfloat_commonNaNToF64UI(aPtr) ((uint_fast64_t)defaultNaNF64UI) /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- @@ -177,14 +184,13 @@ uint_fast32_t | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); +uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0x7FFF -#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating @@ -192,7 +198,8 @@ uint_fast64_t | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \ + ((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 @@ -208,24 +215,25 @@ uint_fast64_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -#define softfloat_extF80UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA0) & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_extF80UIToCommonNaN(uiA64, uiA0, zPtr) \ + if(!((uiA0)&UINT64_C(0x4000000000000000))) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ -#if defined INLINE && ! defined softfloat_commonNaNToExtF80UI +#if defined INLINE && !defined softfloat_commonNaNToExtF80UI INLINE -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ) -{ +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr) { struct uint128 uiZ; uiZ.v64 = defaultNaNExtF80UI64; - uiZ.v0 = defaultNaNExtF80UI0; + uiZ.v0 = defaultNaNExtF80UI0; return uiZ; } #else -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr); #endif /*---------------------------------------------------------------------------- @@ -237,19 +245,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNExtF80UI( - uint_fast16_t uiA64, - uint_fast64_t uiA0, - uint_fast16_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF128UI64 UINT64_C( 0x7FFF800000000000 ) -#define defaultNaNF128UI0 UINT64_C( 0 ) +#define defaultNaNF128UI64 UINT64_C(0x7FFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating @@ -257,7 +259,8 @@ struct uint128 | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) +#define softfloat_isSigNaNF128UI(uiA64, uiA0) \ + ((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF)))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' @@ -266,23 +269,24 @@ struct uint128 | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ -#define softfloat_f128UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA64) & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_f128UIToCommonNaN(uiA64, uiA0, zPtr) \ + if(!((uiA64)&UINT64_C(0x0000800000000000))) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -#if defined INLINE && ! defined softfloat_commonNaNToF128UI +#if defined INLINE && !defined softfloat_commonNaNToF128UI INLINE -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr ) -{ +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN* aPtr) { struct uint128 uiZ; uiZ.v64 = defaultNaNF128UI64; - uiZ.v0 = defaultNaNF128UI0; + uiZ.v0 = defaultNaNF128UI0; return uiZ; } #else -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*); #endif /*---------------------------------------------------------------------------- @@ -294,13 +298,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNF128UI( - uint_fast64_t uiA64, - uint_fast64_t uiA0, - uint_fast64_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0); #else @@ -315,26 +313,23 @@ struct uint128 | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -#define softfloat_extF80MToCommonNaN( aSPtr, zPtr ) if ( ! ((aSPtr)->signif & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_extF80MToCommonNaN(aSPtr, zPtr) \ + if(!((aSPtr)->signif & UINT64_C(0x4000000000000000))) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | 'zSPtr'. *----------------------------------------------------------------------------*/ -#if defined INLINE && ! defined softfloat_commonNaNToExtF80M +#if defined INLINE && !defined softfloat_commonNaNToExtF80M INLINE -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ) -{ +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr) { zSPtr->signExp = defaultNaNExtF80UI64; - zSPtr->signif = defaultNaNExtF80UI0; + zSPtr->signif = defaultNaNExtF80UI0; } #else -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr); #endif /*---------------------------------------------------------------------------- @@ -343,12 +338,7 @@ void | at the location pointed to by 'zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNExtF80M( - const struct extFloat80M *aSPtr, - const struct extFloat80M *bSPtr, - struct extFloat80M *zSPtr - ); +void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. @@ -356,7 +346,7 @@ void #define defaultNaNF128UI96 0x7FFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 -#define defaultNaNF128UI0 0 +#define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN, @@ -366,7 +356,9 @@ void | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -#define softfloat_f128MToCommonNaN( aWPtr, zPtr ) if ( ! ((aWPtr)[indexWordHi( 4 )] & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid ) +#define softfloat_f128MToCommonNaN(aWPtr, zPtr) \ + if(!((aWPtr)[indexWordHi(4)] & UINT64_C(0x0000800000000000))) \ + softfloat_raiseFlags(softfloat_flag_invalid) /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point @@ -374,19 +366,16 @@ void | 'zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -#if defined INLINE && ! defined softfloat_commonNaNToF128M +#if defined INLINE && !defined softfloat_commonNaNToF128M INLINE -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ) -{ - zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96; - zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64; - zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32; - zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0; +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr) { + zWPtr[indexWord(4, 3)] = defaultNaNF128UI96; + zWPtr[indexWord(4, 2)] = defaultNaNF128UI64; + zWPtr[indexWord(4, 1)] = defaultNaNF128UI32; + zWPtr[indexWord(4, 0)] = defaultNaNF128UI0; } #else -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr); #endif /*---------------------------------------------------------------------------- @@ -397,11 +386,8 @@ void | and 'zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNF128M( - const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); +void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr); #endif #endif - diff --git a/softfloat/source/ARM-VFPv2/specialize.h b/softfloat/source/ARM-VFPv2/specialize.h index 5321f33..638e690 100644 --- a/softfloat/source/ARM-VFPv2/specialize.h +++ b/softfloat/source/ARM-VFPv2/specialize.h @@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef specialize_h #define specialize_h 1 -#include -#include #include "primitiveTypes.h" #include "softfloat.h" +#include +#include /*---------------------------------------------------------------------------- | Default value for 'softfloat_detectTininess'. @@ -53,21 +53,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #define ui32_fromPosOverflow 0xFFFFFFFF #define ui32_fromNegOverflow 0 -#define ui32_fromNaN 0 -#define i32_fromPosOverflow 0x7FFFFFFF -#define i32_fromNegOverflow (-0x7FFFFFFF - 1) -#define i32_fromNaN 0 +#define ui32_fromNaN 0 +#define i32_fromPosOverflow 0x7FFFFFFF +#define i32_fromNegOverflow (-0x7FFFFFFF - 1) +#define i32_fromNaN 0 /*---------------------------------------------------------------------------- | The values to return on conversions to 64-bit integer formats that raise an | invalid exception. *----------------------------------------------------------------------------*/ -#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) #define ui64_fromNegOverflow 0 -#define ui64_fromNaN 0 -#define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF ) -#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1) -#define i64_fromNaN 0 +#define ui64_fromNaN 0 +#define i64_fromPosOverflow INT64_C(0x7FFFFFFFFFFFFFFF) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN 0 /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format @@ -92,7 +92,7 @@ struct commonNaN { | 16-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) +#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts @@ -100,13 +100,13 @@ struct commonNaN { | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr ); +void softfloat_f16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); +uint_fast16_t softfloat_commonNaNToF16UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- @@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast16_t - softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ); +uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. @@ -127,7 +126,7 @@ uint_fast16_t | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) +#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts @@ -135,13 +134,13 @@ uint_fast16_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); +void softfloat_f32UIToCommonNaN(uint_fast32_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); +uint_fast32_t softfloat_commonNaNToF32UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- @@ -149,20 +148,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); +uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 ) +#define defaultNaNF64UI UINT64_C(0x7FF8000000000000) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) +#define softfloat_isSigNaNF64UI(uiA) \ + ((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF))) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts @@ -170,13 +169,13 @@ uint_fast32_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); +void softfloat_f64UIToCommonNaN(uint_fast64_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); +uint_fast64_t softfloat_commonNaNToF64UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- @@ -184,14 +183,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); +uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0x7FFF -#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating @@ -199,7 +197,8 @@ uint_fast64_t | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \ + ((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 @@ -215,16 +214,14 @@ uint_fast64_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80UIToCommonNaN( - uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -235,19 +232,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNExtF80UI( - uint_fast16_t uiA64, - uint_fast64_t uiA0, - uint_fast16_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF128UI64 UINT64_C( 0x7FFF800000000000 ) -#define defaultNaNF128UI0 UINT64_C( 0 ) +#define defaultNaNF128UI64 UINT64_C(0x7FFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating @@ -255,7 +246,8 @@ struct uint128 | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) +#define softfloat_isSigNaNF128UI(uiA64, uiA0) \ + ((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF)))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' @@ -264,15 +256,13 @@ struct uint128 | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ -void - softfloat_f128UIToCommonNaN( - uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNF128UI( - uint_fast64_t uiA64, - uint_fast64_t uiA0, - uint_fast64_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0); #else @@ -304,18 +288,14 @@ struct uint128 | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80MToCommonNaN( - const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); +void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | 'zSPtr'. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values @@ -323,12 +303,7 @@ void | at the location pointed to by 'zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNExtF80M( - const struct extFloat80M *aSPtr, - const struct extFloat80M *bSPtr, - struct extFloat80M *zSPtr - ); +void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. @@ -336,7 +311,7 @@ void #define defaultNaNF128UI96 0x7FFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 -#define defaultNaNF128UI0 0 +#define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN, @@ -346,8 +321,7 @@ void | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); +void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point @@ -355,8 +329,7 @@ void | 'zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by @@ -366,11 +339,8 @@ void | and 'zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNF128M( - const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); +void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr); #endif #endif - diff --git a/softfloat/source/RISCV/specialize.h b/softfloat/source/RISCV/specialize.h index 1cb9854..f0cb14c 100644 --- a/softfloat/source/RISCV/specialize.h +++ b/softfloat/source/RISCV/specialize.h @@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef specialize_h #define specialize_h 1 -#include -#include #include "primitiveTypes.h" #include "softfloat.h" +#include +#include /*---------------------------------------------------------------------------- | Default value for 'softfloat_detectTininess'. @@ -53,21 +53,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #define ui32_fromPosOverflow UINT32_C(0xFFFFFFFF) #define ui32_fromNegOverflow UINT32_C(0x0) -#define ui32_fromNaN UINT32_C(0xFFFFFFFF) -#define i32_fromPosOverflow INT64_C(0x7FFFFFFF) -#define i32_fromNegOverflow (-INT64_C(0x7FFFFFFF)-1) -#define i32_fromNaN INT64_C(0x7FFFFFFF) +#define ui32_fromNaN UINT32_C(0xFFFFFFFF) +#define i32_fromPosOverflow INT64_C(0x7FFFFFFF) +#define i32_fromNegOverflow (-INT64_C(0x7FFFFFFF) - 1) +#define i32_fromNaN INT64_C(0x7FFFFFFF) /*---------------------------------------------------------------------------- | The values to return on conversions to 64-bit integer formats that raise an | invalid exception. *----------------------------------------------------------------------------*/ -#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF ) -#define ui64_fromNegOverflow UINT64_C( 0x0 ) -#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF) -#define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF) -#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF)-1) -#define i64_fromNaN INT64_C( 0x7FFFFFFFFFFFFFFF) +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNegOverflow UINT64_C(0x0) +#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF) +#define i64_fromPosOverflow INT64_C(0x7FFFFFFFFFFFFFFF) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN INT64_C(0x7FFFFFFFFFFFFFFF) /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format @@ -92,7 +92,7 @@ struct commonNaN { | 16-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) +#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts @@ -100,13 +100,13 @@ struct commonNaN { | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr ); +void softfloat_f16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); +uint_fast16_t softfloat_commonNaNToF16UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- @@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast16_t - softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB ); +uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. @@ -127,7 +126,7 @@ uint_fast16_t | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) +#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts @@ -135,13 +134,13 @@ uint_fast16_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); +void softfloat_f32UIToCommonNaN(uint_fast32_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); +uint_fast32_t softfloat_commonNaNToF32UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- @@ -149,20 +148,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast32_t - softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); +uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 ) +#define defaultNaNF64UI UINT64_C(0x7FF8000000000000) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) +#define softfloat_isSigNaNF64UI(uiA) \ + ((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF))) /*---------------------------------------------------------------------------- | Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts @@ -170,13 +169,13 @@ uint_fast32_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); +void softfloat_f64UIToCommonNaN(uint_fast64_t uiA, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); +uint_fast64_t softfloat_commonNaNToF64UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- @@ -184,14 +183,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); | the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -uint_fast64_t - softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); +uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0xFFFF -#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating @@ -199,7 +197,8 @@ uint_fast64_t | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \ + ((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 @@ -215,16 +214,14 @@ uint_fast64_t | location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80UIToCommonNaN( - uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -235,19 +232,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNExtF80UI( - uint_fast16_t uiA64, - uint_fast64_t uiA0, - uint_fast16_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ -#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 ) -#define defaultNaNF128UI0 UINT64_C( 0 ) +#define defaultNaNF128UI64 UINT64_C(0xFFFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating @@ -255,7 +246,8 @@ struct uint128 | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ -#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) +#define softfloat_isSigNaNF128UI(uiA64, uiA0) \ + ((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF)))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' @@ -264,15 +256,13 @@ struct uint128 | pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ -void - softfloat_f128UIToCommonNaN( - uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); +void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating 'uiA64' and @@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_propagateNaNF128UI( - uint_fast64_t uiA64, - uint_fast64_t uiA0, - uint_fast64_t uiB64, - uint_fast64_t uiB0 - ); +struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0); #else @@ -304,18 +288,14 @@ struct uint128 | common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_extF80MToCommonNaN( - const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); +void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | 'zSPtr'. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToExtF80M( - const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); +void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values @@ -323,12 +303,7 @@ void | at the location pointed to by 'zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNExtF80M( - const struct extFloat80M *aSPtr, - const struct extFloat80M *bSPtr, - struct extFloat80M *zSPtr - ); +void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. @@ -336,7 +311,7 @@ void #define defaultNaNF128UI96 0xFFFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 -#define defaultNaNF128UI0 0 +#define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN, @@ -346,8 +321,7 @@ void | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); +void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point @@ -355,8 +329,7 @@ void | 'zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); +void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr); /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by @@ -366,11 +339,8 @@ void | and 'zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ -void - softfloat_propagateNaNF128M( - const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); +void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr); #endif #endif - diff --git a/softfloat/source/include/internals.h b/softfloat/source/include/internals.h index 020b340..bd976d1 100644 --- a/softfloat/source/include/internals.h +++ b/softfloat/source/include/internals.h @@ -37,242 +37,205 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef internals_h #define internals_h 1 -#include -#include #include "primitives.h" #include "softfloat_types.h" +#include +#include -union ui16_f16 { uint16_t ui; float16_t f; }; -union ui32_f32 { uint32_t ui; float32_t f; }; -union ui64_f64 { uint64_t ui; float64_t f; }; - -#ifdef SOFTFLOAT_FAST_INT64 -union extF80M_extF80 { struct extFloat80M fM; extFloat80_t f; }; -union ui128_f128 { struct uint128 ui; float128_t f; }; -#endif - -enum { - softfloat_mulAdd_subC = 1, - softfloat_mulAdd_subProd = 2 +union ui16_f16 { + uint16_t ui; + float16_t f; +}; +union ui32_f32 { + uint32_t ui; + float32_t f; +}; +union ui64_f64 { + uint64_t ui; + float64_t f; }; -/*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -uint_fast32_t softfloat_roundToUI32( bool, uint_fast64_t, uint_fast8_t, bool ); - #ifdef SOFTFLOAT_FAST_INT64 -uint_fast64_t - softfloat_roundToUI64( - bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); -#else -uint_fast64_t softfloat_roundMToUI64( bool, uint32_t *, uint_fast8_t, bool ); +union extF80M_extF80 { + struct extFloat80M fM; + extFloat80_t f; +}; +union ui128_f128 { + struct uint128 ui; + float128_t f; +}; #endif -int_fast32_t softfloat_roundToI32( bool, uint_fast64_t, uint_fast8_t, bool ); +enum { softfloat_mulAdd_subC = 1, softfloat_mulAdd_subProd = 2 }; + +/*---------------------------------------------------------------------------- + *----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_roundToUI32(bool, uint_fast64_t, uint_fast8_t, bool); #ifdef SOFTFLOAT_FAST_INT64 -int_fast64_t - softfloat_roundToI64( - bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); +uint_fast64_t softfloat_roundToUI64(bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool); #else -int_fast64_t softfloat_roundMToI64( bool, uint32_t *, uint_fast8_t, bool ); +uint_fast64_t softfloat_roundMToUI64(bool, uint32_t*, uint_fast8_t, bool); +#endif + +int_fast32_t softfloat_roundToI32(bool, uint_fast64_t, uint_fast8_t, bool); + +#ifdef SOFTFLOAT_FAST_INT64 +int_fast64_t softfloat_roundToI64(bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool); +#else +int_fast64_t softfloat_roundMToI64(bool, uint32_t*, uint_fast8_t, bool); #endif /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signF16UI( a ) ((bool) ((uint16_t) (a)>>15)) -#define expF16UI( a ) ((int_fast8_t) ((a)>>10) & 0x1F) -#define fracF16UI( a ) ((a) & 0x03FF) -#define packToF16UI( sign, exp, sig ) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig)) + *----------------------------------------------------------------------------*/ +#define signF16UI(a) ((bool)((uint16_t)(a) >> 15)) +#define expF16UI(a) ((int_fast8_t)((a) >> 10) & 0x1F) +#define fracF16UI(a) ((a)&0x03FF) +#define packToF16UI(sign, exp, sig) (((uint16_t)(sign) << 15) + ((uint16_t)(exp) << 10) + (sig)) -#define isNaNF16UI( a ) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF)) +#define isNaNF16UI(a) (((~(a)&0x7C00) == 0) && ((a)&0x03FF)) -struct exp8_sig16 { int_fast8_t exp; uint_fast16_t sig; }; -struct exp8_sig16 softfloat_normSubnormalF16Sig( uint_fast16_t ); +struct exp8_sig16 { + int_fast8_t exp; + uint_fast16_t sig; +}; +struct exp8_sig16 softfloat_normSubnormalF16Sig(uint_fast16_t); -float16_t softfloat_roundPackToF16( bool, int_fast16_t, uint_fast16_t ); -float16_t softfloat_normRoundPackToF16( bool, int_fast16_t, uint_fast16_t ); +float16_t softfloat_roundPackToF16(bool, int_fast16_t, uint_fast16_t); +float16_t softfloat_normRoundPackToF16(bool, int_fast16_t, uint_fast16_t); -float16_t softfloat_addMagsF16( uint_fast16_t, uint_fast16_t ); -float16_t softfloat_subMagsF16( uint_fast16_t, uint_fast16_t ); -float16_t - softfloat_mulAddF16( - uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t ); +float16_t softfloat_addMagsF16(uint_fast16_t, uint_fast16_t); +float16_t softfloat_subMagsF16(uint_fast16_t, uint_fast16_t); +float16_t softfloat_mulAddF16(uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t); /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signF32UI( a ) ((bool) ((uint32_t) (a)>>31)) -#define expF32UI( a ) ((int_fast16_t) ((a)>>23) & 0xFF) -#define fracF32UI( a ) ((a) & 0x007FFFFF) -#define packToF32UI( sign, exp, sig ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig)) + *----------------------------------------------------------------------------*/ +#define signF32UI(a) ((bool)((uint32_t)(a) >> 31)) +#define expF32UI(a) ((int_fast16_t)((a) >> 23) & 0xFF) +#define fracF32UI(a) ((a)&0x007FFFFF) +#define packToF32UI(sign, exp, sig) (((uint32_t)(sign) << 31) + ((uint32_t)(exp) << 23) + (sig)) -#define isNaNF32UI( a ) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF)) +#define isNaNF32UI(a) (((~(a)&0x7F800000) == 0) && ((a)&0x007FFFFF)) -struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; }; -struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t ); +struct exp16_sig32 { + int_fast16_t exp; + uint_fast32_t sig; +}; +struct exp16_sig32 softfloat_normSubnormalF32Sig(uint_fast32_t); -float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t ); -float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t ); +float32_t softfloat_roundPackToF32(bool, int_fast16_t, uint_fast32_t); +float32_t softfloat_normRoundPackToF32(bool, int_fast16_t, uint_fast32_t); -float32_t softfloat_addMagsF32( uint_fast32_t, uint_fast32_t ); -float32_t softfloat_subMagsF32( uint_fast32_t, uint_fast32_t ); -float32_t - softfloat_mulAddF32( - uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t ); +float32_t softfloat_addMagsF32(uint_fast32_t, uint_fast32_t); +float32_t softfloat_subMagsF32(uint_fast32_t, uint_fast32_t); +float32_t softfloat_mulAddF32(uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t); /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signF64UI( a ) ((bool) ((uint64_t) (a)>>63)) -#define expF64UI( a ) ((int_fast16_t) ((a)>>52) & 0x7FF) -#define fracF64UI( a ) ((a) & UINT64_C( 0x000FFFFFFFFFFFFF )) -#define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig))) + *----------------------------------------------------------------------------*/ +#define signF64UI(a) ((bool)((uint64_t)(a) >> 63)) +#define expF64UI(a) ((int_fast16_t)((a) >> 52) & 0x7FF) +#define fracF64UI(a) ((a)&UINT64_C(0x000FFFFFFFFFFFFF)) +#define packToF64UI(sign, exp, sig) ((uint64_t)(((uint_fast64_t)(sign) << 63) + ((uint_fast64_t)(exp) << 52) + (sig))) -#define isNaNF64UI( a ) (((~(a) & UINT64_C( 0x7FF0000000000000 )) == 0) && ((a) & UINT64_C( 0x000FFFFFFFFFFFFF ))) +#define isNaNF64UI(a) (((~(a)&UINT64_C(0x7FF0000000000000)) == 0) && ((a)&UINT64_C(0x000FFFFFFFFFFFFF))) -struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; }; -struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t ); +struct exp16_sig64 { + int_fast16_t exp; + uint_fast64_t sig; +}; +struct exp16_sig64 softfloat_normSubnormalF64Sig(uint_fast64_t); -float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t ); -float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t ); +float64_t softfloat_roundPackToF64(bool, int_fast16_t, uint_fast64_t); +float64_t softfloat_normRoundPackToF64(bool, int_fast16_t, uint_fast64_t); -float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool ); -float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool ); -float64_t - softfloat_mulAddF64( - uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); +float64_t softfloat_addMagsF64(uint_fast64_t, uint_fast64_t, bool); +float64_t softfloat_subMagsF64(uint_fast64_t, uint_fast64_t, bool); +float64_t softfloat_mulAddF64(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t); /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signExtF80UI64( a64 ) ((bool) ((uint16_t) (a64)>>15)) -#define expExtF80UI64( a64 ) ((a64) & 0x7FFF) -#define packToExtF80UI64( sign, exp ) ((uint_fast16_t) (sign)<<15 | (exp)) + *----------------------------------------------------------------------------*/ +#define signExtF80UI64(a64) ((bool)((uint16_t)(a64) >> 15)) +#define expExtF80UI64(a64) ((a64)&0x7FFF) +#define packToExtF80UI64(sign, exp) ((uint_fast16_t)(sign) << 15 | (exp)) -#define isNaNExtF80UI( a64, a0 ) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) +#define isNaNExtF80UI(a64, a0) ((((a64)&0x7FFF) == 0x7FFF) && ((a0)&UINT64_C(0x7FFFFFFFFFFFFFFF))) #ifdef SOFTFLOAT_FAST_INT64 /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ -struct exp32_sig64 { int_fast32_t exp; uint64_t sig; }; -struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t ); +struct exp32_sig64 { + int_fast32_t exp; + uint64_t sig; +}; +struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint_fast64_t); -extFloat80_t - softfloat_roundPackToExtF80( - bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); -extFloat80_t - softfloat_normRoundPackToExtF80( - bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); +extFloat80_t softfloat_roundPackToExtF80(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t); +extFloat80_t softfloat_normRoundPackToExtF80(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t); -extFloat80_t - softfloat_addMagsExtF80( - uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); -extFloat80_t - softfloat_subMagsExtF80( - uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); +extFloat80_t softfloat_addMagsExtF80(uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool); +extFloat80_t softfloat_subMagsExtF80(uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool); /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signF128UI64( a64 ) ((bool) ((uint64_t) (a64)>>63)) -#define expF128UI64( a64 ) ((int_fast32_t) ((a64)>>48) & 0x7FFF) -#define fracF128UI64( a64 ) ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF )) -#define packToF128UI64( sign, exp, sig64 ) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<48) + (sig64)) + *----------------------------------------------------------------------------*/ +#define signF128UI64(a64) ((bool)((uint64_t)(a64) >> 63)) +#define expF128UI64(a64) ((int_fast32_t)((a64) >> 48) & 0x7FFF) +#define fracF128UI64(a64) ((a64)&UINT64_C(0x0000FFFFFFFFFFFF)) +#define packToF128UI64(sign, exp, sig64) (((uint_fast64_t)(sign) << 63) + ((uint_fast64_t)(exp) << 48) + (sig64)) -#define isNaNF128UI( a64, a0 ) (((~(a64) & UINT64_C( 0x7FFF000000000000 )) == 0) && (a0 || ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF )))) +#define isNaNF128UI(a64, a0) (((~(a64)&UINT64_C(0x7FFF000000000000)) == 0) && (a0 || ((a64)&UINT64_C(0x0000FFFFFFFFFFFF)))) -struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; }; -struct exp32_sig128 - softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t ); +struct exp32_sig128 { + int_fast32_t exp; + struct uint128 sig; +}; +struct exp32_sig128 softfloat_normSubnormalF128Sig(uint_fast64_t, uint_fast64_t); -float128_t - softfloat_roundPackToF128( - bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t ); -float128_t - softfloat_normRoundPackToF128( - bool, int_fast32_t, uint_fast64_t, uint_fast64_t ); +float128_t softfloat_roundPackToF128(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t); +float128_t softfloat_normRoundPackToF128(bool, int_fast32_t, uint_fast64_t, uint_fast64_t); -float128_t - softfloat_addMagsF128( - uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); -float128_t - softfloat_subMagsF128( - uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); -float128_t - softfloat_mulAddF128( - uint_fast64_t, - uint_fast64_t, - uint_fast64_t, - uint_fast64_t, - uint_fast64_t, - uint_fast64_t, - uint_fast8_t - ); +float128_t softfloat_addMagsF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool); +float128_t softfloat_subMagsF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool); +float128_t softfloat_mulAddF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t); #else /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ + *----------------------------------------------------------------------------*/ -bool - softfloat_tryPropagateNaNExtF80M( - const struct extFloat80M *, - const struct extFloat80M *, - struct extFloat80M * - ); -void softfloat_invalidExtF80M( struct extFloat80M * ); +bool softfloat_tryPropagateNaNExtF80M(const struct extFloat80M*, const struct extFloat80M*, struct extFloat80M*); +void softfloat_invalidExtF80M(struct extFloat80M*); -int softfloat_normExtF80SigM( uint64_t * ); +int softfloat_normExtF80SigM(uint64_t*); -void - softfloat_roundPackMToExtF80M( - bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); -void - softfloat_normRoundPackMToExtF80M( - bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); +void softfloat_roundPackMToExtF80M(bool, int32_t, uint32_t*, uint_fast8_t, struct extFloat80M*); +void softfloat_normRoundPackMToExtF80M(bool, int32_t, uint32_t*, uint_fast8_t, struct extFloat80M*); -void - softfloat_addExtF80M( - const struct extFloat80M *, - const struct extFloat80M *, - struct extFloat80M *, - bool - ); +void softfloat_addExtF80M(const struct extFloat80M*, const struct extFloat80M*, struct extFloat80M*, bool); -int - softfloat_compareNonnormExtF80M( - const struct extFloat80M *, const struct extFloat80M * ); +int softfloat_compareNonnormExtF80M(const struct extFloat80M*, const struct extFloat80M*); /*---------------------------------------------------------------------------- -*----------------------------------------------------------------------------*/ -#define signF128UI96( a96 ) ((bool) ((uint32_t) (a96)>>31)) -#define expF128UI96( a96 ) ((int32_t) ((a96)>>16) & 0x7FFF) -#define fracF128UI96( a96 ) ((a96) & 0x0000FFFF) -#define packToF128UI96( sign, exp, sig96 ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<16) + (sig96)) + *----------------------------------------------------------------------------*/ +#define signF128UI96(a96) ((bool)((uint32_t)(a96) >> 31)) +#define expF128UI96(a96) ((int32_t)((a96) >> 16) & 0x7FFF) +#define fracF128UI96(a96) ((a96)&0x0000FFFF) +#define packToF128UI96(sign, exp, sig96) (((uint32_t)(sign) << 31) + ((uint32_t)(exp) << 16) + (sig96)) -bool softfloat_isNaNF128M( const uint32_t * ); +bool softfloat_isNaNF128M(const uint32_t*); -bool - softfloat_tryPropagateNaNF128M( - const uint32_t *, const uint32_t *, uint32_t * ); -void softfloat_invalidF128M( uint32_t * ); +bool softfloat_tryPropagateNaNF128M(const uint32_t*, const uint32_t*, uint32_t*); +void softfloat_invalidF128M(uint32_t*); -int softfloat_shiftNormSigF128M( const uint32_t *, uint_fast8_t, uint32_t * ); +int softfloat_shiftNormSigF128M(const uint32_t*, uint_fast8_t, uint32_t*); -void softfloat_roundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); -void softfloat_normRoundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); +void softfloat_roundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*); +void softfloat_normRoundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*); -void - softfloat_addF128M( const uint32_t *, const uint32_t *, uint32_t *, bool ); -void - softfloat_mulAddF128M( - const uint32_t *, - const uint32_t *, - const uint32_t *, - uint32_t *, - uint_fast8_t - ); +void softfloat_addF128M(const uint32_t*, const uint32_t*, uint32_t*, bool); +void softfloat_mulAddF128M(const uint32_t*, const uint32_t*, const uint32_t*, uint32_t*, uint_fast8_t); #endif #endif - diff --git a/softfloat/source/include/opts-GCC.h b/softfloat/source/include/opts-GCC.h index 18c1523..99a4127 100644 --- a/softfloat/source/include/opts-GCC.h +++ b/softfloat/source/include/opts-GCC.h @@ -39,70 +39,70 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef INLINE -#include #include "primitiveTypes.h" +#include #ifdef SOFTFLOAT_BUILTIN_CLZ -INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) - { return a ? __builtin_clz( a ) - 16 : 16; } +INLINE uint_fast8_t softfloat_countLeadingZeros16(uint16_t a) { return a ? __builtin_clz(a) - 16 : 16; } #define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16 -INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) - { return a ? __builtin_clz( a ) : 32; } +INLINE uint_fast8_t softfloat_countLeadingZeros32(uint32_t a) { return a ? __builtin_clz(a) : 32; } #define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 -INLINE uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ) - { return a ? __builtin_clzll( a ) : 64; } +INLINE uint_fast8_t softfloat_countLeadingZeros64(uint64_t a) { return a ? __builtin_clzll(a) : 64; } #define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 #endif #ifdef SOFTFLOAT_INTRINSIC_INT128 -INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) -{ - union { unsigned __int128 ui; struct uint128 s; } uZ; - uZ.ui = (unsigned __int128) a * ((uint_fast64_t) b<<32); +INLINE struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) { + union { + unsigned __int128 ui; + struct uint128 s; + } uZ; + uZ.ui = (unsigned __int128)a * ((uint_fast64_t)b << 32); return uZ.s; } #define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128 -INLINE struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ) -{ - union { unsigned __int128 ui; struct uint128 s; } uZ; - uZ.ui = (unsigned __int128) a * b; +INLINE struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b) { + union { + unsigned __int128 ui; + struct uint128 s; + } uZ; + uZ.ui = (unsigned __int128)a * b; return uZ.s; } #define softfloat_mul64To128 softfloat_mul64To128 INLINE -struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) -{ - union { unsigned __int128 ui; struct uint128 s; } uZ; - uZ.ui = ((unsigned __int128) a64<<64 | a0) * b; +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) { + union { + unsigned __int128 ui; + struct uint128 s; + } uZ; + uZ.ui = ((unsigned __int128)a64 << 64 | a0) * b; return uZ.s; } #define softfloat_mul128By32 softfloat_mul128By32 INLINE -void - softfloat_mul128To256M( - uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr ) -{ +void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t* zPtr) { unsigned __int128 z0, mid1, mid, z128; - z0 = (unsigned __int128) a0 * b0; - mid1 = (unsigned __int128) a64 * b0; - mid = mid1 + (unsigned __int128) a0 * b64; - z128 = (unsigned __int128) a64 * b64; - z128 += (unsigned __int128) (mid < mid1)<<64 | mid>>64; + z0 = (unsigned __int128)a0 * b0; + mid1 = (unsigned __int128)a64 * b0; + mid = mid1 + (unsigned __int128)a0 * b64; + z128 = (unsigned __int128)a64 * b64; + z128 += (unsigned __int128)(mid < mid1) << 64 | mid >> 64; mid <<= 64; z0 += mid; z128 += (z0 < mid); - zPtr[indexWord( 4, 0 )] = z0; - zPtr[indexWord( 4, 1 )] = z0>>64; - zPtr[indexWord( 4, 2 )] = z128; - zPtr[indexWord( 4, 3 )] = z128>>64; + zPtr[indexWord(4, 0)] = z0; + zPtr[indexWord(4, 1)] = z0 >> 64; + zPtr[indexWord(4, 2)] = z128; + zPtr[indexWord(4, 3)] = z128 >> 64; } #define softfloat_mul128To256M softfloat_mul128To256M @@ -111,4 +111,3 @@ void #endif #endif - diff --git a/softfloat/source/include/primitiveTypes.h b/softfloat/source/include/primitiveTypes.h index a4a6dd1..fca21f9 100644 --- a/softfloat/source/include/primitiveTypes.h +++ b/softfloat/source/include/primitiveTypes.h @@ -42,13 +42,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef SOFTFLOAT_FAST_INT64 #ifdef LITTLEENDIAN -struct uint128 { uint64_t v0, v64; }; -struct uint64_extra { uint64_t extra, v; }; -struct uint128_extra { uint64_t extra; struct uint128 v; }; +struct uint128 { + uint64_t v0, v64; +}; +struct uint64_extra { + uint64_t extra, v; +}; +struct uint128_extra { + uint64_t extra; + struct uint128 v; +}; #else -struct uint128 { uint64_t v64, v0; }; -struct uint64_extra { uint64_t v, extra; }; -struct uint128_extra { struct uint128 v; uint64_t extra; }; +struct uint128 { + uint64_t v64, v0; +}; +struct uint64_extra { + uint64_t v, extra; +}; +struct uint128_extra { + struct uint128 v; + uint64_t extra; +}; #endif #endif @@ -59,27 +73,28 @@ struct uint128_extra { struct uint128 v; uint64_t extra; }; *----------------------------------------------------------------------------*/ #ifdef LITTLEENDIAN #define wordIncr 1 -#define indexWord( total, n ) (n) -#define indexWordHi( total ) ((total) - 1) -#define indexWordLo( total ) 0 -#define indexMultiword( total, m, n ) (n) -#define indexMultiwordHi( total, n ) ((total) - (n)) -#define indexMultiwordLo( total, n ) 0 -#define indexMultiwordHiBut( total, n ) (n) -#define indexMultiwordLoBut( total, n ) 0 -#define INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 } +#define indexWord(total, n) (n) +#define indexWordHi(total) ((total)-1) +#define indexWordLo(total) 0 +#define indexMultiword(total, m, n) (n) +#define indexMultiwordHi(total, n) ((total) - (n)) +#define indexMultiwordLo(total, n) 0 +#define indexMultiwordHiBut(total, n) (n) +#define indexMultiwordLoBut(total, n) 0 +#define INIT_UINTM4(v3, v2, v1, v0) \ + { v0, v1, v2, v3 } #else #define wordIncr -1 -#define indexWord( total, n ) ((total) - 1 - (n)) -#define indexWordHi( total ) 0 -#define indexWordLo( total ) ((total) - 1) -#define indexMultiword( total, m, n ) ((total) - 1 - (m)) -#define indexMultiwordHi( total, n ) 0 -#define indexMultiwordLo( total, n ) ((total) - (n)) -#define indexMultiwordHiBut( total, n ) 0 -#define indexMultiwordLoBut( total, n ) (n) -#define INIT_UINTM4( v3, v2, v1, v0 ) { v3, v2, v1, v0 } +#define indexWord(total, n) ((total)-1 - (n)) +#define indexWordHi(total) 0 +#define indexWordLo(total) ((total)-1) +#define indexMultiword(total, m, n) ((total)-1 - (m)) +#define indexMultiwordHi(total, n) 0 +#define indexMultiwordLo(total, n) ((total) - (n)) +#define indexMultiwordHiBut(total, n) 0 +#define indexMultiwordLoBut(total, n) (n) +#define INIT_UINTM4(v3, v2, v1, v0) \ + { v3, v2, v1, v0 } #endif #endif - diff --git a/softfloat/source/include/primitives.h b/softfloat/source/include/primitives.h index 863ab45..11967d2 100644 --- a/softfloat/source/include/primitives.h +++ b/softfloat/source/include/primitives.h @@ -37,9 +37,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef primitives_h #define primitives_h 1 +#include "primitiveTypes.h" #include #include -#include "primitiveTypes.h" #ifndef softfloat_shortShiftRightJam64 /*---------------------------------------------------------------------------- @@ -50,10 +50,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ) - { return a>>dist | ((a & (((uint_fast64_t) 1<> dist | ((a & (((uint_fast64_t)1 << dist) - 1)) != 0); } #else -uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ); +uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint_fast8_t dist); #endif #endif @@ -68,13 +67,11 @@ uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ); | is zero or nonzero. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) -INLINE uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ) -{ - return - (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0); +INLINE uint32_t softfloat_shiftRightJam32(uint32_t a, uint_fast16_t dist) { + return (dist < 31) ? a >> dist | ((uint32_t)(a << (-dist & 31)) != 0) : (a != 0); } #else -uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ); +uint32_t softfloat_shiftRightJam32(uint32_t a, uint_fast16_t dist); #endif #endif @@ -89,13 +86,11 @@ uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist ); | is zero or nonzero. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) -INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist ) -{ - return - (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0); +INLINE uint64_t softfloat_shiftRightJam64(uint64_t a, uint_fast32_t dist) { + return (dist < 63) ? a >> dist | ((uint64_t)(a << (-dist & 63)) != 0) : (a != 0); } #else -uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist ); +uint64_t softfloat_shiftRightJam64(uint64_t a, uint_fast32_t dist); #endif #endif @@ -112,10 +107,9 @@ extern const uint_least8_t softfloat_countLeadingZeros8[256]; | 'a'. If 'a' is zero, 16 is returned. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) -INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) -{ +INLINE uint_fast8_t softfloat_countLeadingZeros16(uint16_t a) { uint_fast8_t count = 8; - if ( 0x100 <= a ) { + if(0x100 <= a) { count = 0; a >>= 8; } @@ -123,7 +117,7 @@ INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) return count; } #else -uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ); +uint_fast8_t softfloat_countLeadingZeros16(uint16_t a); #endif #endif @@ -133,22 +127,21 @@ uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ); | 'a'. If 'a' is zero, 32 is returned. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) -INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) -{ +INLINE uint_fast8_t softfloat_countLeadingZeros32(uint32_t a) { uint_fast8_t count = 0; - if ( a < 0x10000 ) { + if(a < 0x10000) { count = 16; a <<= 16; } - if ( a < 0x1000000 ) { + if(a < 0x1000000) { count += 8; a <<= 8; } - count += softfloat_countLeadingZeros8[a>>24]; + count += softfloat_countLeadingZeros8[a >> 24]; return count; } #else -uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ); +uint_fast8_t softfloat_countLeadingZeros32(uint32_t a); #endif #endif @@ -157,7 +150,7 @@ uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ); | Returns the number of leading 0 bits before the most-significant 1 bit of | 'a'. If 'a' is zero, 64 is returned. *----------------------------------------------------------------------------*/ -uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ); +uint_fast8_t softfloat_countLeadingZeros64(uint64_t a); #endif extern const uint16_t softfloat_approxRecip_1k0s[16]; @@ -176,9 +169,9 @@ extern const uint16_t softfloat_approxRecip_1k1s[16]; | (units in the last place). *----------------------------------------------------------------------------*/ #ifdef SOFTFLOAT_FAST_DIV64TO32 -#define softfloat_approxRecip32_1( a ) ((uint32_t) (UINT64_C( 0x7FFFFFFFFFFFFFFF ) / (uint32_t) (a))) +#define softfloat_approxRecip32_1(a) ((uint32_t)(UINT64_C(0x7FFFFFFFFFFFFFFF) / (uint32_t)(a))) #else -uint32_t softfloat_approxRecip32_1( uint32_t a ); +uint32_t softfloat_approxRecip32_1(uint32_t a); #endif #endif @@ -204,7 +197,7 @@ extern const uint16_t softfloat_approxRecipSqrt_1k1s[16]; | returned is also always within the range 0.5 to 1; thus, the most- | significant bit of the result is always set. *----------------------------------------------------------------------------*/ -uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a ); +uint32_t softfloat_approxRecipSqrt32_1(unsigned int oddExpA, uint32_t a); #endif #ifdef SOFTFLOAT_FAST_INT64 @@ -222,10 +215,9 @@ uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a ); *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (1 <= INLINE_LEVEL) INLINE -bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) - { return (a64 == b64) && (a0 == b0); } +bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 == b64) && (a0 == b0); } #else -bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); #endif #endif @@ -237,10 +229,9 @@ bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) - { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); } +bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); } #else -bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); #endif #endif @@ -252,10 +243,9 @@ bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) - { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); } +bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); } #else -bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); #endif #endif @@ -266,17 +256,14 @@ bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -struct uint128 - softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist ) -{ +struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist) { struct uint128 z; - z.v64 = a64<>(-dist & 63); - z.v0 = a0<> (-dist & 63); + z.v0 = a0 << dist; return z; } #else -struct uint128 - softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist ); +struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist); #endif #endif @@ -287,17 +274,14 @@ struct uint128 *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -struct uint128 - softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist ) -{ +struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist) { struct uint128 z; - z.v64 = a64>>dist; - z.v0 = a64<<(-dist & 63) | a0>>dist; + z.v64 = a64 >> dist; + z.v0 = a64 << (-dist & 63) | a0 >> dist; return z; } #else -struct uint128 - softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist ); +struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist); #endif #endif @@ -308,19 +292,14 @@ struct uint128 *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -struct uint64_extra - softfloat_shortShiftRightJam64Extra( - uint64_t a, uint64_t extra, uint_fast8_t dist ) -{ +struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist) { struct uint64_extra z; - z.v = a>>dist; - z.extra = a<<(-dist & 63) | (extra != 0); + z.v = a >> dist; + z.extra = a << (-dist & 63) | (extra != 0); return z; } #else -struct uint64_extra - softfloat_shortShiftRightJam64Extra( - uint64_t a, uint64_t extra, uint_fast8_t dist ); +struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist); #endif #endif @@ -334,22 +313,15 @@ struct uint64_extra *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) INLINE -struct uint128 - softfloat_shortShiftRightJam128( - uint64_t a64, uint64_t a0, uint_fast8_t dist ) -{ +struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist) { uint_fast8_t negDist = -dist; struct uint128 z; - z.v64 = a64>>dist; - z.v0 = - a64<<(negDist & 63) | a0>>dist - | ((uint64_t) (a0<<(negDist & 63)) != 0); + z.v64 = a64 >> dist; + z.v0 = a64 << (negDist & 63) | a0 >> dist | ((uint64_t)(a0 << (negDist & 63)) != 0); return z; } #else -struct uint128 - softfloat_shortShiftRightJam128( - uint64_t a64, uint64_t a0, uint_fast8_t dist ); +struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist); #endif #endif @@ -360,21 +332,16 @@ struct uint128 *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) INLINE -struct uint128_extra - softfloat_shortShiftRightJam128Extra( - uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist ) -{ +struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist) { uint_fast8_t negDist = -dist; struct uint128_extra z; - z.v.v64 = a64>>dist; - z.v.v0 = a64<<(negDist & 63) | a0>>dist; - z.extra = a0<<(negDist & 63) | (extra != 0); + z.v.v64 = a64 >> dist; + z.v.v0 = a64 << (negDist & 63) | a0 >> dist; + z.extra = a0 << (negDist & 63) | (extra != 0); return z; } #else -struct uint128_extra - softfloat_shortShiftRightJam128Extra( - uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist ); +struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist); #endif #endif @@ -397,14 +364,11 @@ struct uint128_extra *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) INLINE -struct uint64_extra - softfloat_shiftRightJam64Extra( - uint64_t a, uint64_t extra, uint_fast32_t dist ) -{ +struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist) { struct uint64_extra z; - if ( dist < 64 ) { - z.v = a>>dist; - z.extra = a<<(-dist & 63); + if(dist < 64) { + z.v = a >> dist; + z.extra = a << (-dist & 63); } else { z.v = 0; z.extra = (dist == 64) ? a : (a != 0); @@ -413,9 +377,7 @@ struct uint64_extra return z; } #else -struct uint64_extra - softfloat_shiftRightJam64Extra( - uint64_t a, uint64_t extra, uint_fast32_t dist ); +struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist); #endif #endif @@ -430,8 +392,7 @@ struct uint64_extra | greater than 128, the result will be either 0 or 1, depending on whether the | original 128 bits are all zeros. *----------------------------------------------------------------------------*/ -struct uint128 - softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist ); +struct uint128 softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint_fast32_t dist); #endif #ifndef softfloat_shiftRightJam128Extra @@ -452,9 +413,7 @@ struct uint128 | is modified as described above and returned in the 'extra' field of the | result.) *----------------------------------------------------------------------------*/ -struct uint128_extra - softfloat_shiftRightJam128Extra( - uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist ); +struct uint128_extra softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist); #endif #ifndef softfloat_shiftRightJam256M @@ -470,9 +429,7 @@ struct uint128_extra | is greater than 256, the stored result will be either 0 or 1, depending on | whether the original 256 bits are all zeros. *----------------------------------------------------------------------------*/ -void - softfloat_shiftRightJam256M( - const uint64_t *aPtr, uint_fast32_t dist, uint64_t *zPtr ); +void softfloat_shiftRightJam256M(const uint64_t* aPtr, uint_fast32_t dist, uint64_t* zPtr); #endif #ifndef softfloat_add128 @@ -483,17 +440,14 @@ void *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -struct uint128 - softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) -{ +struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { struct uint128 z; z.v0 = a0 + b0; z.v64 = a64 + b64 + (z.v0 < a0); return z; } #else -struct uint128 - softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); #endif #endif @@ -505,9 +459,7 @@ struct uint128 | an array of four 64-bit elements that concatenate in the platform's normal | endian order to form a 256-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_add256M( - const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ); +void softfloat_add256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr); #endif #ifndef softfloat_sub128 @@ -518,9 +470,7 @@ void *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -struct uint128 - softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) -{ +struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { struct uint128 z; z.v0 = a0 - b0; z.v64 = a64 - b64; @@ -528,8 +478,7 @@ struct uint128 return z; } #else -struct uint128 - softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0); #endif #endif @@ -542,9 +491,7 @@ struct uint128 | 64-bit elements that concatenate in the platform's normal endian order to | form a 256-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_sub256M( - const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ); +void softfloat_sub256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr); #endif #ifndef softfloat_mul64ByShifted32To128 @@ -552,17 +499,16 @@ void | Returns the 128-bit product of 'a', 'b', and 2^32. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) -INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) -{ +INLINE struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) { uint_fast64_t mid; struct uint128 z; - mid = (uint_fast64_t) (uint32_t) a * b; - z.v0 = mid<<32; - z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32); + mid = (uint_fast64_t)(uint32_t)a * b; + z.v0 = mid << 32; + z.v64 = (uint_fast64_t)(uint32_t)(a >> 32) * b + (mid >> 32); return z; } #else -struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ); +struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b); #endif #endif @@ -570,7 +516,7 @@ struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ); /*---------------------------------------------------------------------------- | Returns the 128-bit product of 'a' and 'b'. *----------------------------------------------------------------------------*/ -struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ); +struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b); #endif #ifndef softfloat_mul128By32 @@ -581,19 +527,18 @@ struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ); *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) INLINE -struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) -{ +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) { struct uint128 z; uint_fast64_t mid; uint_fast32_t carry; z.v0 = a0 * b; - mid = (uint_fast64_t) (uint32_t) (a0>>32) * b; - carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid); - z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32); + mid = (uint_fast64_t)(uint32_t)(a0 >> 32) * b; + carry = (uint32_t)((uint_fast32_t)(z.v0 >> 32) - (uint_fast32_t)mid); + z.v64 = a64 * b + (uint_fast32_t)((mid + carry) >> 32); return z; } #else -struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ); +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b); #endif #endif @@ -605,9 +550,7 @@ struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ); | Argument 'zPtr' points to an array of four 64-bit elements that concatenate | in the platform's normal endian order to form a 256-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_mul128To256M( - uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr ); +void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t* zPtr); #endif #else @@ -626,7 +569,7 @@ void | Each of 'aPtr' and 'bPtr' points to an array of three 32-bit elements that | concatenate in the platform's normal endian order to form a 96-bit integer. *----------------------------------------------------------------------------*/ -int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr ); +int_fast8_t softfloat_compare96M(const uint32_t* aPtr, const uint32_t* bPtr); #endif #ifndef softfloat_compare128M @@ -638,8 +581,7 @@ int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr ); | Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that | concatenate in the platform's normal endian order to form a 128-bit integer. *----------------------------------------------------------------------------*/ -int_fast8_t - softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr ); +int_fast8_t softfloat_compare128M(const uint32_t* aPtr, const uint32_t* bPtr); #endif #ifndef softfloat_shortShiftLeft64To96M @@ -652,19 +594,14 @@ int_fast8_t *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE -void - softfloat_shortShiftLeft64To96M( - uint64_t a, uint_fast8_t dist, uint32_t *zPtr ) -{ - zPtr[indexWord( 3, 0 )] = (uint32_t) a<>= 32 - dist; - zPtr[indexWord( 3, 2 )] = a>>32; - zPtr[indexWord( 3, 1 )] = a; + zPtr[indexWord(3, 2)] = a >> 32; + zPtr[indexWord(3, 1)] = a; } #else -void - softfloat_shortShiftLeft64To96M( - uint64_t a, uint_fast8_t dist, uint32_t *zPtr ); +void softfloat_shortShiftLeft64To96M(uint64_t a, uint_fast8_t dist, uint32_t* zPtr); #endif #endif @@ -678,13 +615,7 @@ void | that concatenate in the platform's normal endian order to form an N-bit | integer. *----------------------------------------------------------------------------*/ -void - softfloat_shortShiftLeftM( - uint_fast8_t size_words, - const uint32_t *aPtr, - uint_fast8_t dist, - uint32_t *zPtr - ); +void softfloat_shortShiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr); #endif #ifndef softfloat_shortShiftLeft96M @@ -692,7 +623,7 @@ void | This function or macro is the same as 'softfloat_shortShiftLeftM' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftLeft96M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 3, aPtr, dist, zPtr ) +#define softfloat_shortShiftLeft96M(aPtr, dist, zPtr) softfloat_shortShiftLeftM(3, aPtr, dist, zPtr) #endif #ifndef softfloat_shortShiftLeft128M @@ -700,7 +631,7 @@ void | This function or macro is the same as 'softfloat_shortShiftLeftM' with | 'size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftLeft128M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 4, aPtr, dist, zPtr ) +#define softfloat_shortShiftLeft128M(aPtr, dist, zPtr) softfloat_shortShiftLeftM(4, aPtr, dist, zPtr) #endif #ifndef softfloat_shortShiftLeft160M @@ -708,7 +639,7 @@ void | This function or macro is the same as 'softfloat_shortShiftLeftM' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftLeft160M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 5, aPtr, dist, zPtr ) +#define softfloat_shortShiftLeft160M(aPtr, dist, zPtr) softfloat_shortShiftLeftM(5, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftLeftM @@ -722,13 +653,7 @@ void | The value of 'dist' can be arbitrarily large. In particular, if 'dist' is | greater than N, the stored result will be 0. *----------------------------------------------------------------------------*/ -void - softfloat_shiftLeftM( - uint_fast8_t size_words, - const uint32_t *aPtr, - uint32_t dist, - uint32_t *zPtr - ); +void softfloat_shiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr); #endif #ifndef softfloat_shiftLeft96M @@ -736,7 +661,7 @@ void | This function or macro is the same as 'softfloat_shiftLeftM' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_shiftLeft96M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 3, aPtr, dist, zPtr ) +#define softfloat_shiftLeft96M(aPtr, dist, zPtr) softfloat_shiftLeftM(3, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftLeft128M @@ -744,7 +669,7 @@ void | This function or macro is the same as 'softfloat_shiftLeftM' with | 'size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_shiftLeft128M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 4, aPtr, dist, zPtr ) +#define softfloat_shiftLeft128M(aPtr, dist, zPtr) softfloat_shiftLeftM(4, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftLeft160M @@ -752,7 +677,7 @@ void | This function or macro is the same as 'softfloat_shiftLeftM' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_shiftLeft160M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 5, aPtr, dist, zPtr ) +#define softfloat_shiftLeft160M(aPtr, dist, zPtr) softfloat_shiftLeftM(5, aPtr, dist, zPtr) #endif #ifndef softfloat_shortShiftRightM @@ -765,13 +690,7 @@ void | that concatenate in the platform's normal endian order to form an N-bit | integer. *----------------------------------------------------------------------------*/ -void - softfloat_shortShiftRightM( - uint_fast8_t size_words, - const uint32_t *aPtr, - uint_fast8_t dist, - uint32_t *zPtr - ); +void softfloat_shortShiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr); #endif #ifndef softfloat_shortShiftRight128M @@ -779,7 +698,7 @@ void | This function or macro is the same as 'softfloat_shortShiftRightM' with | 'size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftRight128M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 4, aPtr, dist, zPtr ) +#define softfloat_shortShiftRight128M(aPtr, dist, zPtr) softfloat_shortShiftRightM(4, aPtr, dist, zPtr) #endif #ifndef softfloat_shortShiftRight160M @@ -787,7 +706,7 @@ void | This function or macro is the same as 'softfloat_shortShiftRightM' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftRight160M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 5, aPtr, dist, zPtr ) +#define softfloat_shortShiftRight160M(aPtr, dist, zPtr) softfloat_shortShiftRightM(5, aPtr, dist, zPtr) #endif #ifndef softfloat_shortShiftRightJamM @@ -801,9 +720,7 @@ void | to a 'size_words'-long array of 32-bit elements that concatenate in the | platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_shortShiftRightJamM( - uint_fast8_t, const uint32_t *, uint_fast8_t, uint32_t * ); +void softfloat_shortShiftRightJamM(uint_fast8_t, const uint32_t*, uint_fast8_t, uint32_t*); #endif #ifndef softfloat_shortShiftRightJam160M @@ -811,7 +728,7 @@ void | This function or macro is the same as 'softfloat_shortShiftRightJamM' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_shortShiftRightJam160M( aPtr, dist, zPtr ) softfloat_shortShiftRightJamM( 5, aPtr, dist, zPtr ) +#define softfloat_shortShiftRightJam160M(aPtr, dist, zPtr) softfloat_shortShiftRightJamM(5, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftRightM @@ -825,13 +742,7 @@ void | The value of 'dist' can be arbitrarily large. In particular, if 'dist' is | greater than N, the stored result will be 0. *----------------------------------------------------------------------------*/ -void - softfloat_shiftRightM( - uint_fast8_t size_words, - const uint32_t *aPtr, - uint32_t dist, - uint32_t *zPtr - ); +void softfloat_shiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr); #endif #ifndef softfloat_shiftRight96M @@ -839,7 +750,7 @@ void | This function or macro is the same as 'softfloat_shiftRightM' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_shiftRight96M( aPtr, dist, zPtr ) softfloat_shiftRightM( 3, aPtr, dist, zPtr ) +#define softfloat_shiftRight96M(aPtr, dist, zPtr) softfloat_shiftRightM(3, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftRightJamM @@ -856,13 +767,7 @@ void | is greater than N, the stored result will be either 0 or 1, depending on | whether the original N bits are all zeros. *----------------------------------------------------------------------------*/ -void - softfloat_shiftRightJamM( - uint_fast8_t size_words, - const uint32_t *aPtr, - uint32_t dist, - uint32_t *zPtr - ); +void softfloat_shiftRightJamM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr); #endif #ifndef softfloat_shiftRightJam96M @@ -870,7 +775,7 @@ void | This function or macro is the same as 'softfloat_shiftRightJamM' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_shiftRightJam96M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 3, aPtr, dist, zPtr ) +#define softfloat_shiftRightJam96M(aPtr, dist, zPtr) softfloat_shiftRightJamM(3, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftRightJam128M @@ -878,7 +783,7 @@ void | This function or macro is the same as 'softfloat_shiftRightJamM' with | 'size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_shiftRightJam128M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 4, aPtr, dist, zPtr ) +#define softfloat_shiftRightJam128M(aPtr, dist, zPtr) softfloat_shiftRightJamM(4, aPtr, dist, zPtr) #endif #ifndef softfloat_shiftRightJam160M @@ -886,7 +791,7 @@ void | This function or macro is the same as 'softfloat_shiftRightJamM' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_shiftRightJam160M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 5, aPtr, dist, zPtr ) +#define softfloat_shiftRightJam160M(aPtr, dist, zPtr) softfloat_shiftRightJamM(5, aPtr, dist, zPtr) #endif #ifndef softfloat_addM @@ -898,13 +803,7 @@ void | elements that concatenate in the platform's normal endian order to form an | N-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_addM( - uint_fast8_t size_words, - const uint32_t *aPtr, - const uint32_t *bPtr, - uint32_t *zPtr - ); +void softfloat_addM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr); #endif #ifndef softfloat_add96M @@ -912,7 +811,7 @@ void | This function or macro is the same as 'softfloat_addM' with 'size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_add96M( aPtr, bPtr, zPtr ) softfloat_addM( 3, aPtr, bPtr, zPtr ) +#define softfloat_add96M(aPtr, bPtr, zPtr) softfloat_addM(3, aPtr, bPtr, zPtr) #endif #ifndef softfloat_add128M @@ -920,7 +819,7 @@ void | This function or macro is the same as 'softfloat_addM' with 'size_words' | = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_add128M( aPtr, bPtr, zPtr ) softfloat_addM( 4, aPtr, bPtr, zPtr ) +#define softfloat_add128M(aPtr, bPtr, zPtr) softfloat_addM(4, aPtr, bPtr, zPtr) #endif #ifndef softfloat_add160M @@ -928,7 +827,7 @@ void | This function or macro is the same as 'softfloat_addM' with 'size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_add160M( aPtr, bPtr, zPtr ) softfloat_addM( 5, aPtr, bPtr, zPtr ) +#define softfloat_add160M(aPtr, bPtr, zPtr) softfloat_addM(5, aPtr, bPtr, zPtr) #endif #ifndef softfloat_addCarryM @@ -940,14 +839,7 @@ void | points to a 'size_words'-long array of 32-bit elements that concatenate in | the platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ -uint_fast8_t - softfloat_addCarryM( - uint_fast8_t size_words, - const uint32_t *aPtr, - const uint32_t *bPtr, - uint_fast8_t carry, - uint32_t *zPtr - ); +uint_fast8_t softfloat_addCarryM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint_fast8_t carry, uint32_t* zPtr); #endif #ifndef softfloat_addComplCarryM @@ -956,14 +848,8 @@ uint_fast8_t | the value of the unsigned integer pointed to by 'bPtr' is bit-wise completed | before the addition. *----------------------------------------------------------------------------*/ -uint_fast8_t - softfloat_addComplCarryM( - uint_fast8_t size_words, - const uint32_t *aPtr, - const uint32_t *bPtr, - uint_fast8_t carry, - uint32_t *zPtr - ); +uint_fast8_t softfloat_addComplCarryM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint_fast8_t carry, + uint32_t* zPtr); #endif #ifndef softfloat_addComplCarry96M @@ -971,7 +857,7 @@ uint_fast8_t | This function or macro is the same as 'softfloat_addComplCarryM' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_addComplCarry96M( aPtr, bPtr, carry, zPtr ) softfloat_addComplCarryM( 3, aPtr, bPtr, carry, zPtr ) +#define softfloat_addComplCarry96M(aPtr, bPtr, carry, zPtr) softfloat_addComplCarryM(3, aPtr, bPtr, carry, zPtr) #endif #ifndef softfloat_negXM @@ -981,7 +867,7 @@ uint_fast8_t | points to a 'size_words'-long array of 32-bit elements that concatenate in | the platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ -void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); +void softfloat_negXM(uint_fast8_t size_words, uint32_t* zPtr); #endif #ifndef softfloat_negX96M @@ -989,7 +875,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_negXM' with 'size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_negX96M( zPtr ) softfloat_negXM( 3, zPtr ) +#define softfloat_negX96M(zPtr) softfloat_negXM(3, zPtr) #endif #ifndef softfloat_negX128M @@ -997,7 +883,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_negXM' with 'size_words' | = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_negX128M( zPtr ) softfloat_negXM( 4, zPtr ) +#define softfloat_negX128M(zPtr) softfloat_negXM(4, zPtr) #endif #ifndef softfloat_negX160M @@ -1005,7 +891,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_negXM' with 'size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_negX160M( zPtr ) softfloat_negXM( 5, zPtr ) +#define softfloat_negX160M(zPtr) softfloat_negXM(5, zPtr) #endif #ifndef softfloat_negX256M @@ -1013,7 +899,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_negXM' with 'size_words' | = 8 (N = 256). *----------------------------------------------------------------------------*/ -#define softfloat_negX256M( zPtr ) softfloat_negXM( 8, zPtr ) +#define softfloat_negX256M(zPtr) softfloat_negXM(8, zPtr) #endif #ifndef softfloat_sub1XM @@ -1024,7 +910,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); | elements that concatenate in the platform's normal endian order to form an | N-bit integer. *----------------------------------------------------------------------------*/ -void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ); +void softfloat_sub1XM(uint_fast8_t size_words, uint32_t* zPtr); #endif #ifndef softfloat_sub1X96M @@ -1032,7 +918,7 @@ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_sub1XM' with 'size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_sub1X96M( zPtr ) softfloat_sub1XM( 3, zPtr ) +#define softfloat_sub1X96M(zPtr) softfloat_sub1XM(3, zPtr) #endif #ifndef softfloat_sub1X160M @@ -1040,7 +926,7 @@ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ); | This function or macro is the same as 'softfloat_sub1XM' with 'size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_sub1X160M( zPtr ) softfloat_sub1XM( 5, zPtr ) +#define softfloat_sub1X160M(zPtr) softfloat_sub1XM(5, zPtr) #endif #ifndef softfloat_subM @@ -1052,13 +938,7 @@ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ); | array of 32-bit elements that concatenate in the platform's normal endian | order to form an N-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_subM( - uint_fast8_t size_words, - const uint32_t *aPtr, - const uint32_t *bPtr, - uint32_t *zPtr - ); +void softfloat_subM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr); #endif #ifndef softfloat_sub96M @@ -1066,7 +946,7 @@ void | This function or macro is the same as 'softfloat_subM' with 'size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_sub96M( aPtr, bPtr, zPtr ) softfloat_subM( 3, aPtr, bPtr, zPtr ) +#define softfloat_sub96M(aPtr, bPtr, zPtr) softfloat_subM(3, aPtr, bPtr, zPtr) #endif #ifndef softfloat_sub128M @@ -1074,7 +954,7 @@ void | This function or macro is the same as 'softfloat_subM' with 'size_words' | = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_sub128M( aPtr, bPtr, zPtr ) softfloat_subM( 4, aPtr, bPtr, zPtr ) +#define softfloat_sub128M(aPtr, bPtr, zPtr) softfloat_subM(4, aPtr, bPtr, zPtr) #endif #ifndef softfloat_sub160M @@ -1082,7 +962,7 @@ void | This function or macro is the same as 'softfloat_subM' with 'size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_sub160M( aPtr, bPtr, zPtr ) softfloat_subM( 5, aPtr, bPtr, zPtr ) +#define softfloat_sub160M(aPtr, bPtr, zPtr) softfloat_subM(5, aPtr, bPtr, zPtr) #endif #ifndef softfloat_mul64To128M @@ -1092,7 +972,7 @@ void | elements that concatenate in the platform's normal endian order to form a | 128-bit integer. *----------------------------------------------------------------------------*/ -void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr ); +void softfloat_mul64To128M(uint64_t a, uint64_t b, uint32_t* zPtr); #endif #ifndef softfloat_mul128MTo256M @@ -1104,9 +984,7 @@ void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr ); | Argument 'zPtr' points to an array of eight 32-bit elements that concatenate | to form a 256-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_mul128MTo256M( - const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ); +void softfloat_mul128MTo256M(const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr); #endif #ifndef softfloat_remStepMBy32 @@ -1119,15 +997,8 @@ void | to a 'size_words'-long array of 32-bit elements that concatenate in the | platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ -void - softfloat_remStepMBy32( - uint_fast8_t size_words, - const uint32_t *remPtr, - uint_fast8_t dist, - const uint32_t *bPtr, - uint32_t q, - uint32_t *zPtr - ); +void softfloat_remStepMBy32(uint_fast8_t size_words, const uint32_t* remPtr, uint_fast8_t dist, const uint32_t* bPtr, uint32_t q, + uint32_t* zPtr); #endif #ifndef softfloat_remStep96MBy32 @@ -1135,7 +1006,7 @@ void | This function or macro is the same as 'softfloat_remStepMBy32' with | 'size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ -#define softfloat_remStep96MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 3, remPtr, dist, bPtr, q, zPtr ) +#define softfloat_remStep96MBy32(remPtr, dist, bPtr, q, zPtr) softfloat_remStepMBy32(3, remPtr, dist, bPtr, q, zPtr) #endif #ifndef softfloat_remStep128MBy32 @@ -1143,7 +1014,7 @@ void | This function or macro is the same as 'softfloat_remStepMBy32' with | 'size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ -#define softfloat_remStep128MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 4, remPtr, dist, bPtr, q, zPtr ) +#define softfloat_remStep128MBy32(remPtr, dist, bPtr, q, zPtr) softfloat_remStepMBy32(4, remPtr, dist, bPtr, q, zPtr) #endif #ifndef softfloat_remStep160MBy32 @@ -1151,10 +1022,9 @@ void | This function or macro is the same as 'softfloat_remStepMBy32' with | 'size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ -#define softfloat_remStep160MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 5, remPtr, dist, bPtr, q, zPtr ) +#define softfloat_remStep160MBy32(remPtr, dist, bPtr, q, zPtr) softfloat_remStepMBy32(5, remPtr, dist, bPtr, q, zPtr) #endif #endif #endif - diff --git a/softfloat/source/include/softfloat.h b/softfloat/source/include/softfloat.h index b33374c..f07211e 100644 --- a/softfloat/source/include/softfloat.h +++ b/softfloat/source/include/softfloat.h @@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ - /*============================================================================ | Note: If SoftFloat is made available as a general library for programs to | use, it is strongly recommended that a platform-specific version of this @@ -42,13 +41,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | eliminates all dependencies on compile-time macros. *============================================================================*/ - #ifndef softfloat_h #define softfloat_h 1 +#include "softfloat_types.h" #include #include -#include "softfloat_types.h" #ifndef THREAD_LOCAL #define THREAD_LOCAL @@ -58,10 +56,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | Software floating-point underflow tininess-detection mode. *----------------------------------------------------------------------------*/ extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess; -enum { - softfloat_tininess_beforeRounding = 0, - softfloat_tininess_afterRounding = 1 -}; +enum { softfloat_tininess_beforeRounding = 0, softfloat_tininess_afterRounding = 1 }; /*---------------------------------------------------------------------------- | Software floating-point rounding mode. (Mode "odd" is supported only if @@ -69,12 +64,12 @@ enum { *----------------------------------------------------------------------------*/ extern THREAD_LOCAL uint_fast8_t softfloat_roundingMode; enum { - softfloat_round_near_even = 0, - softfloat_round_minMag = 1, - softfloat_round_min = 2, - softfloat_round_max = 3, + softfloat_round_near_even = 0, + softfloat_round_minMag = 1, + softfloat_round_min = 2, + softfloat_round_max = 3, softfloat_round_near_maxMag = 4, - softfloat_round_odd = 6 + softfloat_round_odd = 6 }; /*---------------------------------------------------------------------------- @@ -82,162 +77,162 @@ enum { *----------------------------------------------------------------------------*/ extern THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags; enum { - softfloat_flag_inexact = 1, - softfloat_flag_underflow = 2, - softfloat_flag_overflow = 4, - softfloat_flag_infinite = 8, - softfloat_flag_invalid = 16 + softfloat_flag_inexact = 1, + softfloat_flag_underflow = 2, + softfloat_flag_overflow = 4, + softfloat_flag_infinite = 8, + softfloat_flag_invalid = 16 }; /*---------------------------------------------------------------------------- | Routine to raise any or all of the software floating-point exception flags. *----------------------------------------------------------------------------*/ -void softfloat_raiseFlags( uint_fast8_t ); +void softfloat_raiseFlags(uint_fast8_t); /*---------------------------------------------------------------------------- | Integer-to-floating-point conversion routines. *----------------------------------------------------------------------------*/ -float16_t ui32_to_f16( uint32_t ); -float32_t ui32_to_f32( uint32_t ); -float64_t ui32_to_f64( uint32_t ); +float16_t ui32_to_f16(uint32_t); +float32_t ui32_to_f32(uint32_t); +float64_t ui32_to_f64(uint32_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t ui32_to_extF80( uint32_t ); -float128_t ui32_to_f128( uint32_t ); +extFloat80_t ui32_to_extF80(uint32_t); +float128_t ui32_to_f128(uint32_t); #endif -void ui32_to_extF80M( uint32_t, extFloat80_t * ); -void ui32_to_f128M( uint32_t, float128_t * ); -float16_t ui64_to_f16( uint64_t ); -float32_t ui64_to_f32( uint64_t ); -float64_t ui64_to_f64( uint64_t ); +void ui32_to_extF80M(uint32_t, extFloat80_t*); +void ui32_to_f128M(uint32_t, float128_t*); +float16_t ui64_to_f16(uint64_t); +float32_t ui64_to_f32(uint64_t); +float64_t ui64_to_f64(uint64_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t ui64_to_extF80( uint64_t ); -float128_t ui64_to_f128( uint64_t ); +extFloat80_t ui64_to_extF80(uint64_t); +float128_t ui64_to_f128(uint64_t); #endif -void ui64_to_extF80M( uint64_t, extFloat80_t * ); -void ui64_to_f128M( uint64_t, float128_t * ); -float16_t i32_to_f16( int32_t ); -float32_t i32_to_f32( int32_t ); -float64_t i32_to_f64( int32_t ); +void ui64_to_extF80M(uint64_t, extFloat80_t*); +void ui64_to_f128M(uint64_t, float128_t*); +float16_t i32_to_f16(int32_t); +float32_t i32_to_f32(int32_t); +float64_t i32_to_f64(int32_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t i32_to_extF80( int32_t ); -float128_t i32_to_f128( int32_t ); +extFloat80_t i32_to_extF80(int32_t); +float128_t i32_to_f128(int32_t); #endif -void i32_to_extF80M( int32_t, extFloat80_t * ); -void i32_to_f128M( int32_t, float128_t * ); -float16_t i64_to_f16( int64_t ); -float32_t i64_to_f32( int64_t ); -float64_t i64_to_f64( int64_t ); +void i32_to_extF80M(int32_t, extFloat80_t*); +void i32_to_f128M(int32_t, float128_t*); +float16_t i64_to_f16(int64_t); +float32_t i64_to_f32(int64_t); +float64_t i64_to_f64(int64_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t i64_to_extF80( int64_t ); -float128_t i64_to_f128( int64_t ); +extFloat80_t i64_to_extF80(int64_t); +float128_t i64_to_f128(int64_t); #endif -void i64_to_extF80M( int64_t, extFloat80_t * ); -void i64_to_f128M( int64_t, float128_t * ); +void i64_to_extF80M(int64_t, extFloat80_t*); +void i64_to_f128M(int64_t, float128_t*); /*---------------------------------------------------------------------------- | 16-bit (half-precision) floating-point operations. *----------------------------------------------------------------------------*/ -uint_fast32_t f16_to_ui32( float16_t, uint_fast8_t, bool ); -uint_fast64_t f16_to_ui64( float16_t, uint_fast8_t, bool ); -int_fast32_t f16_to_i32( float16_t, uint_fast8_t, bool ); -int_fast64_t f16_to_i64( float16_t, uint_fast8_t, bool ); -uint_fast32_t f16_to_ui32_r_minMag( float16_t, bool ); -uint_fast64_t f16_to_ui64_r_minMag( float16_t, bool ); -int_fast32_t f16_to_i32_r_minMag( float16_t, bool ); -int_fast64_t f16_to_i64_r_minMag( float16_t, bool ); -float32_t f16_to_f32( float16_t ); -float64_t f16_to_f64( float16_t ); +uint_fast32_t f16_to_ui32(float16_t, uint_fast8_t, bool); +uint_fast64_t f16_to_ui64(float16_t, uint_fast8_t, bool); +int_fast32_t f16_to_i32(float16_t, uint_fast8_t, bool); +int_fast64_t f16_to_i64(float16_t, uint_fast8_t, bool); +uint_fast32_t f16_to_ui32_r_minMag(float16_t, bool); +uint_fast64_t f16_to_ui64_r_minMag(float16_t, bool); +int_fast32_t f16_to_i32_r_minMag(float16_t, bool); +int_fast64_t f16_to_i64_r_minMag(float16_t, bool); +float32_t f16_to_f32(float16_t); +float64_t f16_to_f64(float16_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t f16_to_extF80( float16_t ); -float128_t f16_to_f128( float16_t ); +extFloat80_t f16_to_extF80(float16_t); +float128_t f16_to_f128(float16_t); #endif -void f16_to_extF80M( float16_t, extFloat80_t * ); -void f16_to_f128M( float16_t, float128_t * ); -float16_t f16_roundToInt( float16_t, uint_fast8_t, bool ); -float16_t f16_add( float16_t, float16_t ); -float16_t f16_sub( float16_t, float16_t ); -float16_t f16_mul( float16_t, float16_t ); -float16_t f16_mulAdd( float16_t, float16_t, float16_t ); -float16_t f16_div( float16_t, float16_t ); -float16_t f16_rem( float16_t, float16_t ); -float16_t f16_sqrt( float16_t ); -bool f16_eq( float16_t, float16_t ); -bool f16_le( float16_t, float16_t ); -bool f16_lt( float16_t, float16_t ); -bool f16_eq_signaling( float16_t, float16_t ); -bool f16_le_quiet( float16_t, float16_t ); -bool f16_lt_quiet( float16_t, float16_t ); -bool f16_isSignalingNaN( float16_t ); +void f16_to_extF80M(float16_t, extFloat80_t*); +void f16_to_f128M(float16_t, float128_t*); +float16_t f16_roundToInt(float16_t, uint_fast8_t, bool); +float16_t f16_add(float16_t, float16_t); +float16_t f16_sub(float16_t, float16_t); +float16_t f16_mul(float16_t, float16_t); +float16_t f16_mulAdd(float16_t, float16_t, float16_t); +float16_t f16_div(float16_t, float16_t); +float16_t f16_rem(float16_t, float16_t); +float16_t f16_sqrt(float16_t); +bool f16_eq(float16_t, float16_t); +bool f16_le(float16_t, float16_t); +bool f16_lt(float16_t, float16_t); +bool f16_eq_signaling(float16_t, float16_t); +bool f16_le_quiet(float16_t, float16_t); +bool f16_lt_quiet(float16_t, float16_t); +bool f16_isSignalingNaN(float16_t); /*---------------------------------------------------------------------------- | 32-bit (single-precision) floating-point operations. *----------------------------------------------------------------------------*/ -uint_fast32_t f32_to_ui32( float32_t, uint_fast8_t, bool ); -uint_fast64_t f32_to_ui64( float32_t, uint_fast8_t, bool ); -int_fast32_t f32_to_i32( float32_t, uint_fast8_t, bool ); -int_fast64_t f32_to_i64( float32_t, uint_fast8_t, bool ); -uint_fast32_t f32_to_ui32_r_minMag( float32_t, bool ); -uint_fast64_t f32_to_ui64_r_minMag( float32_t, bool ); -int_fast32_t f32_to_i32_r_minMag( float32_t, bool ); -int_fast64_t f32_to_i64_r_minMag( float32_t, bool ); -float16_t f32_to_f16( float32_t ); -float64_t f32_to_f64( float32_t ); +uint_fast32_t f32_to_ui32(float32_t, uint_fast8_t, bool); +uint_fast64_t f32_to_ui64(float32_t, uint_fast8_t, bool); +int_fast32_t f32_to_i32(float32_t, uint_fast8_t, bool); +int_fast64_t f32_to_i64(float32_t, uint_fast8_t, bool); +uint_fast32_t f32_to_ui32_r_minMag(float32_t, bool); +uint_fast64_t f32_to_ui64_r_minMag(float32_t, bool); +int_fast32_t f32_to_i32_r_minMag(float32_t, bool); +int_fast64_t f32_to_i64_r_minMag(float32_t, bool); +float16_t f32_to_f16(float32_t); +float64_t f32_to_f64(float32_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t f32_to_extF80( float32_t ); -float128_t f32_to_f128( float32_t ); +extFloat80_t f32_to_extF80(float32_t); +float128_t f32_to_f128(float32_t); #endif -void f32_to_extF80M( float32_t, extFloat80_t * ); -void f32_to_f128M( float32_t, float128_t * ); -float32_t f32_roundToInt( float32_t, uint_fast8_t, bool ); -float32_t f32_add( float32_t, float32_t ); -float32_t f32_sub( float32_t, float32_t ); -float32_t f32_mul( float32_t, float32_t ); -float32_t f32_mulAdd( float32_t, float32_t, float32_t ); -float32_t f32_div( float32_t, float32_t ); -float32_t f32_rem( float32_t, float32_t ); -float32_t f32_sqrt( float32_t ); -bool f32_eq( float32_t, float32_t ); -bool f32_le( float32_t, float32_t ); -bool f32_lt( float32_t, float32_t ); -bool f32_eq_signaling( float32_t, float32_t ); -bool f32_le_quiet( float32_t, float32_t ); -bool f32_lt_quiet( float32_t, float32_t ); -bool f32_isSignalingNaN( float32_t ); +void f32_to_extF80M(float32_t, extFloat80_t*); +void f32_to_f128M(float32_t, float128_t*); +float32_t f32_roundToInt(float32_t, uint_fast8_t, bool); +float32_t f32_add(float32_t, float32_t); +float32_t f32_sub(float32_t, float32_t); +float32_t f32_mul(float32_t, float32_t); +float32_t f32_mulAdd(float32_t, float32_t, float32_t); +float32_t f32_div(float32_t, float32_t); +float32_t f32_rem(float32_t, float32_t); +float32_t f32_sqrt(float32_t); +bool f32_eq(float32_t, float32_t); +bool f32_le(float32_t, float32_t); +bool f32_lt(float32_t, float32_t); +bool f32_eq_signaling(float32_t, float32_t); +bool f32_le_quiet(float32_t, float32_t); +bool f32_lt_quiet(float32_t, float32_t); +bool f32_isSignalingNaN(float32_t); /*---------------------------------------------------------------------------- | 64-bit (double-precision) floating-point operations. *----------------------------------------------------------------------------*/ -uint_fast32_t f64_to_ui32( float64_t, uint_fast8_t, bool ); -uint_fast64_t f64_to_ui64( float64_t, uint_fast8_t, bool ); -int_fast32_t f64_to_i32( float64_t, uint_fast8_t, bool ); -int_fast64_t f64_to_i64( float64_t, uint_fast8_t, bool ); -uint_fast32_t f64_to_ui32_r_minMag( float64_t, bool ); -uint_fast64_t f64_to_ui64_r_minMag( float64_t, bool ); -int_fast32_t f64_to_i32_r_minMag( float64_t, bool ); -int_fast64_t f64_to_i64_r_minMag( float64_t, bool ); -float16_t f64_to_f16( float64_t ); -float32_t f64_to_f32( float64_t ); +uint_fast32_t f64_to_ui32(float64_t, uint_fast8_t, bool); +uint_fast64_t f64_to_ui64(float64_t, uint_fast8_t, bool); +int_fast32_t f64_to_i32(float64_t, uint_fast8_t, bool); +int_fast64_t f64_to_i64(float64_t, uint_fast8_t, bool); +uint_fast32_t f64_to_ui32_r_minMag(float64_t, bool); +uint_fast64_t f64_to_ui64_r_minMag(float64_t, bool); +int_fast32_t f64_to_i32_r_minMag(float64_t, bool); +int_fast64_t f64_to_i64_r_minMag(float64_t, bool); +float16_t f64_to_f16(float64_t); +float32_t f64_to_f32(float64_t); #ifdef SOFTFLOAT_FAST_INT64 -extFloat80_t f64_to_extF80( float64_t ); -float128_t f64_to_f128( float64_t ); +extFloat80_t f64_to_extF80(float64_t); +float128_t f64_to_f128(float64_t); #endif -void f64_to_extF80M( float64_t, extFloat80_t * ); -void f64_to_f128M( float64_t, float128_t * ); -float64_t f64_roundToInt( float64_t, uint_fast8_t, bool ); -float64_t f64_add( float64_t, float64_t ); -float64_t f64_sub( float64_t, float64_t ); -float64_t f64_mul( float64_t, float64_t ); -float64_t f64_mulAdd( float64_t, float64_t, float64_t ); -float64_t f64_div( float64_t, float64_t ); -float64_t f64_rem( float64_t, float64_t ); -float64_t f64_sqrt( float64_t ); -bool f64_eq( float64_t, float64_t ); -bool f64_le( float64_t, float64_t ); -bool f64_lt( float64_t, float64_t ); -bool f64_eq_signaling( float64_t, float64_t ); -bool f64_le_quiet( float64_t, float64_t ); -bool f64_lt_quiet( float64_t, float64_t ); -bool f64_isSignalingNaN( float64_t ); +void f64_to_extF80M(float64_t, extFloat80_t*); +void f64_to_f128M(float64_t, float128_t*); +float64_t f64_roundToInt(float64_t, uint_fast8_t, bool); +float64_t f64_add(float64_t, float64_t); +float64_t f64_sub(float64_t, float64_t); +float64_t f64_mul(float64_t, float64_t); +float64_t f64_mulAdd(float64_t, float64_t, float64_t); +float64_t f64_div(float64_t, float64_t); +float64_t f64_rem(float64_t, float64_t); +float64_t f64_sqrt(float64_t); +bool f64_eq(float64_t, float64_t); +bool f64_le(float64_t, float64_t); +bool f64_lt(float64_t, float64_t); +bool f64_eq_signaling(float64_t, float64_t); +bool f64_le_quiet(float64_t, float64_t); +bool f64_lt_quiet(float64_t, float64_t); +bool f64_isSignalingNaN(float64_t); /*---------------------------------------------------------------------------- | Rounding precision for 80-bit extended double-precision floating-point. @@ -249,124 +244,118 @@ extern THREAD_LOCAL uint_fast8_t extF80_roundingPrecision; | 80-bit extended double-precision floating-point operations. *----------------------------------------------------------------------------*/ #ifdef SOFTFLOAT_FAST_INT64 -uint_fast32_t extF80_to_ui32( extFloat80_t, uint_fast8_t, bool ); -uint_fast64_t extF80_to_ui64( extFloat80_t, uint_fast8_t, bool ); -int_fast32_t extF80_to_i32( extFloat80_t, uint_fast8_t, bool ); -int_fast64_t extF80_to_i64( extFloat80_t, uint_fast8_t, bool ); -uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t, bool ); -uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t, bool ); -int_fast32_t extF80_to_i32_r_minMag( extFloat80_t, bool ); -int_fast64_t extF80_to_i64_r_minMag( extFloat80_t, bool ); -float16_t extF80_to_f16( extFloat80_t ); -float32_t extF80_to_f32( extFloat80_t ); -float64_t extF80_to_f64( extFloat80_t ); -float128_t extF80_to_f128( extFloat80_t ); -extFloat80_t extF80_roundToInt( extFloat80_t, uint_fast8_t, bool ); -extFloat80_t extF80_add( extFloat80_t, extFloat80_t ); -extFloat80_t extF80_sub( extFloat80_t, extFloat80_t ); -extFloat80_t extF80_mul( extFloat80_t, extFloat80_t ); -extFloat80_t extF80_div( extFloat80_t, extFloat80_t ); -extFloat80_t extF80_rem( extFloat80_t, extFloat80_t ); -extFloat80_t extF80_sqrt( extFloat80_t ); -bool extF80_eq( extFloat80_t, extFloat80_t ); -bool extF80_le( extFloat80_t, extFloat80_t ); -bool extF80_lt( extFloat80_t, extFloat80_t ); -bool extF80_eq_signaling( extFloat80_t, extFloat80_t ); -bool extF80_le_quiet( extFloat80_t, extFloat80_t ); -bool extF80_lt_quiet( extFloat80_t, extFloat80_t ); -bool extF80_isSignalingNaN( extFloat80_t ); +uint_fast32_t extF80_to_ui32(extFloat80_t, uint_fast8_t, bool); +uint_fast64_t extF80_to_ui64(extFloat80_t, uint_fast8_t, bool); +int_fast32_t extF80_to_i32(extFloat80_t, uint_fast8_t, bool); +int_fast64_t extF80_to_i64(extFloat80_t, uint_fast8_t, bool); +uint_fast32_t extF80_to_ui32_r_minMag(extFloat80_t, bool); +uint_fast64_t extF80_to_ui64_r_minMag(extFloat80_t, bool); +int_fast32_t extF80_to_i32_r_minMag(extFloat80_t, bool); +int_fast64_t extF80_to_i64_r_minMag(extFloat80_t, bool); +float16_t extF80_to_f16(extFloat80_t); +float32_t extF80_to_f32(extFloat80_t); +float64_t extF80_to_f64(extFloat80_t); +float128_t extF80_to_f128(extFloat80_t); +extFloat80_t extF80_roundToInt(extFloat80_t, uint_fast8_t, bool); +extFloat80_t extF80_add(extFloat80_t, extFloat80_t); +extFloat80_t extF80_sub(extFloat80_t, extFloat80_t); +extFloat80_t extF80_mul(extFloat80_t, extFloat80_t); +extFloat80_t extF80_div(extFloat80_t, extFloat80_t); +extFloat80_t extF80_rem(extFloat80_t, extFloat80_t); +extFloat80_t extF80_sqrt(extFloat80_t); +bool extF80_eq(extFloat80_t, extFloat80_t); +bool extF80_le(extFloat80_t, extFloat80_t); +bool extF80_lt(extFloat80_t, extFloat80_t); +bool extF80_eq_signaling(extFloat80_t, extFloat80_t); +bool extF80_le_quiet(extFloat80_t, extFloat80_t); +bool extF80_lt_quiet(extFloat80_t, extFloat80_t); +bool extF80_isSignalingNaN(extFloat80_t); #endif -uint_fast32_t extF80M_to_ui32( const extFloat80_t *, uint_fast8_t, bool ); -uint_fast64_t extF80M_to_ui64( const extFloat80_t *, uint_fast8_t, bool ); -int_fast32_t extF80M_to_i32( const extFloat80_t *, uint_fast8_t, bool ); -int_fast64_t extF80M_to_i64( const extFloat80_t *, uint_fast8_t, bool ); -uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *, bool ); -uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *, bool ); -int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *, bool ); -int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *, bool ); -float16_t extF80M_to_f16( const extFloat80_t * ); -float32_t extF80M_to_f32( const extFloat80_t * ); -float64_t extF80M_to_f64( const extFloat80_t * ); -void extF80M_to_f128M( const extFloat80_t *, float128_t * ); -void - extF80M_roundToInt( - const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * ); -void extF80M_add( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); -void extF80M_sub( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); -void extF80M_mul( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); -void extF80M_div( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); -void extF80M_rem( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); -void extF80M_sqrt( const extFloat80_t *, extFloat80_t * ); -bool extF80M_eq( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_le( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_lt( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_eq_signaling( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_le_quiet( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_lt_quiet( const extFloat80_t *, const extFloat80_t * ); -bool extF80M_isSignalingNaN( const extFloat80_t * ); +uint_fast32_t extF80M_to_ui32(const extFloat80_t*, uint_fast8_t, bool); +uint_fast64_t extF80M_to_ui64(const extFloat80_t*, uint_fast8_t, bool); +int_fast32_t extF80M_to_i32(const extFloat80_t*, uint_fast8_t, bool); +int_fast64_t extF80M_to_i64(const extFloat80_t*, uint_fast8_t, bool); +uint_fast32_t extF80M_to_ui32_r_minMag(const extFloat80_t*, bool); +uint_fast64_t extF80M_to_ui64_r_minMag(const extFloat80_t*, bool); +int_fast32_t extF80M_to_i32_r_minMag(const extFloat80_t*, bool); +int_fast64_t extF80M_to_i64_r_minMag(const extFloat80_t*, bool); +float16_t extF80M_to_f16(const extFloat80_t*); +float32_t extF80M_to_f32(const extFloat80_t*); +float64_t extF80M_to_f64(const extFloat80_t*); +void extF80M_to_f128M(const extFloat80_t*, float128_t*); +void extF80M_roundToInt(const extFloat80_t*, uint_fast8_t, bool, extFloat80_t*); +void extF80M_add(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); +void extF80M_sub(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); +void extF80M_mul(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); +void extF80M_div(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); +void extF80M_rem(const extFloat80_t*, const extFloat80_t*, extFloat80_t*); +void extF80M_sqrt(const extFloat80_t*, extFloat80_t*); +bool extF80M_eq(const extFloat80_t*, const extFloat80_t*); +bool extF80M_le(const extFloat80_t*, const extFloat80_t*); +bool extF80M_lt(const extFloat80_t*, const extFloat80_t*); +bool extF80M_eq_signaling(const extFloat80_t*, const extFloat80_t*); +bool extF80M_le_quiet(const extFloat80_t*, const extFloat80_t*); +bool extF80M_lt_quiet(const extFloat80_t*, const extFloat80_t*); +bool extF80M_isSignalingNaN(const extFloat80_t*); /*---------------------------------------------------------------------------- | 128-bit (quadruple-precision) floating-point operations. *----------------------------------------------------------------------------*/ #ifdef SOFTFLOAT_FAST_INT64 -uint_fast32_t f128_to_ui32( float128_t, uint_fast8_t, bool ); -uint_fast64_t f128_to_ui64( float128_t, uint_fast8_t, bool ); -int_fast32_t f128_to_i32( float128_t, uint_fast8_t, bool ); -int_fast64_t f128_to_i64( float128_t, uint_fast8_t, bool ); -uint_fast32_t f128_to_ui32_r_minMag( float128_t, bool ); -uint_fast64_t f128_to_ui64_r_minMag( float128_t, bool ); -int_fast32_t f128_to_i32_r_minMag( float128_t, bool ); -int_fast64_t f128_to_i64_r_minMag( float128_t, bool ); -float16_t f128_to_f16( float128_t ); -float32_t f128_to_f32( float128_t ); -float64_t f128_to_f64( float128_t ); -extFloat80_t f128_to_extF80( float128_t ); -float128_t f128_roundToInt( float128_t, uint_fast8_t, bool ); -float128_t f128_add( float128_t, float128_t ); -float128_t f128_sub( float128_t, float128_t ); -float128_t f128_mul( float128_t, float128_t ); -float128_t f128_mulAdd( float128_t, float128_t, float128_t ); -float128_t f128_div( float128_t, float128_t ); -float128_t f128_rem( float128_t, float128_t ); -float128_t f128_sqrt( float128_t ); -bool f128_eq( float128_t, float128_t ); -bool f128_le( float128_t, float128_t ); -bool f128_lt( float128_t, float128_t ); -bool f128_eq_signaling( float128_t, float128_t ); -bool f128_le_quiet( float128_t, float128_t ); -bool f128_lt_quiet( float128_t, float128_t ); -bool f128_isSignalingNaN( float128_t ); +uint_fast32_t f128_to_ui32(float128_t, uint_fast8_t, bool); +uint_fast64_t f128_to_ui64(float128_t, uint_fast8_t, bool); +int_fast32_t f128_to_i32(float128_t, uint_fast8_t, bool); +int_fast64_t f128_to_i64(float128_t, uint_fast8_t, bool); +uint_fast32_t f128_to_ui32_r_minMag(float128_t, bool); +uint_fast64_t f128_to_ui64_r_minMag(float128_t, bool); +int_fast32_t f128_to_i32_r_minMag(float128_t, bool); +int_fast64_t f128_to_i64_r_minMag(float128_t, bool); +float16_t f128_to_f16(float128_t); +float32_t f128_to_f32(float128_t); +float64_t f128_to_f64(float128_t); +extFloat80_t f128_to_extF80(float128_t); +float128_t f128_roundToInt(float128_t, uint_fast8_t, bool); +float128_t f128_add(float128_t, float128_t); +float128_t f128_sub(float128_t, float128_t); +float128_t f128_mul(float128_t, float128_t); +float128_t f128_mulAdd(float128_t, float128_t, float128_t); +float128_t f128_div(float128_t, float128_t); +float128_t f128_rem(float128_t, float128_t); +float128_t f128_sqrt(float128_t); +bool f128_eq(float128_t, float128_t); +bool f128_le(float128_t, float128_t); +bool f128_lt(float128_t, float128_t); +bool f128_eq_signaling(float128_t, float128_t); +bool f128_le_quiet(float128_t, float128_t); +bool f128_lt_quiet(float128_t, float128_t); +bool f128_isSignalingNaN(float128_t); #endif -uint_fast32_t f128M_to_ui32( const float128_t *, uint_fast8_t, bool ); -uint_fast64_t f128M_to_ui64( const float128_t *, uint_fast8_t, bool ); -int_fast32_t f128M_to_i32( const float128_t *, uint_fast8_t, bool ); -int_fast64_t f128M_to_i64( const float128_t *, uint_fast8_t, bool ); -uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *, bool ); -uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *, bool ); -int_fast32_t f128M_to_i32_r_minMag( const float128_t *, bool ); -int_fast64_t f128M_to_i64_r_minMag( const float128_t *, bool ); -float16_t f128M_to_f16( const float128_t * ); -float32_t f128M_to_f32( const float128_t * ); -float64_t f128M_to_f64( const float128_t * ); -void f128M_to_extF80M( const float128_t *, extFloat80_t * ); -void f128M_roundToInt( const float128_t *, uint_fast8_t, bool, float128_t * ); -void f128M_add( const float128_t *, const float128_t *, float128_t * ); -void f128M_sub( const float128_t *, const float128_t *, float128_t * ); -void f128M_mul( const float128_t *, const float128_t *, float128_t * ); -void - f128M_mulAdd( - const float128_t *, const float128_t *, const float128_t *, float128_t * - ); -void f128M_div( const float128_t *, const float128_t *, float128_t * ); -void f128M_rem( const float128_t *, const float128_t *, float128_t * ); -void f128M_sqrt( const float128_t *, float128_t * ); -bool f128M_eq( const float128_t *, const float128_t * ); -bool f128M_le( const float128_t *, const float128_t * ); -bool f128M_lt( const float128_t *, const float128_t * ); -bool f128M_eq_signaling( const float128_t *, const float128_t * ); -bool f128M_le_quiet( const float128_t *, const float128_t * ); -bool f128M_lt_quiet( const float128_t *, const float128_t * ); -bool f128M_isSignalingNaN( const float128_t * ); +uint_fast32_t f128M_to_ui32(const float128_t*, uint_fast8_t, bool); +uint_fast64_t f128M_to_ui64(const float128_t*, uint_fast8_t, bool); +int_fast32_t f128M_to_i32(const float128_t*, uint_fast8_t, bool); +int_fast64_t f128M_to_i64(const float128_t*, uint_fast8_t, bool); +uint_fast32_t f128M_to_ui32_r_minMag(const float128_t*, bool); +uint_fast64_t f128M_to_ui64_r_minMag(const float128_t*, bool); +int_fast32_t f128M_to_i32_r_minMag(const float128_t*, bool); +int_fast64_t f128M_to_i64_r_minMag(const float128_t*, bool); +float16_t f128M_to_f16(const float128_t*); +float32_t f128M_to_f32(const float128_t*); +float64_t f128M_to_f64(const float128_t*); +void f128M_to_extF80M(const float128_t*, extFloat80_t*); +void f128M_roundToInt(const float128_t*, uint_fast8_t, bool, float128_t*); +void f128M_add(const float128_t*, const float128_t*, float128_t*); +void f128M_sub(const float128_t*, const float128_t*, float128_t*); +void f128M_mul(const float128_t*, const float128_t*, float128_t*); +void f128M_mulAdd(const float128_t*, const float128_t*, const float128_t*, float128_t*); +void f128M_div(const float128_t*, const float128_t*, float128_t*); +void f128M_rem(const float128_t*, const float128_t*, float128_t*); +void f128M_sqrt(const float128_t*, float128_t*); +bool f128M_eq(const float128_t*, const float128_t*); +bool f128M_le(const float128_t*, const float128_t*); +bool f128M_lt(const float128_t*, const float128_t*); +bool f128M_eq_signaling(const float128_t*, const float128_t*); +bool f128M_le_quiet(const float128_t*, const float128_t*); +bool f128M_lt_quiet(const float128_t*, const float128_t*); +bool f128M_isSignalingNaN(const float128_t*); #endif - diff --git a/softfloat/source/include/softfloat_types.h b/softfloat/source/include/softfloat_types.h index bc30e31..3fcc9d5 100644 --- a/softfloat/source/include/softfloat_types.h +++ b/softfloat/source/include/softfloat_types.h @@ -47,10 +47,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | the types below may, if desired, be defined as aliases for the native types | (typically 'float' and 'double', and possibly 'long double'). *----------------------------------------------------------------------------*/ -typedef struct { uint16_t v; } float16_t; -typedef struct { uint32_t v; } float32_t; -typedef struct { uint64_t v; } float64_t; -typedef struct { uint64_t v[2]; } float128_t; +typedef struct { + uint16_t v; +} float16_t; +typedef struct { + uint32_t v; +} float32_t; +typedef struct { + uint64_t v; +} float64_t; +typedef struct { + uint64_t v[2]; +} float128_t; /*---------------------------------------------------------------------------- | The format of an 80-bit extended floating-point number in memory. This @@ -58,9 +66,15 @@ typedef struct { uint64_t v[2]; } float128_t; | named 'signif'. *----------------------------------------------------------------------------*/ #ifdef LITTLEENDIAN -struct extFloat80M { uint64_t signif; uint16_t signExp; }; +struct extFloat80M { + uint64_t signif; + uint16_t signExp; +}; #else -struct extFloat80M { uint16_t signExp; uint64_t signif; }; +struct extFloat80M { + uint16_t signExp; + uint64_t signif; +}; #endif /*---------------------------------------------------------------------------- @@ -78,4 +92,3 @@ struct extFloat80M { uint16_t signExp; uint64_t signif; }; typedef struct extFloat80M extFloat80_t; #endif - diff --git a/src/iss/arch/hwl.h b/src/iss/arch/hwl.h index 80f0798..c0b5185 100644 --- a/src/iss/arch/hwl.h +++ b/src/iss/arch/hwl.h @@ -50,45 +50,67 @@ public: virtual ~hwl() = default; protected: - iss::status read_custom_csr_reg(unsigned addr, reg_t &val) override; + iss::status read_custom_csr_reg(unsigned addr, reg_t& val) override; iss::status write_custom_csr_reg(unsigned addr, reg_t val) override; }; - -template -inline hwl::hwl(feature_config cfg): BASE(cfg) { - for (unsigned addr = 0x800; addr < 0x803; ++addr){ +template +inline hwl::hwl(feature_config cfg) +: BASE(cfg) { + for(unsigned addr = 0x800; addr < 0x803; ++addr) { this->register_custom_csr_rd(addr); this->register_custom_csr_wr(addr); } - for (unsigned addr = 0x804; addr < 0x807; ++addr){ + for(unsigned addr = 0x804; addr < 0x807; ++addr) { this->register_custom_csr_rd(addr); this->register_custom_csr_wr(addr); } } -template -inline iss::status iss::arch::hwl::read_custom_csr_reg(unsigned addr, reg_t &val) { - switch(addr){ - case 0x800: val = this->reg.lpstart0; break; - case 0x801: val = this->reg.lpend0; break; - case 0x802: val = this->reg.lpcount0; break; - case 0x804: val = this->reg.lpstart1; break; - case 0x805: val = this->reg.lpend1; break; - case 0x806: val = this->reg.lpcount1; break; +template inline iss::status iss::arch::hwl::read_custom_csr_reg(unsigned addr, reg_t& val) { + switch(addr) { + case 0x800: + val = this->reg.lpstart0; + break; + case 0x801: + val = this->reg.lpend0; + break; + case 0x802: + val = this->reg.lpcount0; + break; + case 0x804: + val = this->reg.lpstart1; + break; + case 0x805: + val = this->reg.lpend1; + break; + case 0x806: + val = this->reg.lpcount1; + break; } return iss::Ok; } -template -inline iss::status iss::arch::hwl::write_custom_csr_reg(unsigned addr, reg_t val) { - switch(addr){ - case 0x800: this->reg.lpstart0 = val; break; - case 0x801: this->reg.lpend0 = val; break; - case 0x802: this->reg.lpcount0 = val; break; - case 0x804: this->reg.lpstart1 = val; break; - case 0x805: this->reg.lpend1 = val; break; - case 0x806: this->reg.lpcount1 = val; break; +template inline iss::status iss::arch::hwl::write_custom_csr_reg(unsigned addr, reg_t val) { + switch(addr) { + case 0x800: + this->reg.lpstart0 = val; + break; + case 0x801: + this->reg.lpend0 = val; + break; + case 0x802: + this->reg.lpcount0 = val; + break; + case 0x804: + this->reg.lpstart1 = val; + break; + case 0x805: + this->reg.lpend1 = val; + break; + case 0x806: + this->reg.lpcount1 = val; + break; } return iss::Ok; } @@ -96,5 +118,4 @@ inline iss::status iss::arch::hwl::write_custom_csr_reg(unsigned addr, reg } // namespace arch } // namespace iss - #endif /* _RISCV_HART_M_P_H */ diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index 4125297..4ac086d 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -43,7 +43,7 @@ namespace arch { enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 }; -enum features_e{FEAT_NONE, FEAT_PMP=1, FEAT_EXT_N=2, FEAT_CLIC=4, FEAT_DEBUG=8, FEAT_TCM=16}; +enum features_e { FEAT_NONE, FEAT_PMP = 1, FEAT_EXT_N = 2, FEAT_CLIC = 4, FEAT_DEBUG = 8, FEAT_TCM = 16 }; enum riscv_csr { /* user-level CSR */ @@ -51,17 +51,17 @@ enum riscv_csr { ustatus = 0x000, uie = 0x004, utvec = 0x005, - utvt = 0x007, //CLIC + utvt = 0x007, // CLIC // User Trap Handling uscratch = 0x040, uepc = 0x041, ucause = 0x042, utval = 0x043, uip = 0x044, - uxnti = 0x045, //CLIC - uintstatus = 0xCB1, // MRW Current interrupt levels (CLIC) - addr subject to change - uintthresh = 0x047, // MRW Interrupt-level threshold (CLIC) - addr subject to change - uscratchcsw = 0x048, // MRW Conditional scratch swap on priv mode change (CLIC) + uxnti = 0x045, // CLIC + uintstatus = 0xCB1, // MRW Current interrupt levels (CLIC) - addr subject to change + uintthresh = 0x047, // MRW Interrupt-level threshold (CLIC) - addr subject to change + uscratchcsw = 0x048, // MRW Conditional scratch swap on priv mode change (CLIC) uscratchcswl = 0x049, // MRW Conditional scratch swap on level change (CLIC) // User Floating-Point CSRs fflags = 0x001, @@ -112,17 +112,17 @@ enum riscv_csr { mie = 0x304, mtvec = 0x305, mcounteren = 0x306, - mtvt = 0x307, //CLIC + mtvt = 0x307, // CLIC // Machine Trap Handling mscratch = 0x340, mepc = 0x341, mcause = 0x342, mtval = 0x343, mip = 0x344, - mxnti = 0x345, //CLIC - mintstatus = 0xFB1, // MRW Current interrupt levels (CLIC) - addr subject to change - mintthresh = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change - mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC) + mxnti = 0x345, // CLIC + mintstatus = 0xFB1, // MRW Current interrupt levels (CLIC) - addr subject to change + mintthresh = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change + mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC) mscratchcswl = 0x349, // MRW Conditional scratch swap on level change (CLIC) // Physical Memory Protection pmpcfg0 = 0x3A0, @@ -175,7 +175,6 @@ enum riscv_csr { dscratch1 = 0x7B3 }; - enum { PGSHIFT = 12, PTE_PPN_SHIFT = 10, @@ -193,7 +192,7 @@ enum { 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, PRIV_D = 4}; +enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3, PRIV_D = 4 }; enum { ISA_A = 1, @@ -256,49 +255,49 @@ public: : trap_access(15 << 16, badaddr) {} }; -inline void read_reg_uint32(uint64_t offs, uint32_t& reg, uint8_t *const data, unsigned length) { +inline void read_reg_uint32(uint64_t offs, uint32_t& reg, uint8_t* const data, unsigned length) { auto reg_ptr = reinterpret_cast(®); - switch (offs & 0x3) { + switch(offs & 0x3) { case 0: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(data + i) = *(reg_ptr + i); - break; + break; case 1: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(data + i) = *(reg_ptr + 1 + i); - break; + break; case 2: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(data + i) = *(reg_ptr + 2 + i); - break; + break; case 3: *data = *(reg_ptr + 3); - break; + break; } } -inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const data, unsigned length) { +inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t* const data, unsigned length) { auto reg_ptr = reinterpret_cast(®); - switch (offs & 0x3) { + switch(offs & 0x3) { case 0: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(reg_ptr + i) = *(data + i); - break; + break; case 1: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(reg_ptr + 1 + i) = *(data + i); - break; + break; case 2: - for (auto i = 0U; i < length; ++i) + for(auto i = 0U; i < length; ++i) *(reg_ptr + 2 + i) = *(data + i); - break; + break; case 3: - *(reg_ptr + 3) = *data ; - break; + *(reg_ptr + 3) = *data; + break; } } -} -} +} // namespace arch +} // namespace iss #endif diff --git a/src/iss/arch/riscv_hart_m_p.h b/src/iss/arch/riscv_hart_m_p.h index 26e327d..0109ecc 100644 --- a/src/iss/arch/riscv_hart_m_p.h +++ b/src/iss/arch/riscv_hart_m_p.h @@ -35,22 +35,22 @@ #ifndef _RISCV_HART_M_P_H #define _RISCV_HART_M_P_H -#include "riscv_hart_common.h" #include "iss/arch/traits.h" #include "iss/instrumentation_if.h" #include "iss/log_categories.h" #include "iss/vm_if.h" +#include "riscv_hart_common.h" #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY #endif #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -66,30 +66,31 @@ namespace iss { namespace arch { -template class riscv_hart_m_p : public BASE { +template class riscv_hart_m_p : public BASE { protected: const std::array lvl = {{'U', 'S', 'H', 'M'}}; - const std::array trap_str = {{"" - "Instruction address misaligned", // 0 - "Instruction access fault", // 1 - "Illegal instruction", // 2 - "Breakpoint", // 3 - "Load address misaligned", // 4 - "Load access fault", // 5 - "Store/AMO address misaligned", // 6 - "Store/AMO access fault", // 7 - "Environment call from U-mode", // 8 - "Environment call from S-mode", // 9 - "Reserved", // a - "Environment call from M-mode", // b - "Instruction page fault", // c - "Load page fault", // d - "Reserved", // e - "Store/AMO page fault"}}; - const std::array irq_str = { - {"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt", - "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", - "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; + const std::array trap_str = {{"" + "Instruction address misaligned", // 0 + "Instruction access fault", // 1 + "Illegal instruction", // 2 + "Breakpoint", // 3 + "Load address misaligned", // 4 + "Load access fault", // 5 + "Store/AMO address misaligned", // 6 + "Store/AMO access fault", // 7 + "Environment call from U-mode", // 8 + "Environment call from S-mode", // 9 + "Reserved", // a + "Environment call from M-mode", // b + "Instruction page fault", // c + "Load page fault", // d + "Reserved", // e + "Store/AMO page fault"}}; + const std::array 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"}}; + public: using core = BASE; using this_class = riscv_hart_m_p; @@ -97,10 +98,10 @@ public: using reg_t = typename core::reg_t; using addr_t = typename core::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); - using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t *const); - using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const *const); + using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t&); + using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); + using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t* const); + using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const* const); // primary template template struct hart_state {}; @@ -108,7 +109,8 @@ public: template class hart_state::value>::type> { public: BEGIN_BF_DECL(mstatus_t, T); - // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) BF_FIELD(SD, 31, 1); // Trap SRET BF_FIELD(TSR, 22, 1); @@ -122,7 +124,8 @@ public: BF_FIELD(SUM, 18, 1); // Modify PRiVilege BF_FIELD(MPRV, 17, 1); - // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty BF_FIELD(XS, 15, 2); // floating-point unit status Off/Initial/Clean/Dirty BF_FIELD(FS, 13, 2); @@ -149,13 +152,13 @@ public: static const reg_t mstatus_reset_val = 0x1800; void write_mstatus(T val) { - auto mask = get_mask() &0xff; // MPP is hardcode as 0x3 + auto mask = get_mask() & 0xff; // MPP is hardcode as 0x3 auto new_val = (mstatus.backing.val & ~mask) | (val & mask); mstatus = new_val; } static constexpr uint32_t get_mask() { - //return 0x807ff988UL; // 0b1000 0000 0111 1111 1111 1000 1000 1000 // only machine mode is supported + // return 0x807ff988UL; // 0b1000 0000 0111 1111 1111 1000 1000 1000 // only machine mode is supported // +-SD // | +-TSR // | |+-TW @@ -177,7 +180,8 @@ public: template class hart_state::value>::type> { public: BEGIN_BF_DECL(mstatus_t, T); - // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) BF_FIELD(SD, 63, 1); // value of XLEN for S-mode BF_FIELD(SXL, 34, 2); @@ -195,7 +199,8 @@ public: BF_FIELD(SUM, 18, 1); // Modify PRiVilege BF_FIELD(MPRV, 17, 1); - // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty BF_FIELD(XS, 15, 2); // floating-point unit status Off/Initial/Clean/Dirty BF_FIELD(FS, 13, 2); @@ -222,13 +227,13 @@ public: static const reg_t mstatus_reset_val = 0x1800; void write_mstatus(T val) { - auto mask = get_mask() &0xff; // MPP is hardcode as 0x3 + auto mask = get_mask() & 0xff; // MPP is hardcode as 0x3 auto new_val = (mstatus.backing.val & ~mask) | (val & mask); mstatus = new_val; } static constexpr T get_mask() { - //return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + // return 0x8000000f007ff9ddULL; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 // // +-TSR // |+-TW @@ -252,12 +257,8 @@ public: return 0b100010001000; // only machine mode is supported } - constexpr bool has_compressed() { - return traits::MISA_VAL&0b0100; - } - constexpr reg_t get_pc_mask() { - return has_compressed()?(reg_t)~1:(reg_t)~3; - } + constexpr bool has_compressed() { return traits::MISA_VAL & 0b0100; } + constexpr reg_t get_pc_mask() { return has_compressed() ? (reg_t)~1 : (reg_t)~3; } riscv_hart_m_p(feature_config cfg = feature_config{}); virtual ~riscv_hart_m_p() = default; @@ -266,36 +267,33 @@ public: std::pair load_file(std::string name, int type = -1) override; - iss::status read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) override; - iss::status write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) override; + iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + uint8_t* const data) override; + iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + const uint8_t* const data) override; uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); } uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; uint64_t leave_trap(uint64_t flags) override; - const reg_t& get_mhartid() const { return mhartid_reg; } - void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; + const reg_t& get_mhartid() const { return mhartid_reg; } + void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; void disass_output(uint64_t pc, const std::string instr) override { - CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", - pc, instr, (reg_t)state.mstatus, this->reg.icount + cycle_offset); + CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", pc, instr, (reg_t)state.mstatus, + this->reg.icount + cycle_offset); }; - iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } + iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; } - void set_csr(unsigned addr, reg_t val){ - csr[addr & csr.page_addr_mask] = val; - } + void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; } + + void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); } - void set_irq_num(unsigned i) { - mcause_max_irq=1< &arch) + riscv_instrumentation_if(riscv_hart_m_p& arch) : arch(arch) {} /** * get the name of this architecture @@ -320,20 +318,20 @@ protected: bool is_branch_taken() override { return arch.reg.last_branch; } - unsigned get_reg_num() override {return traits::NUM_REGS;} + unsigned get_reg_num() override { return traits::NUM_REGS; } - riscv_hart_m_p &arch; + riscv_hart_m_p& arch; }; friend struct riscv_instrumentation_if; - virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data); - virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data); + virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t* const data); + virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data); - iss::status read_clic(uint64_t addr, unsigned length, uint8_t *const data); - iss::status write_clic(uint64_t addr, unsigned length, const uint8_t *const data); + iss::status read_clic(uint64_t addr, unsigned length, uint8_t* const data); + iss::status write_clic(uint64_t addr, unsigned length, const uint8_t* const data); - virtual iss::status read_csr(unsigned addr, reg_t &val); + virtual iss::status read_csr(unsigned addr, reg_t& val); virtual iss::status write_csr(unsigned addr, reg_t val); hart_state_type state; @@ -360,7 +358,7 @@ protected: uint8_t clic_cfg_reg{0}; std::array clic_inttrig_reg; union clic_int_reg_t { - struct{ + struct { uint8_t ip; uint8_t ie; uint8_t attr; @@ -374,43 +372,39 @@ protected: std::vector tcm; - iss::status read_csr_reg(unsigned addr, reg_t &val); + iss::status read_csr_reg(unsigned addr, reg_t& val); iss::status write_csr_reg(unsigned addr, reg_t val); - iss::status read_null(unsigned addr, reg_t &val); - iss::status write_null(unsigned addr, reg_t val){return iss::status::Ok;} - iss::status read_cycle(unsigned addr, reg_t &val); + iss::status read_null(unsigned addr, reg_t& val); + iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; } + iss::status read_cycle(unsigned addr, reg_t& val); iss::status write_cycle(unsigned addr, reg_t val); - iss::status read_instret(unsigned addr, reg_t &val); + iss::status read_instret(unsigned addr, reg_t& val); iss::status write_instret(unsigned addr, reg_t val); - iss::status read_tvec(unsigned addr, reg_t &val); - iss::status read_time(unsigned addr, reg_t &val); - iss::status read_status(unsigned addr, reg_t &val); + iss::status read_tvec(unsigned addr, reg_t& val); + iss::status read_time(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_cause(unsigned addr, reg_t &val); + iss::status read_cause(unsigned addr, reg_t& val); iss::status write_cause(unsigned addr, reg_t val); - iss::status read_ie(unsigned addr, reg_t &val); + iss::status read_ie(unsigned addr, reg_t& val); iss::status write_ie(unsigned addr, reg_t val); - iss::status read_ip(unsigned addr, reg_t &val); - iss::status read_hartid(unsigned addr, reg_t &val); + iss::status read_ip(unsigned addr, reg_t& val); + iss::status read_hartid(unsigned addr, reg_t& val); iss::status write_epc(unsigned addr, reg_t val); iss::status read_intstatus(unsigned addr, reg_t& val); iss::status write_intthresh(unsigned addr, reg_t val); iss::status write_xtvt(unsigned addr, reg_t val); iss::status write_dcsr_dcsr(unsigned addr, reg_t val); - iss::status read_dcsr_reg(unsigned addr, reg_t &val); + iss::status read_dcsr_reg(unsigned addr, reg_t& val); iss::status write_dcsr_reg(unsigned addr, reg_t val); - iss::status read_dpc_reg(unsigned addr, reg_t &val); + iss::status read_dpc_reg(unsigned addr, reg_t& val); iss::status write_dpc_reg(unsigned addr, reg_t val); - virtual iss::status read_custom_csr_reg(unsigned addr, reg_t &val) {return iss::status::Err;}; - virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) {return iss::status::Err;}; + virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; }; + virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; }; - void register_custom_csr_rd(unsigned addr){ - csr_rd_cb[addr] = &this_class::read_custom_csr_reg; - } - void register_custom_csr_wr(unsigned addr){ - csr_wr_cb[addr] = &this_class::write_custom_csr_reg; - } + void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; } + void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; } reg_t mhartid_reg{0x0}; @@ -421,10 +415,10 @@ protected: std::vector> memfn_write; void insert_mem_range(uint64_t, uint64_t, std::function, std::function); feature_config cfg; - uint64_t mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; - inline bool debug_mode_active() {return this->reg.PRIV&0x4;} - std::pair, std::function> - replace_mem_access(std::function rd, std::function wr){ + uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16}; + inline bool debug_mode_active() { return this->reg.PRIV & 0x4; } + std::pair, std::function> replace_mem_access(std::function rd, + std::function wr) { std::pair, std::function> ret{hart_mem_rd_delegate, hart_mem_wr_delegate}; hart_mem_rd_delegate = rd; hart_mem_wr_delegate = wr; @@ -446,52 +440,61 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr[mimpid] = 1; uart_buf.str(""); - for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ + for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; csr_wr_cb[addr] = &this_class::write_csr_reg; } - if(traits::XLEN==32) for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ + if(traits::XLEN == 32) + for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_csr_reg; + } + for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; csr_wr_cb[addr] = &this_class::write_csr_reg; } - for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_csr_reg; - } - for (unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr){ + for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; } - if(traits::XLEN==32) for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - //csr_wr_cb[addr] = &this_class::write_csr_reg; - } + if(traits::XLEN == 32) + for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + // csr_wr_cb[addr] = &this_class::write_csr_reg; + } // common regs const std::array roaddrs{{misa, mvendorid, marchid, mimpid}}; - for(auto addr: roaddrs) { + for(auto addr : roaddrs) { csr_rd_cb[addr] = &this_class::read_csr_reg; csr_wr_cb[addr] = &this_class::write_null; } const std::array rwaddrs{{mepc, mtvec, mscratch, mtval}}; - for(auto addr: rwaddrs) { + for(auto addr : rwaddrs) { csr_rd_cb[addr] = &this_class::read_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg; } // special handling & overrides csr_rd_cb[time] = &this_class::read_time; - if(traits::XLEN==32) csr_rd_cb[timeh] = &this_class::read_time; + if(traits::XLEN == 32) + csr_rd_cb[timeh] = &this_class::read_time; csr_rd_cb[cycle] = &this_class::read_cycle; - if(traits::XLEN==32) csr_rd_cb[cycleh] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_rd_cb[cycleh] = &this_class::read_cycle; csr_rd_cb[instret] = &this_class::read_instret; - if(traits::XLEN==32) csr_rd_cb[instreth] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_rd_cb[instreth] = &this_class::read_instret; csr_rd_cb[mcycle] = &this_class::read_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle; - if(traits::XLEN==32) csr_rd_cb[mcycleh] = &this_class::read_cycle; - if(traits::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle; + if(traits::XLEN == 32) + csr_rd_cb[mcycleh] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_wr_cb[mcycleh] = &this_class::write_cycle; csr_rd_cb[minstret] = &this_class::read_instret; csr_wr_cb[minstret] = &this_class::write_instret; - if(traits::XLEN==32) csr_rd_cb[minstreth] = &this_class::read_instret; - if(traits::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret; + if(traits::XLEN == 32) + csr_rd_cb[minstreth] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[mstatus] = &this_class::read_status; csr_wr_cb[mstatus] = &this_class::write_status; csr_rd_cb[mcause] = &this_class::read_cause; @@ -510,39 +513,40 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) if(FEAT & FEAT_CLIC) { csr_rd_cb[mtvt] = &this_class::read_csr_reg; csr_wr_cb[mtvt] = &this_class::write_xtvt; -// csr_rd_cb[mxnti] = &this_class::read_csr_reg; -// csr_wr_cb[mxnti] = &this_class::write_csr_reg; + // csr_rd_cb[mxnti] = &this_class::read_csr_reg; + // csr_wr_cb[mxnti] = &this_class::write_csr_reg; csr_rd_cb[mintstatus] = &this_class::read_intstatus; csr_wr_cb[mintstatus] = &this_class::write_null; -// csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; -// csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; -// csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; -// csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; + // csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; + // csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; + // csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; + // csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_wr_cb[mintthresh] = &this_class::write_intthresh; - clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); - clic_cfg_reg=0x20; - clic_mact_lvl = clic_mprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; - csr[mintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; - insert_mem_range(cfg.clic_base, 0x5000UL, - [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, - [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); + clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0}); + clic_cfg_reg = 0x20; + clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1; + csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1; + insert_mem_range( + cfg.clic_base, 0x5000UL, + [this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); }, + [this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); }); } if(FEAT & FEAT_TCM) { tcm.resize(cfg.tcm_size); - std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) { - auto offset=addr.val-this->cfg.tcm_base; + std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t* const data) { + auto offset = addr.val - this->cfg.tcm_base; std::copy(tcm.data() + offset, tcm.data() + offset + length, data); return iss::Ok; }; - std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const * const data) { - auto offset=addr.val-this->cfg.tcm_base; + std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const* const data) { + auto offset = addr.val - this->cfg.tcm_base; std::copy(data, data + length, tcm.data() + offset); return iss::Ok; }; insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb); } - if(FEAT & FEAT_DEBUG){ + if(FEAT & FEAT_DEBUG) { csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg; @@ -552,158 +556,158 @@ riscv_hart_m_p::riscv_hart_m_p(feature_config cfg) csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; } - hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { - return this->read_mem(a, l, d); - }; - hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { - return this->write_mem(a, l, d); - }; + hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); }; + hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); }; } template std::pair riscv_hart_m_p::load_file(std::string name, int type) { - FILE *fp = fopen(name.c_str(), "r"); - if (fp) { + FILE* fp = fopen(name.c_str(), "r"); + if(fp) { std::array buf; auto n = fread(buf.data(), 1, 4, fp); fclose(fp); - if (n != 4) throw std::runtime_error("input file has insufficient size"); + if(n != 4) + throw std::runtime_error("input file has insufficient size"); buf[4] = 0; - if (strcmp(buf.data() + 1, "ELF") == 0) { + if(strcmp(buf.data() + 1, "ELF") == 0) { // Create elfio reader ELFIO::elfio reader; // Load ELF data - if (!reader.load(name)) throw std::runtime_error("could not process elf file"); + if(!reader.load(name)) + throw std::runtime_error("could not process elf file"); // check elf properties - if (reader.get_class() != ELFCLASS32) - if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file"); - if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file"); - if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); + if(reader.get_class() != ELFCLASS32) + if(sizeof(reg_t) == 4) + throw std::runtime_error("wrong elf class in file"); + if(reader.get_type() != ET_EXEC) + throw std::runtime_error("wrong elf type in file"); + if(reader.get_machine() != EM_RISCV) + throw std::runtime_error("wrong elf machine in file"); auto entry = reader.get_entry(); - for (const auto pseg : reader.segments) { + 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) { - auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, - traits::MEM, pseg->get_physical_address(), - fsize, reinterpret_cast(seg_data)); - if (res != iss::Ok) - LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex - << pseg->get_physical_address(); + if(fsize > 0) { + auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, + pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); + if(res != iss::Ok) + LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); } } for(const auto sec : reader.sections) { if(sec->get_name() == ".symtab") { - if ( SHT_SYMTAB == sec->get_type() || - SHT_DYNSYM == sec->get_type() ) { - ELFIO::symbol_section_accessor symbols( reader, sec ); + if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) { + ELFIO::symbol_section_accessor symbols(reader, sec); auto sym_no = symbols.get_symbols_num(); - std::string name; - ELFIO::Elf64_Addr value = 0; - ELFIO::Elf_Xword size = 0; - unsigned char bind = 0; - unsigned char type = 0; - ELFIO::Elf_Half section = 0; - unsigned char other = 0; - for ( auto i = 0U; i < sym_no; ++i ) { - symbols.get_symbol( i, name, value, size, bind, type, section, other ); - if(name=="tohost") { + std::string name; + ELFIO::Elf64_Addr value = 0; + ELFIO::Elf_Xword size = 0; + unsigned char bind = 0; + unsigned char type = 0; + ELFIO::Elf_Half section = 0; + unsigned char other = 0; + for(auto i = 0U; i < sym_no; ++i) { + symbols.get_symbol(i, name, value, size, bind, type, section, other); + if(name == "tohost") { tohost = value; - } else if(name=="fromhost") { + } else if(name == "fromhost") { fromhost = value; } } } - } else if (sec->get_name() == ".tohost") { + } else if(sec->get_name() == ".tohost") { tohost = sec->get_address(); fromhost = tohost + 0x40; } - } return std::make_pair(entry, true); } - throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file",name)); + throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name)); } throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); } -template +template inline void riscv_hart_m_p::insert_mem_range(uint64_t base, uint64_t size, std::function rd_f, - std::function wr_fn) { + std::function wr_fn) { std::tuple entry{base, size}; - auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry, - [](std::tuple const& a, std::tuple const& b){ - return std::get<0>(a)(b); - }); + auto it = std::upper_bound( + memfn_range.begin(), memfn_range.end(), entry, + [](std::tuple const& a, std::tuple const& b) { return std::get<0>(a) < std::get<0>(b); }); auto idx = std::distance(memfn_range.begin(), it); memfn_range.insert(it, entry); - memfn_read.insert(std::begin(memfn_read)+idx, rd_f); - memfn_write.insert(std::begin(memfn_write)+idx, wr_fn); + memfn_read.insert(std::begin(memfn_read) + idx, rd_f); + memfn_write.insert(std::begin(memfn_write) + idx, wr_fn); } template -iss::status riscv_hart_m_p::read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) { +iss::status riscv_hart_m_p::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, uint8_t* const data) { #ifndef NDEBUG - if (access && iss::access_type::DEBUG) { + if(access && iss::access_type::DEBUG) { LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; - } else if(access && iss::access_type::FETCH){ + } else if(access && iss::access_type::FETCH) { LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; } else { LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; - } + } #endif try { - switch (space) { + switch(space) { case traits::MEM: { - auto alignment = is_fetch(access)? (has_compressed()? 2 : 4) : length; - if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { + auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length; + if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) { fault_data = addr; - if (is_debug(access)) throw trap_access(0, addr); + if(is_debug(access)) + throw trap_access(0, addr); this->reg.trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { - if(!is_debug(access) && (addr&(alignment-1))){ - this->reg.trap_state = (1UL << 31) | 4<<16; - fault_data=addr; + if(!is_debug(access) && (addr & (alignment - 1))) { + this->reg.trap_state = (1UL << 31) | 4 << 16; + fault_data = addr; return iss::Err; } phys_addr_t phys_addr{access, space, addr}; auto res = iss::Err; - if(access != access_type::FETCH && memfn_range.size()){ - auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ - return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; - }); - if(it!=std::end(memfn_range)) { + if(access != access_type::FETCH && memfn_range.size()) { + auto it = + std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a) { + return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; + }); + if(it != std::end(memfn_range)) { auto idx = std::distance(std::begin(memfn_range), it); res = memfn_read[idx](phys_addr, length, data); } else - res = hart_mem_rd_delegate( phys_addr, length, data); + res = hart_mem_rd_delegate(phys_addr, length, data); } else { - res = hart_mem_rd_delegate( phys_addr, length, data); + res = hart_mem_rd_delegate(phys_addr, length, data); } - if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)){ + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault - fault_data=addr; + fault_data = addr; } return res; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1UL << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } } break; case traits::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return read_csr(addr, *reinterpret_cast(data)); + if(length != sizeof(reg_t)) + return iss::Err; + return read_csr(addr, *reinterpret_cast(data)); } break; case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; + if((addr + length) > mem.size()) + return iss::Err; return iss::Ok; } break; case traits::RES: { auto it = atomic_reservation.find(addr); - if (it != atomic_reservation.end() && it->second != 0) { + if(it != atomic_reservation.end() && it->second != 0) { memset(data, 0xff, length); atomic_reservation.erase(addr); } else @@ -713,85 +717,88 @@ iss::status riscv_hart_m_p::read(const address_type type, const acce return iss::Err; // assert("Not supported"); } return iss::Ok; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1UL << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } } template -iss::status riscv_hart_m_p::write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) { +iss::status riscv_hart_m_p::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, const uint8_t* const data) { #ifndef NDEBUG - const char *prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; - switch (length) { + const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; + switch(length) { case 8: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 4: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 2: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 1: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; default: LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; } #endif try { - switch (space) { + switch(space) { case traits::MEM: { - if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { + if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); + if(access && iss::access_type::DEBUG) + throw trap_access(0, addr); this->reg.trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { - if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ - this->reg.trap_state = (1UL << 31) | 6<<16; - fault_data=addr; + if(length > 1 && (addr & (length - 1)) && (access & access_type::DEBUG) != access_type::DEBUG) { + this->reg.trap_state = (1UL << 31) | 6 << 16; + fault_data = addr; return iss::Err; } phys_addr_t phys_addr{access, space, addr}; auto res = iss::Err; - if(access != access_type::FETCH && memfn_range.size()){ - auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ - return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; - }); - if(it!=std::end(memfn_range)) { + if(access != access_type::FETCH && memfn_range.size()) { + auto it = + std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a) { + return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; + }); + if(it != std::end(memfn_range)) { auto idx = std::distance(std::begin(memfn_range), it); - res = memfn_write[idx]( phys_addr, length, data); + res = memfn_write[idx](phys_addr, length, data); } else - res = write_mem( phys_addr, length, data); + res = write_mem(phys_addr, length, data); } else { - res = write_mem( phys_addr, length, data); + res = write_mem(phys_addr, length, data); } - if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 7 (Store/AMO access fault) - fault_data=addr; + fault_data = addr; } return res; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1UL << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } - if ((addr + length) > mem.size()) return iss::Err; - switch (addr) { + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { 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) { + if(((char)data[0]) == '\n' || data[0] == 0) { // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send // '"<::write(const address_type type, const acc } return iss::Ok; case 0x10008000: { // HFROSC base, hfrosccfg reg - auto &p = mem(addr / mem.page_size); + auto& p = mem(addr / mem.page_size); auto offs = addr & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); - auto &x = *(p.data() + offs + 3); - if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 + auto& x = *(p.data() + offs + 3); + if(x & 0x40) + x |= 0x80; // hfroscrdy = 1 if hfroscen==1 return iss::Ok; } case 0x10008008: { // HFROSC base, pllcfg reg - auto &p = mem(addr / mem.page_size); + auto& p = mem(addr / mem.page_size); auto offs = addr & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); - auto &x = *(p.data() + offs + 3); + auto& x = *(p.data() + offs + 3); x |= 0x80; // set pll lock upon writing return iss::Ok; } break; @@ -818,12 +826,14 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc } } break; case traits::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return write_csr(addr, *reinterpret_cast(data)); + if(length != sizeof(reg_t)) + return iss::Err; + return write_csr(addr, *reinterpret_cast(data)); } break; case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; - switch (addr) { + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { case 2: case 3: { ptw.clear(); @@ -839,43 +849,45 @@ iss::status riscv_hart_m_p::write(const address_type type, const acc return iss::Err; } return iss::Ok; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1UL << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } } -template iss::status riscv_hart_m_p::read_csr(unsigned addr, reg_t &val) { - if (addr >= csr.size()) return iss::Err; +template iss::status riscv_hart_m_p::read_csr(unsigned addr, reg_t& val) { + if(addr >= csr.size()) + return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges + if(this->reg.PRIV < req_priv_lvl) // not having required privileges throw illegal_instruction_fault(this->fault_data); auto it = csr_rd_cb.find(addr); - if (it == csr_rd_cb.end() || !it->second) // non existent register + if(it == csr_rd_cb.end() || !it->second) // non existent register throw illegal_instruction_fault(this->fault_data); return (this->*(it->second))(addr, val); } template iss::status riscv_hart_m_p::write_csr(unsigned addr, reg_t val) { - if (addr >= csr.size()) return iss::Err; + if(addr >= csr.size()) + return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges + if(this->reg.PRIV < req_priv_lvl) // not having required privileges throw illegal_instruction_fault(this->fault_data); - if((addr&0xc00)==0xc00) // writing to read-only region + if((addr & 0xc00) == 0xc00) // writing to read-only region throw illegal_instruction_fault(this->fault_data); auto it = csr_wr_cb.find(addr); - if (it == csr_wr_cb.end() || !it->second) // non existent register + if(it == csr_wr_cb.end() || !it->second) // non existent register throw illegal_instruction_fault(this->fault_data); return (this->*(it->second))(addr, val); } -template iss::status riscv_hart_m_p::read_csr_reg(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_csr_reg(unsigned addr, reg_t& val) { val = csr[addr]; return iss::Ok; } -template iss::status riscv_hart_m_p::read_null(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_null(unsigned addr, reg_t& val) { val = 0; return iss::Ok; } @@ -885,70 +897,71 @@ template iss::status riscv_hart_m_p return iss::Ok; } -template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t& val) { auto cycle_val = this->reg.icount + cycle_offset; - if (addr == mcycle) { + if(addr == mcycle) { val = static_cast(cycle_val); - } else if (addr == mcycleh) { + } else if(addr == mcycleh) { val = static_cast(cycle_val >> 32); } return iss::Ok; } template iss::status riscv_hart_m_p::write_cycle(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { + if(sizeof(typename traits::reg_t) != 4) { mcycle_csr = static_cast(val); } else { - if (addr == mcycle) { + if(addr == mcycle) { mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val; - } else { - mcycle_csr = (static_cast(val)<<32) + (mcycle_csr & 0xffffffff); + } else { + mcycle_csr = (static_cast(val) << 32) + (mcycle_csr & 0xffffffff); } } - cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around + cycle_offset = mcycle_csr - this->reg.icount; // TODO: relying on wrap-around return iss::Ok; } -template iss::status riscv_hart_m_p::read_instret(unsigned addr, reg_t &val) { - if ((addr&0xff) == (minstret&0xff)) { +template iss::status riscv_hart_m_p::read_instret(unsigned addr, reg_t& val) { + if((addr & 0xff) == (minstret & 0xff)) { val = static_cast(this->reg.instret); - } else if ((addr&0xff) == (minstreth&0xff)) { + } else if((addr & 0xff) == (minstreth & 0xff)) { val = static_cast(this->reg.instret >> 32); } return iss::Ok; } template iss::status riscv_hart_m_p::write_instret(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { + if(sizeof(typename traits::reg_t) != 4) { this->reg.instret = static_cast(val); } else { - if ((addr&0xff) == (minstret&0xff)) { + if((addr & 0xff) == (minstret & 0xff)) { this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; - } else { - this->reg.instret = (static_cast(val)<<32) + (this->reg.instret & 0xffffffff); + } else { + this->reg.instret = (static_cast(val) << 32) + (this->reg.instret & 0xffffffff); } } this->reg.instret--; return iss::Ok; } -template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t& val) { uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; - if (addr == time) { + if(addr == time) { val = static_cast(time_val); - } else if (addr == timeh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; + } else if(addr == timeh) { + if(sizeof(typename traits::reg_t) != 4) + return iss::Err; val = static_cast(time_val >> 32); } return iss::Ok; } -template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t &val) { - val = FEAT & features_e::FEAT_CLIC? csr[addr] : csr[addr] & ~2; +template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t& val) { + val = FEAT & features_e::FEAT_CLIC ? csr[addr] : csr[addr] & ~2; return iss::Ok; } -template iss::status riscv_hart_m_p::read_status(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_status(unsigned addr, reg_t& val) { val = state.mstatus & hart_state_type::get_mask(); return iss::Ok; } @@ -959,37 +972,37 @@ template iss::status riscv_hart_m_p return iss::Ok; } -template iss::status riscv_hart_m_p::read_cause(unsigned addr, reg_t &val) { - if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { - val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); - val |= clic_mprev_lvl<<16; - val |= state.mstatus.MPIE<<27; - val |= state.mstatus.MPP<<28; +template iss::status riscv_hart_m_p::read_cause(unsigned addr, reg_t& val) { + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) { + val = csr[addr] & ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16)); + val |= clic_mprev_lvl << 16; + val |= state.mstatus.MPIE << 27; + val |= state.mstatus.MPP << 28; } else - val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); + val = csr[addr] & ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1)); return iss::Ok; } template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { - if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { - auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) { + auto mask = ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16)); csr[addr] = (val & mask) | (csr[addr] & ~mask); - clic_mprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; - state.mstatus.MPIE=(val>>27)&0x1; - state.mstatus.MPP=(val>>28)&0x3; + clic_mprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1; + state.mstatus.MPIE = (val >> 27) & 0x1; + state.mstatus.MPP = (val >> 28) & 0x3; } else { - auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); + auto mask = ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1)); csr[addr] = (val & mask) | (csr[addr] & ~mask); } return iss::Ok; } -template iss::status riscv_hart_m_p::read_hartid(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_hartid(unsigned addr, reg_t& val) { val = mhartid_reg; return iss::Ok; } -template iss::status riscv_hart_m_p::read_ie(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_ie(unsigned addr, reg_t& val) { auto mask = get_irq_mask(); val = csr[mie] & mask; return iss::Ok; @@ -1002,7 +1015,7 @@ template iss::status riscv_hart_m_p return iss::Ok; } -template iss::status riscv_hart_m_p::read_ip(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_ip(unsigned addr, reg_t& val) { auto mask = get_irq_mask(); val = csr[mip] & mask; return iss::Ok; @@ -1024,7 +1037,7 @@ template iss::status riscv_hart_m_p return iss::Ok; } -template iss::status riscv_hart_m_p::read_dcsr_reg(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_dcsr_reg(unsigned addr, reg_t& val) { if(!debug_mode_active()) throw illegal_instruction_fault(this->fault_data); val = csr[addr]; @@ -1038,7 +1051,7 @@ template iss::status riscv_hart_m_p return iss::Ok; } -template iss::status riscv_hart_m_p::read_dpc_reg(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_dpc_reg(unsigned addr, reg_t& val) { if(!debug_mode_active()) throw illegal_instruction_fault(this->fault_data); val = this->reg.DPC; @@ -1052,30 +1065,27 @@ template iss::status riscv_hart_m_p return iss::Ok; } -template -iss::status riscv_hart_m_p::read_intstatus(unsigned addr, reg_t& val) { - val = (clic_mact_lvl&0xff) <<24; +template iss::status riscv_hart_m_p::read_intstatus(unsigned addr, reg_t& val) { + val = (clic_mact_lvl & 0xff) << 24; return iss::Ok; } -template -iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val) { - csr[addr]= (val &0xff) | (1<<(cfg.clic_int_ctl_bits)) - 1; +template iss::status riscv_hart_m_p::write_intthresh(unsigned addr, reg_t val) { + csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1; return iss::Ok; } -template -iss::status riscv_hart_m_p::write_xtvt(unsigned addr, reg_t val) { - csr[addr]= val & ~0x3fULL; +template iss::status riscv_hart_m_p::write_xtvt(unsigned addr, reg_t val) { + csr[addr] = val & ~0x3fULL; return iss::Ok; } template -iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - switch (paddr.val) { +iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) { + switch(paddr.val) { default: { - for(auto offs=0U; offs::read_mem(phys_addr_t paddr, unsigned len } template -iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - switch (paddr.val) { +iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) { + switch(paddr.val) { case 0xFFFF0000: // UART0 base, TXFIFO reg - if (((char)data[0]) == '\n' || data[0] == 0) { - LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<> 12) & 0x3) << " send '" << uart_buf.str() << "'"; uart_buf.str(""); } else if(((char)data[0]) != '\r') uart_buf << (char)data[0]; break; default: { - mem_type::page_type &p = mem(paddr.val / mem.page_size); + mem_type::page_type& p = mem(paddr.val / mem.page_size); std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); // tohost handling in case of riscv-test - if (paddr.access && iss::access_type::FUNC) { - auto tohost_upper = (traits::XLEN == 32 && paddr.val == (tohost + 4)) || - (traits::XLEN == 64 && paddr.val == tohost); - auto tohost_lower = - (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.val == tohost); - if (tohost_lower || tohost_upper) { - uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); - if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { - switch (hostvar >> 48) { + if(paddr.access && iss::access_type::FUNC) { + auto tohost_upper = + (traits::XLEN == 32 && paddr.val == (tohost + 4)) || (traits::XLEN == 64 && paddr.val == tohost); + auto tohost_lower = (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.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) { + if(hostvar != 0x1) { LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } else { LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } - this->reg.trap_state=std::numeric_limits::max(); - this->interrupt_sim=hostvar; + this->reg.trap_state = std::numeric_limits::max(); + this->interrupt_sim = hostvar; #ifndef WITH_TCC throw(iss::simulation_stopped(hostvar)); #endif break; case 0x0101: { char c = static_cast(hostvar & 0xff); - if (c == '\n' || c == 0) { + if(c == '\n' || c == 0) { LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; uart_buf.str(""); } else @@ -1131,12 +1140,11 @@ iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned le default: break; } - } else if (tohost_lower) + } else if(tohost_lower) to_host_wr_cnt++; - } else if ((traits::XLEN == 32 && paddr.val == fromhost + 4) || - (traits::XLEN == 64 && paddr.val == fromhost)) { - uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); - *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; + } else if((traits::XLEN == 32 && paddr.val == fromhost + 4) || (traits::XLEN == 64 && paddr.val == fromhost)) { + uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); + *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; } } } @@ -1144,32 +1152,36 @@ iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned le return iss::Ok; } -template -iss::status riscv_hart_m_p::read_clic(uint64_t addr, unsigned length, uint8_t *const data) { - if(addr==cfg.clic_base) { // cliccfg - *data=clic_cfg_reg; - for(auto i=1; i=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig - auto offset = ((addr&0x7fff)-0x40)/4; +template +iss::status riscv_hart_m_p::read_clic(uint64_t addr, unsigned length, uint8_t* const data) { + if(addr == cfg.clic_base) { // cliccfg + *data = clic_cfg_reg; + for(auto i = 1; i < length; ++i) + *(data + i) = 0; + } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig + auto offset = ((addr & 0x7fff) - 0x40) / 4; read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl - auto offset = ((addr&0x7fff)-0x1000)/4; + } else if(addr >= (cfg.clic_base + 0x1000) && + (addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl + auto offset = ((addr & 0x7fff) - 0x1000) / 4; read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); } else { - for(auto i = 0U; i -iss::status riscv_hart_m_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { - if(addr==cfg.clic_base) { // cliccfg - clic_cfg_reg = (clic_cfg_reg&~0x1e) | (*data&0x1e); - } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig - auto offset = ((addr&0x7fff)-0x40)/4; +template +iss::status riscv_hart_m_p::write_clic(uint64_t addr, unsigned length, const uint8_t* const data) { + if(addr == cfg.clic_base) { // cliccfg + clic_cfg_reg = (clic_cfg_reg & ~0x1e) | (*data & 0x1e); + } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig + auto offset = ((addr & 0x7fff) - 0x40) / 4; write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl - auto offset = ((addr&0x7fff)-0x1000)/4; + } else if(addr >= (cfg.clic_base + 0x1000) && + (addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl + auto offset = ((addr & 0x7fff) - 0x1000) / 4; write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1 } @@ -1182,8 +1194,8 @@ template inline void riscv_hart_m_p } template void riscv_hart_m_p::check_interrupt() { - //TODO: Implement CLIC functionality - //auto ideleg = csr[mideleg]; + // TODO: Implement CLIC functionality + // 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 @@ -1194,11 +1206,11 @@ template void riscv_hart_m_p::check auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie; auto enabled_interrupts = m_enabled ? ena_irq : 0; - if (enabled_interrupts != 0) { + if(enabled_interrupts != 0) { int res = 0; - while ((enabled_interrupts & 1) == 0) { - enabled_interrupts >>= 1; - res++; + while((enabled_interrupts & 1) == 0) { + enabled_interrupts >>= 1; + res++; } this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id } @@ -1211,8 +1223,9 @@ template uint64_t riscv_hart_m_p::e auto cause = bit_sub<16, 15>(flags); // calculate effective privilege level unsigned new_priv = PRIV_M; - if (trap_id == 0) { // exception - if (cause == 11) cause = 0x8 + PRIV_M; // adjust environment call cause + if(trap_id == 0) { // exception + if(cause == 11) + cause = 0x8 + PRIV_M; // adjust environment call cause // store ret addr in xepc register csr[mepc] = static_cast(addr) & get_pc_mask(); // store actual address instruction of exception /* @@ -1222,17 +1235,17 @@ template uint64_t riscv_hart_m_p::e * access, or page-fault exception occurs, mtval is written with the * faulting effective address. */ - switch(cause){ + switch(cause) { case 0: csr[mtval] = static_cast(addr); break; case 2: - csr[mtval] = (!has_compressed() || (instr & 0x3)==3)?instr:instr&0xffff; + csr[mtval] = (!has_compressed() || (instr & 0x3) == 3) ? instr : instr & 0xffff; break; case 3: if((FEAT & FEAT_DEBUG) && (csr[dcsr] & 0x8000)) { this->reg.DPC = addr; - csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) + csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1 << 6) | PRIV_M; // FIXME: cause should not be 4 (stepi) new_priv = this->reg.PRIV | PRIV_D; } else { csr[mtval] = addr; @@ -1250,7 +1263,7 @@ template uint64_t riscv_hart_m_p::e csr[mepc] = this->reg.NEXT_PC & get_pc_mask(); // store next address if interrupt this->reg.pending_trap = 0; } - csr[mcause] = (trap_id << (traits::XLEN-1)) + cause; + csr[mcause] = (trap_id << (traits::XLEN - 1)) + 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 @@ -1265,7 +1278,7 @@ template uint64_t riscv_hart_m_p::e // get trap vector auto xtvec = csr[mtvec]; // calculate adds// set NEXT_PC to trap addressess to jump to based on MODE - if((FEAT & features_e::FEAT_CLIC) && trap_id!=0 && (xtvec & 0x3UL)==3UL) { + if((FEAT & features_e::FEAT_CLIC) && trap_id != 0 && (xtvec & 0x3UL) == 3UL) { reg_t data; auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast(&data)); if(ret == iss::Err) @@ -1274,7 +1287,8 @@ template uint64_t riscv_hart_m_p::e } else { // bits in mtvec this->reg.NEXT_PC = xtvec & ~0x3UL; - if ((xtvec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; + if((xtvec & 0x1) == 1 && trap_id != 0) + this->reg.NEXT_PC += 4 * cause; } // reset trap state this->reg.PRIV = new_priv; @@ -1285,10 +1299,10 @@ template uint64_t riscv_hart_m_p::e #else sprintf(buffer.data(), "0x%016lx", addr); #endif - if((flags&0xffffffff) != 0xffffffff) - CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" - << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" - << " at address " << buffer.data() << " occurred"; + if((flags & 0xffffffff) != 0xffffffff) + CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" + << cause << ")" + << " at address " << buffer.data() << " occurred"; return this->reg.NEXT_PC; } diff --git a/src/iss/arch/riscv_hart_msu_vp.h b/src/iss/arch/riscv_hart_msu_vp.h index 56c7209..8355d3c 100644 --- a/src/iss/arch/riscv_hart_msu_vp.h +++ b/src/iss/arch/riscv_hart_msu_vp.h @@ -35,22 +35,22 @@ #ifndef _RISCV_HART_MSU_VP_H #define _RISCV_HART_MSU_VP_H -#include "riscv_hart_common.h" #include "iss/arch/traits.h" #include "iss/instrumentation_if.h" #include "iss/log_categories.h" #include "iss/vm_if.h" +#include "riscv_hart_common.h" #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY #endif #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -69,27 +69,28 @@ namespace arch { template class riscv_hart_msu_vp : public BASE { protected: const std::array lvl = {{'U', 'S', 'H', 'M'}}; - const std::array trap_str = {{"" - "Instruction address misaligned", // 0 - "Instruction access fault", // 1 - "Illegal instruction", // 2 - "Breakpoint", // 3 - "Load address misaligned", // 4 - "Load access fault", // 5 - "Store/AMO address misaligned", // 6 - "Store/AMO access fault", // 7 - "Environment call from U-mode", // 8 - "Environment call from S-mode", // 9 - "Reserved", // a - "Environment call from M-mode", // b - "Instruction page fault", // c - "Load page fault", // d - "Reserved", // e - "Store/AMO page fault"}}; - const std::array irq_str = { - {"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt", - "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", - "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; + const std::array trap_str = {{"" + "Instruction address misaligned", // 0 + "Instruction access fault", // 1 + "Illegal instruction", // 2 + "Breakpoint", // 3 + "Load address misaligned", // 4 + "Load access fault", // 5 + "Store/AMO address misaligned", // 6 + "Store/AMO access fault", // 7 + "Environment call from U-mode", // 8 + "Environment call from S-mode", // 9 + "Reserved", // a + "Environment call from M-mode", // b + "Instruction page fault", // c + "Load page fault", // d + "Reserved", // e + "Store/AMO page fault"}}; + const std::array 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"}}; + public: using core = BASE; using this_class = riscv_hart_msu_vp; @@ -98,7 +99,7 @@ public: using reg_t = typename core::reg_t; using addr_t = typename core::addr_t; - using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); + using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t&); using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); // primary template @@ -107,7 +108,8 @@ public: template class hart_state::value>::type> { public: BEGIN_BF_DECL(mstatus_t, T); - // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) BF_FIELD(SD, 31, 1); // Trap SRET BF_FIELD(TSR, 22, 1); @@ -121,7 +123,8 @@ public: BF_FIELD(SUM, 18, 1); // Modify PRiVilege BF_FIELD(MPRV, 17, 1); - // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty BF_FIELD(XS, 15, 2); // floating-point unit status Off/Initial/Clean/Dirty BF_FIELD(FS, 13, 2); @@ -161,21 +164,28 @@ public: #if __cplusplus < 201402L return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL; #else - switch (priv_lvl) { - case PRIV_U: return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 - case PRIV_S: return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011 - default: return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011 + switch(priv_lvl) { + case PRIV_U: + return 0x80000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 + case PRIV_S: + return 0x800de133UL; // 0b1000 0000 0000 1101 1110 0001 0011 0011 + default: + return 0x807ff9ddUL; // 0b1000 0000 0111 1111 1111 1001 1011 1011 } #endif } static inline vm_info decode_vm_info(uint32_t state, T sptbr) { - if (state == PRIV_M) return {0, 0, 0, 0}; - if (state <= PRIV_S) - switch (bit_sub<31, 1>(sptbr)) { - case 0: return {0, 0, 0, 0}; // off - case 1: return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32 - default: abort(); + if(state == PRIV_M) + return {0, 0, 0, 0}; + if(state <= PRIV_S) + switch(bit_sub<31, 1>(sptbr)) { + case 0: + return {0, 0, 0, 0}; // off + case 1: + return {2, 10, 4, bit_sub<0, 22>(sptbr) << PGSHIFT}; // SV32 + default: + abort(); } abort(); return {0, 0, 0, 0}; // dummy @@ -185,7 +195,8 @@ public: template class hart_state::value>::type> { public: BEGIN_BF_DECL(mstatus_t, T); - // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) BF_FIELD(SD, 63, 1); // value of XLEN for S-mode BF_FIELD(SXL, 34, 2); @@ -203,7 +214,8 @@ public: BF_FIELD(SUM, 18, 1); // Modify PRiVilege BF_FIELD(MPRV, 17, 1); - // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty BF_FIELD(XS, 15, 2); // floating-point unit status Off/Initial/Clean/Dirty BF_FIELD(FS, 13, 2); @@ -233,10 +245,10 @@ public: T old_val = mstatus; auto mask = get_mask(priv_lvl); auto new_val = (old_val & ~mask) | (val & mask); - if ((new_val & mstatus.SXL.Mask) == 0) { + if((new_val & mstatus.SXL.Mask) == 0) { new_val |= old_val & mstatus.SXL.Mask; } - if ((new_val & mstatus.UXL.Mask) == 0) { + if((new_val & mstatus.UXL.Mask) == 0) { new_val |= old_val & mstatus.UXL.Mask; } mstatus = new_val; @@ -248,24 +260,37 @@ public: static constexpr T get_mask(unsigned priv_lvl) { uint64_t ret; - switch (priv_lvl) { - case PRIV_U: ret = 0x8000000f00000011ULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 - case PRIV_S: ret = 0x8000000f000de133ULL;break; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011 - default: ret = 0x8000000f007ff9ddULL;break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + switch(priv_lvl) { + case PRIV_U: + ret = 0x8000000f00000011ULL; + break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 + case PRIV_S: + ret = 0x8000000f000de133ULL; + break; // 0b1...0 0011 0000 0000 0000 1101 1110 0001 0011 0011 + default: + ret = 0x8000000f007ff9ddULL; + break; // 0b1...0 1111 0000 0000 0111 1111 1111 1001 1011 1011 } return ret; } static inline vm_info decode_vm_info(uint32_t state, T sptbr) { - if (state == PRIV_M) return {0, 0, 0, 0}; - if (state <= PRIV_S) - switch (bit_sub<60, 4>(sptbr)) { - case 0: return {0, 0, 0, 0}; // off - case 8: return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV39 - case 9: return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV48 - case 10: return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV57 - case 11: return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT};// SV64 - default: abort(); + if(state == PRIV_M) + return {0, 0, 0, 0}; + if(state <= PRIV_S) + switch(bit_sub<60, 4>(sptbr)) { + case 0: + return {0, 0, 0, 0}; // off + case 8: + return {3, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV39 + case 9: + return {4, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV48 + case 10: + return {5, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV57 + case 11: + return {6, 9, 8, bit_sub<0, 44>(sptbr) << PGSHIFT}; // SV64 + default: + abort(); } abort(); return {0, 0, 0, 0}; // dummy @@ -293,12 +318,12 @@ public: std::pair load_file(std::string name, int type = -1) override; - phys_addr_t virt2phys(const iss::addr_t &addr) override; + phys_addr_t virt2phys(const iss::addr_t& addr) override; - iss::status read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) override; - iss::status write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) override; + iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + uint8_t* const data) override; + iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + const uint8_t* const data) override; uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data, fault_data); } uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; @@ -306,23 +331,20 @@ public: void wait_until(uint64_t flags) override; void disass_output(uint64_t pc, const std::string instr) override { - CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset); + CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, + this->reg.icount + cycle_offset); }; - iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } + iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; } - void set_csr(unsigned addr, reg_t val){ - csr[addr & csr.page_addr_mask] = val; - } + void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; } + + void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); } - void set_irq_num(unsigned i) { - mcause_max_irq=1< &arch) + riscv_instrumentation_if(riscv_hart_msu_vp& arch) : arch(arch) {} /** * get the name of this architecture @@ -347,19 +369,19 @@ protected: bool is_branch_taken() override { return arch.reg.last_branch; } - unsigned get_reg_num() override {return traits::NUM_REGS; } + unsigned get_reg_num() override { return traits::NUM_REGS; } - riscv_hart_msu_vp &arch; + riscv_hart_msu_vp& arch; }; friend struct riscv_instrumentation_if; addr_t get_pc() { return this->reg.PC; } addr_t get_next_pc() { return this->reg.NEXT_PC; } - virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data); - virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data); + virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t* const data); + virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data); - virtual iss::status read_csr(unsigned addr, reg_t &val); + virtual iss::status read_csr(unsigned addr, reg_t& val); virtual iss::status write_csr(unsigned addr, reg_t val); hart_state_type state; @@ -388,40 +410,36 @@ protected: std::vector tcm; - iss::status read_csr_reg(unsigned addr, reg_t &val); + iss::status read_csr_reg(unsigned addr, reg_t& val); iss::status write_csr_reg(unsigned addr, reg_t val); - iss::status read_null(unsigned addr, reg_t &val); - iss::status write_null(unsigned addr, reg_t val){return iss::status::Ok;} - iss::status read_cycle(unsigned addr, reg_t &val); + iss::status read_null(unsigned addr, reg_t& val); + iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; } + iss::status read_cycle(unsigned addr, reg_t& val); iss::status write_cycle(unsigned addr, reg_t val); - iss::status read_instret(unsigned addr, reg_t &val); + iss::status read_instret(unsigned addr, reg_t& val); iss::status write_instret(unsigned addr, reg_t val); - iss::status read_tvec(unsigned addr, reg_t &val); - iss::status read_time(unsigned addr, reg_t &val); - iss::status read_status(unsigned addr, reg_t &val); + iss::status read_tvec(unsigned addr, reg_t& val); + iss::status read_time(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 write_cause(unsigned addr, reg_t val); - iss::status read_ie(unsigned addr, reg_t &val); + iss::status read_ie(unsigned addr, reg_t& val); iss::status write_ie(unsigned addr, reg_t val); - iss::status read_ip(unsigned addr, reg_t &val); + iss::status read_ip(unsigned addr, reg_t& val); iss::status write_ideleg(unsigned addr, reg_t val); iss::status write_edeleg(unsigned addr, reg_t val); - iss::status read_hartid(unsigned addr, reg_t &val); + iss::status read_hartid(unsigned addr, reg_t& val); iss::status write_epc(unsigned addr, reg_t val); - iss::status read_satp(unsigned addr, reg_t &val); + iss::status read_satp(unsigned addr, reg_t& val); iss::status write_satp(unsigned addr, reg_t val); - iss::status read_fcsr(unsigned addr, reg_t &val); + iss::status read_fcsr(unsigned addr, reg_t& val); iss::status write_fcsr(unsigned addr, reg_t val); - virtual iss::status read_custom_csr_reg(unsigned addr, reg_t &val) {return iss::status::Err;}; - virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) {return iss::status::Err;}; + virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; }; + virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; }; - void register_custom_csr_rd(unsigned addr){ - csr_rd_cb[addr] = &this_class::read_custom_csr_reg; - } - void register_custom_csr_wr(unsigned addr){ - csr_wr_cb[addr] = &this_class::write_custom_csr_reg; - } + void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; } + void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; } reg_t mhartid_reg{0x0}; @@ -440,52 +458,56 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() csr[mimpid] = 1; uart_buf.str(""); - for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ + for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; csr_wr_cb[addr] = &this_class::write_csr_reg; } - for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ + for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) { csr_rd_cb[addr] = &this_class::read_null; csr_wr_cb[addr] = &this_class::write_csr_reg; } - for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ + for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; csr_wr_cb[addr] = &this_class::write_csr_reg; } - for (unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr){ + for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; } - for (unsigned addr = cycleh; addr <= hpmcounter31h; ++addr){ + for(unsigned addr = cycleh; addr <= hpmcounter31h; ++addr) { csr_rd_cb[addr] = &this_class::read_null; - //csr_wr_cb[addr] = &this_class::write_csr_reg; + // csr_wr_cb[addr] = &this_class::write_csr_reg; } // common regs - const std::array addrs{{ - misa, mvendorid, marchid, mimpid, - mepc, mtvec, mscratch, mcause, mtval, mscratch, - sepc, stvec, sscratch, scause, stval, sscratch, - uepc, utvec, uscratch, ucause, utval, uscratch - }}; - for(auto addr: addrs) { + const std::array addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause, + mtval, mscratch, sepc, stvec, sscratch, scause, stval, sscratch, + uepc, utvec, uscratch, ucause, utval, uscratch}}; + for(auto addr : addrs) { csr_rd_cb[addr] = &this_class::read_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg; } // special handling & overrides csr_rd_cb[time] = &this_class::read_time; - if(traits::XLEN==32) csr_rd_cb[timeh] = &this_class::read_time; + if(traits::XLEN == 32) + csr_rd_cb[timeh] = &this_class::read_time; csr_rd_cb[cycle] = &this_class::read_cycle; - if(traits::XLEN==32) csr_rd_cb[cycleh] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_rd_cb[cycleh] = &this_class::read_cycle; csr_rd_cb[instret] = &this_class::read_instret; - if(traits::XLEN==32) csr_rd_cb[instreth] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_rd_cb[instreth] = &this_class::read_instret; csr_rd_cb[mcycle] = &this_class::read_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle; - if(traits::XLEN==32) csr_rd_cb[mcycleh] = &this_class::read_cycle; - if(traits::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle; + if(traits::XLEN == 32) + csr_rd_cb[mcycleh] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_wr_cb[mcycleh] = &this_class::write_cycle; csr_rd_cb[minstret] = &this_class::read_instret; csr_wr_cb[minstret] = &this_class::write_instret; - if(traits::XLEN==32) csr_rd_cb[minstreth] = &this_class::read_instret; - if(traits::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret; + if(traits::XLEN == 32) + csr_rd_cb[minstreth] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[mstatus] = &this_class::read_status; csr_wr_cb[mstatus] = &this_class::write_status; csr_wr_cb[mcause] = &this_class::write_cause; @@ -531,133 +553,137 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() } template std::pair riscv_hart_msu_vp::load_file(std::string name, int type) { - FILE *fp = fopen(name.c_str(), "r"); - if (fp) { + FILE* fp = fopen(name.c_str(), "r"); + if(fp) { std::array buf; auto n = fread(buf.data(), 1, 4, fp); fclose(fp); - if (n != 4) throw std::runtime_error("input file has insufficient size"); + if(n != 4) + throw std::runtime_error("input file has insufficient size"); buf[4] = 0; - if (strcmp(buf.data() + 1, "ELF") == 0) { + if(strcmp(buf.data() + 1, "ELF") == 0) { // Create elfio reader ELFIO::elfio reader; // Load ELF data - if (!reader.load(name)) throw std::runtime_error("could not process elf file"); + if(!reader.load(name)) + throw std::runtime_error("could not process elf file"); // check elf properties - if (reader.get_class() != ELFCLASS32) - if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file"); - if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file"); - if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); + if(reader.get_class() != ELFCLASS32) + if(sizeof(reg_t) == 4) + throw std::runtime_error("wrong elf class in file"); + if(reader.get_type() != ET_EXEC) + throw std::runtime_error("wrong elf type in file"); + if(reader.get_machine() != EM_RISCV) + throw std::runtime_error("wrong elf machine in file"); auto entry = reader.get_entry(); - for (const auto pseg : reader.segments) { + 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) { - auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, - traits::MEM, pseg->get_physical_address(), - fsize, reinterpret_cast(seg_data)); - if (res != iss::Ok) - LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex - << pseg->get_physical_address(); + if(fsize > 0) { + auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, + pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); + if(res != iss::Ok) + LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); } } for(const auto sec : reader.sections) { if(sec->get_name() == ".symtab") { - if ( SHT_SYMTAB == sec->get_type() || - SHT_DYNSYM == sec->get_type() ) { - ELFIO::symbol_section_accessor symbols( reader, sec ); + if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) { + ELFIO::symbol_section_accessor symbols(reader, sec); auto sym_no = symbols.get_symbols_num(); - std::string name; - ELFIO::Elf64_Addr value = 0; - ELFIO::Elf_Xword size = 0; - unsigned char bind = 0; - unsigned char type = 0; - ELFIO::Elf_Half section = 0; - unsigned char other = 0; - for ( auto i = 0U; i < sym_no; ++i ) { - symbols.get_symbol( i, name, value, size, bind, type, section, other ); - if(name=="tohost") { + std::string name; + ELFIO::Elf64_Addr value = 0; + ELFIO::Elf_Xword size = 0; + unsigned char bind = 0; + unsigned char type = 0; + ELFIO::Elf_Half section = 0; + unsigned char other = 0; + for(auto i = 0U; i < sym_no; ++i) { + symbols.get_symbol(i, name, value, size, bind, type, section, other); + if(name == "tohost") { tohost = value; - } else if(name=="fromhost") { + } else if(name == "fromhost") { fromhost = value; } } } - } else if (sec->get_name() == ".tohost") { + } else if(sec->get_name() == ".tohost") { tohost = sec->get_address(); fromhost = tohost + 0x40; } - } return std::make_pair(entry, true); } - throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file",name)); + throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name)); } throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); } template -iss::status riscv_hart_msu_vp::read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) { +iss::status riscv_hart_msu_vp::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, uint8_t* const data) { #ifndef NDEBUG - if (access && iss::access_type::DEBUG) { + if(access && iss::access_type::DEBUG) { LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; - } else if(access && iss::access_type::FETCH){ + } else if(access && iss::access_type::FETCH) { LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; } else { LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; - } + } #endif try { - switch (space) { + switch(space) { case traits::MEM: { - auto alignment = is_fetch(access)? (traits::MISA_VAL&0x100? 2 : 4) : length; - if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { + auto alignment = is_fetch(access) ? (traits::MISA_VAL & 0x100 ? 2 : 4) : length; + if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) { fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); + if(access && iss::access_type::DEBUG) + throw trap_access(0, addr); this->reg.trap_state = (1 << 31); // issue trap 0 return iss::Err; } try { - if(!is_debug(access) && (addr&(alignment-1))){ - this->reg.trap_state = 1<<31 | 4<<16; - fault_data=addr; + if(!is_debug(access) && (addr & (alignment - 1))) { + this->reg.trap_state = 1 << 31 | 4 << 16; + fault_data = addr; return iss::Err; } - if (unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary + if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary vm_info vm = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp); - if (vm.levels != 0) { // VM is active + if(vm.levels != 0) { // VM is active auto split_addr = (addr + length) & ~PGMASK; auto len1 = split_addr - addr; auto res = read(type, access, space, addr, len1, data); - if (res == iss::Ok) + if(res == iss::Ok) res = read(type, access, space, split_addr, length - len1, data + len1); return res; } } - auto res = read_mem( BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); - if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)){ - this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault - fault_data=addr; + auto res = read_mem(BASE::v2p(iss::addr_t{access, type, space, addr}), length, data); + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { + this->reg.trap_state = (1 << 31) | (5 << 16); // issue trap 5 (load access fault + fault_data = addr; } return res; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1 << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } } break; case traits::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return read_csr(addr, *reinterpret_cast(data)); + if(length != sizeof(reg_t)) + return iss::Err; + return read_csr(addr, *reinterpret_cast(data)); } break; case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; - switch (addr) { + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { case 2: // SFENCE:VMA lower case 3: { // SFENCE:VMA upper auto tvm = state.mstatus.TVM; - if (this->reg.PRIV == PRIV_S & tvm != 0) { + if(this->reg.PRIV == PRIV_S & tvm != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; @@ -668,7 +694,7 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ } break; case traits::RES: { auto it = atomic_reservation.find(addr); - if (it != atomic_reservation.end() && it->second != 0) { + if(it != atomic_reservation.end() && it->second != 0) { memset(data, 0xff, length); atomic_reservation.erase(addr); } else @@ -678,79 +704,81 @@ iss::status riscv_hart_msu_vp::read(const address_type type, const access_ return iss::Err; // assert("Not supported"); } return iss::Ok; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1UL << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } } template -iss::status riscv_hart_msu_vp::write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) { +iss::status riscv_hart_msu_vp::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, const uint8_t* const data) { #ifndef NDEBUG - const char *prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; - switch (length) { + const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; + switch(length) { case 8: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 4: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 2: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 1: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; default: LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; } #endif try { - switch (space) { + switch(space) { case traits::MEM: { - if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { + if(unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); + if(access && iss::access_type::DEBUG) + throw trap_access(0, addr); this->reg.trap_state = (1 << 31); // issue trap 0 return iss::Err; } phys_addr_t paddr = BASE::v2p(iss::addr_t{access, type, space, addr}); try { - if (unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary + if(unlikely((addr & ~PGMASK) != ((addr + length - 1) & ~PGMASK))) { // we may cross a page boundary vm_info vm = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp); - if (vm.levels != 0) { // VM is active + if(vm.levels != 0) { // VM is active auto split_addr = (addr + length) & ~PGMASK; auto len1 = split_addr - addr; auto res = write(type, access, space, addr, len1, data); - if (res == iss::Ok) + if(res == iss::Ok) res = write(type, access, space, split_addr, length - len1, data + len1); return res; } } auto res = write_mem(paddr, length, data); - if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault) - fault_data=addr; + fault_data = addr; } return res; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1UL << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } - if ((paddr.val + length) > mem.size()) return iss::Err; - switch (paddr.val) { + 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) { + if(((char)data[0]) == '\n' || data[0] == 0) { // LOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send // '"<::write(const address_type type, const access } return iss::Ok; case 0x10008000: { // HFROSC base, hfrosccfg reg - auto &p = mem(paddr.val / mem.page_size); + auto& p = mem(paddr.val / mem.page_size); auto offs = paddr.val & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); - auto &x = *(p.data() + offs + 3); - if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 + auto& x = *(p.data() + offs + 3); + if(x & 0x40) + x |= 0x80; // hfroscrdy = 1 if hfroscen==1 return iss::Ok; } case 0x10008008: { // HFROSC base, pllcfg reg - auto &p = mem(paddr.val / mem.page_size); + auto& p = mem(paddr.val / mem.page_size); auto offs = paddr.val & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); - auto &x = *(p.data() + offs + 3); + auto& x = *(p.data() + offs + 3); x |= 0x80; // set pll lock upon writing return iss::Ok; } break; @@ -777,17 +806,19 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access } } break; case traits::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return write_csr(addr, *reinterpret_cast(data)); + if(length != sizeof(reg_t)) + return iss::Err; + return write_csr(addr, *reinterpret_cast(data)); } break; case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; - switch (addr) { + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { case 2: case 3: { ptw.clear(); auto tvm = state.mstatus.TVM; - if (this->reg.PRIV == PRIV_S & tvm != 0) { + if(this->reg.PRIV == PRIV_S & tvm != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; @@ -803,43 +834,45 @@ iss::status riscv_hart_msu_vp::write(const address_type type, const access return iss::Err; } return iss::Ok; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1UL << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } } -template iss::status riscv_hart_msu_vp::read_csr(unsigned addr, reg_t &val) { - if (addr >= csr.size()) return iss::Err; +template iss::status riscv_hart_msu_vp::read_csr(unsigned addr, reg_t& val) { + if(addr >= csr.size()) + return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges - throw illegal_instruction_fault(this->fault_data); + if(this->reg.PRIV < req_priv_lvl) // not having required privileges + throw illegal_instruction_fault(this->fault_data); auto it = csr_rd_cb.find(addr); - if (it == csr_rd_cb.end() || !it->second) // non existent register + if(it == csr_rd_cb.end() || !it->second) // non existent register throw illegal_instruction_fault(this->fault_data); return (this->*(it->second))(addr, val); } template iss::status riscv_hart_msu_vp::write_csr(unsigned addr, reg_t val) { - if (addr >= csr.size()) return iss::Err; + if(addr >= csr.size()) + return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges + if(this->reg.PRIV < req_priv_lvl) // not having required privileges throw illegal_instruction_fault(this->fault_data); - if((addr&0xc00)==0xc00) // writing to read-only region + if((addr & 0xc00) == 0xc00) // writing to read-only region throw illegal_instruction_fault(this->fault_data); auto it = csr_wr_cb.find(addr); - if (it == csr_wr_cb.end() || !it->second) // non existent register + if(it == csr_wr_cb.end() || !it->second) // non existent register throw illegal_instruction_fault(this->fault_data); return (this->*(it->second))(addr, val); } -template iss::status riscv_hart_msu_vp::read_reg(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_reg(unsigned addr, reg_t& val) { val = csr[addr]; return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_null(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_null(unsigned addr, reg_t& val) { val = 0; return iss::Ok; } @@ -849,71 +882,73 @@ template iss::status riscv_hart_msu_vp::write_reg(unsigned return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_cycle(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_cycle(unsigned addr, reg_t& val) { auto cycle_val = this->reg.icount + cycle_offset; - if (addr == mcycle) { + if(addr == mcycle) { val = static_cast(cycle_val); - } else if (addr == mcycleh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; + } else if(addr == mcycleh) { + if(sizeof(typename traits::reg_t) != 4) + return iss::Err; val = static_cast(cycle_val >> 32); } return iss::Ok; } template iss::status riscv_hart_msu_vp::write_cycle(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { + if(sizeof(typename traits::reg_t) != 4) { mcycle_csr = static_cast(val); } else { - if (addr == mcycle) { + if(addr == mcycle) { mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val; - } else { - mcycle_csr = (static_cast(val)<<32) + (mcycle_csr & 0xffffffff); + } else { + mcycle_csr = (static_cast(val) << 32) + (mcycle_csr & 0xffffffff); } } - cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around + cycle_offset = mcycle_csr - this->reg.icount; // TODO: relying on wrap-around return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_instret(unsigned addr, reg_t &val) { - if ((addr&0xff) == (minstret&0xff)) { +template iss::status riscv_hart_msu_vp::read_instret(unsigned addr, reg_t& val) { + if((addr & 0xff) == (minstret & 0xff)) { val = static_cast(this->reg.instret); - } else if ((addr&0xff) == (minstreth&0xff)) { + } else if((addr & 0xff) == (minstreth & 0xff)) { val = static_cast(this->reg.instret >> 32); } return iss::Ok; } template iss::status riscv_hart_msu_vp::write_instret(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { + if(sizeof(typename traits::reg_t) != 4) { this->reg.instret = static_cast(val); } else { - if ((addr&0xff) == (minstret&0xff)) { + if((addr & 0xff) == (minstret & 0xff)) { this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; - } else { - this->reg.instret = (static_cast(val)<<32) + (this->reg.instret & 0xffffffff); + } else { + this->reg.instret = (static_cast(val) << 32) + (this->reg.instret & 0xffffffff); } } this->reg.instret--; return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_time(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_time(unsigned addr, reg_t& val) { uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; - if (addr == time) { + if(addr == time) { val = static_cast(time_val); - } else if (addr == timeh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; + } else if(addr == timeh) { + if(sizeof(typename traits::reg_t) != 4) + return iss::Err; val = static_cast(time_val >> 32); } return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_tvec(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_tvec(unsigned addr, reg_t& val) { val = csr[addr] & ~2; return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_status(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_status(unsigned addr, reg_t& val) { auto req_priv_lvl = (addr >> 8) & 0x3; val = state.mstatus & hart_state_type::get_mask(req_priv_lvl); return iss::Ok; @@ -928,18 +963,20 @@ template iss::status riscv_hart_msu_vp::write_status(unsig } template iss::status riscv_hart_msu_vp::write_cause(unsigned addr, reg_t val) { - csr[addr] = val & ((1UL<<(traits::XLEN-1))|0xf); //TODO: make exception code size configurable + csr[addr] = val & ((1UL << (traits::XLEN - 1)) | 0xf); // TODO: make exception code size configurable return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_ie(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_ie(unsigned addr, reg_t& val) { val = csr[mie]; - if (addr < mie) val &= csr[mideleg]; - if (addr < sie) val &= csr[sideleg]; + if(addr < mie) + val &= csr[mideleg]; + if(addr < sie) + val &= csr[sideleg]; return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_hartid(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_hartid(unsigned addr, reg_t& val) { val = mhartid_reg; return iss::Ok; } @@ -952,10 +989,12 @@ template iss::status riscv_hart_msu_vp::write_ie(unsigned return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_ip(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_ip(unsigned addr, reg_t& val) { val = csr[mip]; - if (addr < mip) val &= csr[mideleg]; - if (addr < sip) val &= csr[sideleg]; + if(addr < mip) + val &= csr[mideleg]; + if(addr < sip) + val &= csr[sideleg]; return iss::Ok; } @@ -964,9 +1003,9 @@ template iss::status riscv_hart_msu_vp::write_epc(unsigned return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_satp(unsigned addr, reg_t &val) { +template iss::status riscv_hart_msu_vp::read_satp(unsigned addr, reg_t& val) { reg_t tvm = state.mstatus.TVM; - if (this->reg.PRIV == PRIV_S & tvm != 0) { + if(this->reg.PRIV == PRIV_S & tvm != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; @@ -977,7 +1016,7 @@ template iss::status riscv_hart_msu_vp::read_satp(unsigned template iss::status riscv_hart_msu_vp::write_satp(unsigned addr, reg_t val) { reg_t tvm = state.mstatus.TVM; - if (this->reg.PRIV == PRIV_S & tvm != 0) { + if(this->reg.PRIV == PRIV_S & tvm != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; return iss::Err; @@ -986,8 +1025,8 @@ template iss::status riscv_hart_msu_vp::write_satp(unsigne update_vm_info(); return iss::Ok; } -template iss::status riscv_hart_msu_vp::read_fcsr(unsigned addr, reg_t &val) { - switch (addr) { +template iss::status riscv_hart_msu_vp::read_fcsr(unsigned addr, reg_t& val) { + switch(addr) { case 1: // fflags, 4:0 val = bit_sub<0, 5>(this->get_fcsr()); break; @@ -1004,7 +1043,7 @@ template iss::status riscv_hart_msu_vp::read_fcsr(unsigned } template iss::status riscv_hart_msu_vp::write_fcsr(unsigned addr, reg_t val) { - switch (addr) { + switch(addr) { case 1: // fflags, 4:0 this->set_fcsr((this->get_fcsr() & 0xffffffe0) | (val & 0x1f)); break; @@ -1020,56 +1059,53 @@ template iss::status riscv_hart_msu_vp::write_fcsr(unsigne return iss::Ok; } -template -iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - switch (paddr.val) { +template iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) { + switch(paddr.val) { default: { - for(auto offs=0U; offs -iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - switch (paddr.val) { +template iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) { + switch(paddr.val) { case 0xFFFF0000: // UART0 base, TXFIFO reg - if (((char)data[0]) == '\n' || data[0] == 0) { - LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<> 12) & 0x3) << " send '" << uart_buf.str() << "'"; uart_buf.str(""); } else if(((char)data[0]) != '\r') uart_buf << (char)data[0]; break; default: { - mem_type::page_type &p = mem(paddr.val / mem.page_size); + mem_type::page_type& p = mem(paddr.val / mem.page_size); std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); // tohost handling in case of riscv-test - if (paddr.access && iss::access_type::FUNC) { - auto tohost_upper = (traits::XLEN == 32 && paddr.val == (tohost + 4)) || - (traits::XLEN == 64 && paddr.val == tohost); - auto tohost_lower = - (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.val == tohost); - if (tohost_lower || tohost_upper) { - uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); - if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { - switch (hostvar >> 48) { + if(paddr.access && iss::access_type::FUNC) { + auto tohost_upper = + (traits::XLEN == 32 && paddr.val == (tohost + 4)) || (traits::XLEN == 64 && paddr.val == tohost); + auto tohost_lower = (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.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) { + if(hostvar != 0x1) { LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } else { LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } - this->reg.trap_state=std::numeric_limits::max(); - this->interrupt_sim=hostvar; + this->reg.trap_state = std::numeric_limits::max(); + this->interrupt_sim = hostvar; break; - //throw(iss::simulation_stopped(hostvar)); + // throw(iss::simulation_stopped(hostvar)); case 0x0101: { char c = static_cast(hostvar & 0xff); - if (c == '\n' || c == 0) { + if(c == '\n' || c == 0) { LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; uart_buf.str(""); } else @@ -1079,12 +1115,11 @@ iss::status riscv_hart_msu_vp::write_mem(phys_addr_t paddr, unsigned lengt default: break; } - } else if (tohost_lower) + } else if(tohost_lower) to_host_wr_cnt++; - } else if ((traits::XLEN == 32 && paddr.val == fromhost + 4) || - (traits::XLEN == 64 && paddr.val == fromhost)) { - uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); - *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; + } else if((traits::XLEN == 32 && paddr.val == fromhost + 4) || (traits::XLEN == 64 && paddr.val == fromhost)) { + uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); + *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; } } } @@ -1100,12 +1135,12 @@ template inline void riscv_hart_msu_vp::reset(uint64_t add template inline void riscv_hart_msu_vp::update_vm_info() { vm[1] = hart_state_type::decode_vm_info(this->reg.PRIV, state.satp); - BASE::addr_mode[3]=BASE::addr_mode[2] = vm[1].is_active()? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL; - if (state.mstatus.MPRV) + BASE::addr_mode[3] = BASE::addr_mode[2] = vm[1].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL; + if(state.mstatus.MPRV) vm[0] = hart_state_type::decode_vm_info(state.mstatus.MPP, state.satp); else vm[0] = vm[1]; - BASE::addr_mode[1] = BASE::addr_mode[0]=vm[0].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL; + BASE::addr_mode[1] = BASE::addr_mode[0] = vm[0].is_active() ? iss::address_type::VIRTUAL : iss::address_type::PHYSICAL; ptw.clear(); } @@ -1124,42 +1159,42 @@ template void riscv_hart_msu_vp::check_interrupt() { auto m_enabled = this->reg.PRIV < PRIV_M || (this->reg.PRIV == PRIV_M && mie); auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0; - if (enabled_interrupts == 0) { + if(enabled_interrupts == 0) { auto sie = state.mstatus.SIE; auto s_enabled = this->reg.PRIV < PRIV_S || (this->reg.PRIV == PRIV_S && sie); enabled_interrupts = s_enabled ? ena_irq & ideleg : 0; } - if (enabled_interrupts != 0) { + if(enabled_interrupts != 0) { int res = 0; - while ((enabled_interrupts & 1) == 0) enabled_interrupts >>= 1, res++; + while((enabled_interrupts & 1) == 0) + enabled_interrupts >>= 1, res++; this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id } } -template -typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::virt2phys(const iss::addr_t &addr) { +template typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::virt2phys(const iss::addr_t& addr) { const auto type = addr.access & iss::access_type::FUNC; auto it = ptw.find(addr.val >> PGSHIFT); - if (it != ptw.end()) { + if(it != ptw.end()) { const reg_t pte = it->second; const reg_t ad = PTE_A | (type == iss::access_type::WRITE) * PTE_D; #ifdef RISCV_ENABLE_DIRTY // set accessed and possibly dirty bits. - *(uint32_t *)ppte |= ad; + *(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) + if((pte & ad) == ad) return {addr.access, addr.space, (pte & (~PGMASK)) | (addr.val & PGMASK)}; else ptw.erase(it); // throw an exception #endif } else { uint32_t mode = type != iss::access_type::FETCH && state.mstatus.MPRV ? // MPRV - state.mstatus.MPP : - this->reg.PRIV; + state.mstatus.MPP + : this->reg.PRIV; - const vm_info &vm = this->vm[static_cast(type) / 2]; + const vm_info& vm = this->vm[static_cast(type) / 2]; const bool s_mode = mode == PRIV_S; const bool sum = state.mstatus.SUM; @@ -1172,38 +1207,39 @@ typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::virt2phys 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--) { + 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(iss::address_type::PHYSICAL, addr.access, - traits::MEM, base + idx * vm.ptesize, vm.ptesize, (uint8_t *)&pte); - if (res != 0) throw trap_load_access_fault(addr.val); + const uint8_t res = this->read(iss::address_type::PHYSICAL, addr.access, 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 + if(PTE_TABLE(pte)) { // next level of page table base = ppn << PGSHIFT; - } else if ((pte & PTE_U) ? s_mode && (type == iss::access_type::FETCH || !sum) : !s_mode) { + } else if((pte & PTE_U) ? s_mode && (type == iss::access_type::FETCH || !sum) : !s_mode) { break; - } else if (!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { + } else if(!(pte & PTE_V) || (!(pte & PTE_R) && (pte & PTE_W))) { break; - } else if (type == iss::access_type::FETCH - ? !(pte & PTE_X) - : type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) - : !((pte & PTE_R) && (pte & PTE_W))) { + } else if(type == iss::access_type::FETCH ? !(pte & PTE_X) + : type == iss::access_type::READ ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) + : !((pte & PTE_R) && (pte & PTE_W))) { break; - } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { + } else if((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { break; } else { const reg_t ad = PTE_A | ((type == iss::access_type::WRITE) * PTE_D); #ifdef RISCV_ENABLE_DIRTY // set accessed and possibly dirty bits. - *(uint32_t *)ppte |= ad; + *(uint32_t*)ppte |= ad; #else // take exception if access or possibly dirty bit is not set. - if ((pte & ad) != ad) break; + if((pte & ad) != ad) + break; #endif // for superpage mappings, make a fake leaf PTE for the TLB's benefit. const reg_t vpn = addr.val >> PGSHIFT; @@ -1214,7 +1250,7 @@ typename riscv_hart_msu_vp::phys_addr_t riscv_hart_msu_vp::virt2phys } } } - switch (type) { + switch(type) { case access_type::FETCH: this->fault_data = addr.val; throw trap_instruction_page_fault(addr.val); @@ -1233,14 +1269,16 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f auto cur_priv = this->reg.PRIV; // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val - if(flags==std::numeric_limits::max()) flags=this->reg.trap_state; + if(flags == std::numeric_limits::max()) + flags = this->reg.trap_state; auto trap_id = bit_sub<0, 16>(flags); auto cause = bit_sub<16, 15>(flags); - if (trap_id == 0 && cause == 11) cause = 0x8 + cur_priv; // adjust environment call cause + 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) + 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 @@ -1251,15 +1289,15 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f * access, or page-fault exception occurs, mtval is written with the * faulting effective address. */ - switch(cause){ + switch(cause) { case 0: csr[utval | (new_priv << 8)] = static_cast(addr); break; case 2: - csr[utval | (new_priv << 8)] = (instr & 0x3)==3?instr:instr&0xffff; + csr[utval | (new_priv << 8)] = (instr & 0x3) == 3 ? instr : instr & 0xffff; break; case 3: - //TODO: implement debug mode behavior + // TODO: implement debug mode behavior // csr[dpc] = addr; // csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) csr[utval | (new_priv << 8)] = addr; @@ -1274,7 +1312,7 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f } fault_data = 0; } else { - if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) + 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; @@ -1288,7 +1326,7 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f // the trap; and the x IE field of mstatus // is cleared // store the actual privilege level in yPP and store interrupt enable flags - switch (new_priv) { + switch(new_priv) { case PRIV_M: state.mstatus.MPP = cur_priv; state.mstatus.MPIE = state.mstatus.MIE; @@ -1312,14 +1350,15 @@ template uint64_t riscv_hart_msu_vp::enter_trap(uint64_t f // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE // bits in mtvec this->reg.NEXT_PC = ivec & ~0x3UL; - if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; + if((ivec & 0x1) == 1 && trap_id != 0) + this->reg.NEXT_PC += 4 * cause; std::array buffer; sprintf(buffer.data(), "0x%016lx", addr); - if((flags&0xffffffff) != 0xffffffff) - CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" - << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" - << " at address " << buffer.data() << " occurred, changing privilege level from " - << lvl[cur_priv] << " to " << lvl[new_priv]; + if((flags & 0xffffffff) != 0xffffffff) + CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" + << cause << ")" + << " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[cur_priv] << " to " + << lvl[new_priv]; // reset trap state this->reg.PRIV = new_priv; this->reg.trap_state = 0; @@ -1333,7 +1372,7 @@ template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t f auto status = state.mstatus; auto tsr = state.mstatus.TSR; - if (cur_priv == PRIV_S && inst_priv == PRIV_S && tsr != 0) { + 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; @@ -1341,7 +1380,7 @@ template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t f // pop the relevant lower-privilege interrupt enable and privilege mode stack // clear respective yIE - switch (inst_priv) { + switch(inst_priv) { case PRIV_M: this->reg.PRIV = state.mstatus.MPP; state.mstatus.MPP = 0; // clear mpp to U mode @@ -1362,8 +1401,7 @@ template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t f } // sets the pc to the value stored in the x epc register. this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; - CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " - << lvl[this->reg.PRIV]; + CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.PRIV]; update_vm_info(); check_interrupt(); return this->reg.NEXT_PC; @@ -1372,12 +1410,12 @@ template uint64_t riscv_hart_msu_vp::leave_trap(uint64_t f template void riscv_hart_msu_vp::wait_until(uint64_t flags) { auto status = state.mstatus; auto tw = status.TW; - if (this->reg.PRIV == PRIV_S && tw != 0) { + if(this->reg.PRIV == PRIV_S && tw != 0) { this->reg.trap_state = (1 << 31) | (2 << 16); this->fault_data = this->reg.PC; } } -} -} +} // namespace arch +} // namespace iss #endif /* _RISCV_HART_MSU_VP_H */ diff --git a/src/iss/arch/riscv_hart_mu_p.h b/src/iss/arch/riscv_hart_mu_p.h index 33089af..7d4f999 100644 --- a/src/iss/arch/riscv_hart_mu_p.h +++ b/src/iss/arch/riscv_hart_mu_p.h @@ -35,22 +35,22 @@ #ifndef _RISCV_HART_MU_P_H #define _RISCV_HART_MU_P_H -#include "riscv_hart_common.h" #include "iss/arch/traits.h" #include "iss/instrumentation_if.h" #include "iss/log_categories.h" #include "iss/vm_if.h" +#include "riscv_hart_common.h" #ifndef FMT_HEADER_ONLY #define FMT_HEADER_ONLY #endif #include #include #include +#include #include #include #include #include -#include #include #include #include @@ -66,30 +66,31 @@ namespace iss { namespace arch { -template class riscv_hart_mu_p : public BASE { +template class riscv_hart_mu_p : public BASE { protected: const std::array lvl = {{'U', 'S', 'H', 'M'}}; - const std::array trap_str = {{"" - "Instruction address misaligned", // 0 - "Instruction access fault", // 1 - "Illegal instruction", // 2 - "Breakpoint", // 3 - "Load address misaligned", // 4 - "Load access fault", // 5 - "Store/AMO address misaligned", // 6 - "Store/AMO access fault", // 7 - "Environment call from U-mode", // 8 - "Environment call from S-mode", // 9 - "Reserved", // a - "Environment call from M-mode", // b - "Instruction page fault", // c - "Load page fault", // d - "Reserved", // e - "Store/AMO page fault"}}; - const std::array irq_str = { - {"User software interrupt", "Supervisor software interrupt", "Reserved", "Machine software interrupt", - "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", - "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; + const std::array trap_str = {{"" + "Instruction address misaligned", // 0 + "Instruction access fault", // 1 + "Illegal instruction", // 2 + "Breakpoint", // 3 + "Load address misaligned", // 4 + "Load access fault", // 5 + "Store/AMO address misaligned", // 6 + "Store/AMO access fault", // 7 + "Environment call from U-mode", // 8 + "Environment call from S-mode", // 9 + "Reserved", // a + "Environment call from M-mode", // b + "Instruction page fault", // c + "Load page fault", // d + "Reserved", // e + "Store/AMO page fault"}}; + const std::array 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"}}; + public: using core = BASE; using this_class = riscv_hart_mu_p; @@ -97,10 +98,10 @@ public: using reg_t = typename core::reg_t; using addr_t = typename core::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); - using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t *const); - using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const *const); + using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t&); + using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); + using mem_read_f = iss::status(phys_addr_t addr, unsigned, uint8_t* const); + using mem_write_f = iss::status(phys_addr_t addr, unsigned, uint8_t const* const); // primary template template struct hart_state {}; @@ -108,7 +109,8 @@ public: template class hart_state::value>::type> { public: BEGIN_BF_DECL(mstatus_t, T); - // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) BF_FIELD(SD, 31, 1); // Trap SRET BF_FIELD(TSR, 22, 1); @@ -122,7 +124,8 @@ public: BF_FIELD(SUM, 18, 1); // Modify PRiVilege BF_FIELD(MPRV, 17, 1); - // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty BF_FIELD(XS, 15, 2); // floating-point unit status Off/Initial/Clean/Dirty BF_FIELD(FS, 13, 2); @@ -158,25 +161,26 @@ public: #if __cplusplus < 201402L return priv_lvl == PRIV_U ? 0x80000011UL : priv_lvl == PRIV_S ? 0x800de133UL : 0x807ff9ddUL; #else - switch (priv_lvl) { - case PRIV_U: return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 + switch(priv_lvl) { + case PRIV_U: + return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 default: - // +-SD - // | +-TSR - // | |+-TW - // | ||+-TVM - // | |||+-MXR - // | ||||+-SUM - // | |||||+-MPRV - // | |||||| +-XS - // | |||||| | +-FS - // | |||||| | | +-MPP - // | |||||| | | | +-SPP - // | |||||| | | | |+-MPIE - // | |||||| | | | || +-UPIE - // | ||||||/|/|/| || |+-MIE - // | ||||||/|/|/| || || +-UIE - return 0b00000000000000000001100010011001; + // +-SD + // | +-TSR + // | |+-TW + // | ||+-TVM + // | |||+-MXR + // | ||||+-SUM + // | |||||+-MPRV + // | |||||| +-XS + // | |||||| | +-FS + // | |||||| | | +-MPP + // | |||||| | | | +-SPP + // | |||||| | | | |+-MPIE + // | |||||| | | | || +-UPIE + // | ||||||/|/|/| || |+-MIE + // | ||||||/|/|/| || || +-UIE + return 0b00000000000000000001100010011001; } #endif } @@ -186,7 +190,8 @@ public: template class hart_state::value>::type> { public: BEGIN_BF_DECL(mstatus_t, T); - // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR XS==11))) + // SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR + // XS==11))) BF_FIELD(SD, 63, 1); // value of XLEN for S-mode BF_FIELD(SXL, 34, 2); @@ -204,7 +209,8 @@ public: BF_FIELD(SUM, 18, 1); // Modify PRiVilege BF_FIELD(MPRV, 17, 1); - // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None dirty, some clean/Some dirty + // status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None + // dirty, some clean/Some dirty BF_FIELD(XS, 15, 2); // floating-point unit status Off/Initial/Clean/Dirty BF_FIELD(FS, 13, 2); @@ -240,25 +246,26 @@ public: #if __cplusplus < 201402L return priv_lvl == PRIV_U ? 0x011ULL : priv_lvl == PRIV_S ? 0x000de133ULL : 0x007ff9ddULL; #else - switch (priv_lvl) { - case PRIV_U: return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 + switch(priv_lvl) { + case PRIV_U: + return 0x00000011UL; // 0b1000 0000 0000 0000 0000 0000 0001 0001 default: - // +-SD - // | +-TSR - // | |+-TW - // | ||+-TVM - // | |||+-MXR - // | ||||+-SUM - // | |||||+-MPRV - // | |||||| +-XS - // | |||||| | +-FS - // | |||||| | | +-MPP - // | |||||| | | | +-SPP - // | |||||| | | | |+-MPIE - // | |||||| | | | || +-UPIE - // | ||||||/|/|/| || |+-MIE - // | ||||||/|/|/| || || +-UIE - return 0b00000000000000000001100010011001; + // +-SD + // | +-TSR + // | |+-TW + // | ||+-TVM + // | |||+-MXR + // | ||||+-SUM + // | |||||+-MPRV + // | |||||| +-XS + // | |||||| | +-FS + // | |||||| | | +-MPP + // | |||||| | | | +-SPP + // | |||||| | | | |+-MPIE + // | |||||| | | | || +-UPIE + // | ||||||/|/|/| || |+-MIE + // | ||||||/|/|/| || || +-UIE + return 0b00000000000000000001100010011001; } #endif } @@ -271,56 +278,49 @@ public: 0b000100010001, // U mode 0b001100110011, // S mode 0, - 0b100110011001 // M mode + 0b100110011001 // M mode }}; return m[mode]; } - constexpr bool has_compressed() { - return traits::MISA_VAL&0b0100; - } - constexpr reg_t get_pc_mask() { - return has_compressed()?~1:~3; - } + constexpr bool has_compressed() { return traits::MISA_VAL & 0b0100; } + constexpr reg_t get_pc_mask() { return has_compressed() ? ~1 : ~3; } riscv_hart_mu_p(feature_config cfg = feature_config{}); - + virtual ~riscv_hart_mu_p() = default; void reset(uint64_t address) override; std::pair load_file(std::string name, int type = -1) override; - iss::status read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) override; - iss::status write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) override; + iss::status read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + uint8_t* const data) override; + iss::status write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, + const uint8_t* const data) override; uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); } uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; uint64_t leave_trap(uint64_t flags) override; - const reg_t& get_mhartid() const { return mhartid_reg; } - void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; + const reg_t& get_mhartid() const { return mhartid_reg; } + void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; }; void disass_output(uint64_t pc, const std::string instr) override { - CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", - pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset); + CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, + this->reg.icount + cycle_offset); }; - iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } + iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; } - void set_csr(unsigned addr, reg_t val){ - csr[addr & csr.page_addr_mask] = val; - } + void set_csr(unsigned addr, reg_t val) { csr[addr & csr.page_addr_mask] = val; } + + void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); } - void set_irq_num(unsigned i) { - mcause_max_irq=1< &arch) + riscv_instrumentation_if(riscv_hart_mu_p& arch) : arch(arch) {} /** * get the name of this architecture @@ -345,20 +345,20 @@ protected: bool is_branch_taken() override { return arch.reg.last_branch; } - unsigned get_reg_num() override {return traits::NUM_REGS; } + unsigned get_reg_num() override { return traits::NUM_REGS; } - riscv_hart_mu_p &arch; + riscv_hart_mu_p& arch; }; friend struct riscv_instrumentation_if; - virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data); - virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data); + virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t* const data); + virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t* const data); - iss::status read_clic(uint64_t addr, unsigned length, uint8_t *const data); - iss::status write_clic(uint64_t addr, unsigned length, const uint8_t *const data); + iss::status read_clic(uint64_t addr, unsigned length, uint8_t* const data); + iss::status write_clic(uint64_t addr, unsigned length, const uint8_t* const data); - virtual iss::status read_csr(unsigned addr, reg_t &val); + virtual iss::status read_csr(unsigned addr, reg_t& val); virtual iss::status write_csr(unsigned addr, reg_t val); hart_state_type state; @@ -385,7 +385,7 @@ protected: uint8_t clic_cfg_reg{0}; std::array clic_inttrig_reg; union clic_int_reg_t { - struct{ + struct { uint8_t ip; uint8_t ie; uint8_t attr; @@ -399,46 +399,42 @@ protected: std::vector tcm; - iss::status read_csr_reg(unsigned addr, reg_t &val); + iss::status read_csr_reg(unsigned addr, reg_t& val); iss::status write_csr_reg(unsigned addr, reg_t val); - iss::status read_null(unsigned addr, reg_t &val); - iss::status write_null(unsigned addr, reg_t val){return iss::status::Ok;} - iss::status read_cycle(unsigned addr, reg_t &val); + iss::status read_null(unsigned addr, reg_t& val); + iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; } + iss::status read_cycle(unsigned addr, reg_t& val); iss::status write_cycle(unsigned addr, reg_t val); - iss::status read_instret(unsigned addr, reg_t &val); + iss::status read_instret(unsigned addr, reg_t& val); iss::status write_instret(unsigned addr, reg_t val); - iss::status read_tvec(unsigned addr, reg_t &val); - iss::status read_time(unsigned addr, reg_t &val); - iss::status read_status(unsigned addr, reg_t &val); + iss::status read_tvec(unsigned addr, reg_t& val); + iss::status read_time(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_cause(unsigned addr, reg_t &val); + iss::status read_cause(unsigned addr, reg_t& val); iss::status write_cause(unsigned addr, reg_t val); - iss::status read_ie(unsigned addr, reg_t &val); + iss::status read_ie(unsigned addr, reg_t& val); iss::status write_ie(unsigned addr, reg_t val); - iss::status read_ip(unsigned addr, reg_t &val); + iss::status read_ip(unsigned addr, reg_t& val); iss::status write_ideleg(unsigned addr, reg_t val); iss::status write_edeleg(unsigned addr, reg_t val); - iss::status read_hartid(unsigned addr, reg_t &val); + iss::status read_hartid(unsigned addr, reg_t& val); iss::status write_epc(unsigned addr, reg_t val); iss::status read_intstatus(unsigned addr, reg_t& val); iss::status write_intthresh(unsigned addr, reg_t val); iss::status write_xtvt(unsigned addr, reg_t val); iss::status write_dcsr_dcsr(unsigned addr, reg_t val); - iss::status read_dcsr_reg(unsigned addr, reg_t &val); + iss::status read_dcsr_reg(unsigned addr, reg_t& val); iss::status write_dcsr_reg(unsigned addr, reg_t val); - iss::status read_dpc_reg(unsigned addr, reg_t &val); + iss::status read_dpc_reg(unsigned addr, reg_t& val); iss::status write_dpc_reg(unsigned addr, reg_t val); iss::status write_pmpcfg_reg(unsigned addr, reg_t val); - virtual iss::status read_custom_csr_reg(unsigned addr, reg_t &val) {return iss::status::Err;}; - virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) {return iss::status::Err;}; + virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; }; + virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; }; - void register_custom_csr_rd(unsigned addr){ - csr_rd_cb[addr] = &this_class::read_custom_csr_reg; - } - void register_custom_csr_wr(unsigned addr){ - csr_wr_cb[addr] = &this_class::write_custom_csr_reg; - } + void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; } + void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; } reg_t mhartid_reg{0x0}; @@ -449,11 +445,11 @@ protected: std::vector> memfn_write; void insert_mem_range(uint64_t, uint64_t, std::function, std::function); feature_config cfg; - uint64_t mcause_max_irq{(FEAT&features_e::FEAT_CLIC)?4096:16}; - inline bool debug_mode_active() {return this->reg.PRIV&0x4;} + uint64_t mcause_max_irq{(FEAT & features_e::FEAT_CLIC) ? 4096 : 16}; + inline bool debug_mode_active() { return this->reg.PRIV & 0x4; } - std::pair, std::function> - replace_mem_access(std::function rd, std::function wr){ + std::pair, std::function> replace_mem_access(std::function rd, + std::function wr) { std::pair, std::function> ret{hart_mem_rd_delegate, hart_mem_wr_delegate}; hart_mem_rd_delegate = rd; hart_mem_wr_delegate = wr; @@ -475,55 +471,70 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr[mimpid] = 1; uart_buf.str(""); - for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ + for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; csr_wr_cb[addr] = &this_class::write_csr_reg; } - if(traits::XLEN==32) for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ + if(traits::XLEN == 32) + for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + csr_wr_cb[addr] = &this_class::write_csr_reg; + } + for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; csr_wr_cb[addr] = &this_class::write_csr_reg; } - for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_csr_reg; - } - for (unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr){ + for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) { csr_rd_cb[addr] = &this_class::read_null; } - if(traits::XLEN==32) for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){ - csr_rd_cb[addr] = &this_class::read_null; - //csr_wr_cb[addr] = &this_class::write_csr_reg; - } + if(traits::XLEN == 32) + for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) { + csr_rd_cb[addr] = &this_class::read_null; + // csr_wr_cb[addr] = &this_class::write_csr_reg; + } // common regs const std::array roaddrs{{misa, mvendorid, marchid, mimpid}}; - for(auto addr: roaddrs) { + for(auto addr : roaddrs) { csr_rd_cb[addr] = &this_class::read_csr_reg; csr_wr_cb[addr] = &this_class::write_null; } const std::array rwaddrs{{ - mepc, mtvec, mscratch, mtval, - uepc, utvec, uscratch, utval, + mepc, + mtvec, + mscratch, + mtval, + uepc, + utvec, + uscratch, + utval, }}; - for(auto addr: rwaddrs) { + for(auto addr : rwaddrs) { csr_rd_cb[addr] = &this_class::read_csr_reg; csr_wr_cb[addr] = &this_class::write_csr_reg; } // special handling & overrides csr_rd_cb[time] = &this_class::read_time; - if(traits::XLEN==32) csr_rd_cb[timeh] = &this_class::read_time; + if(traits::XLEN == 32) + csr_rd_cb[timeh] = &this_class::read_time; csr_rd_cb[cycle] = &this_class::read_cycle; - if(traits::XLEN==32) csr_rd_cb[cycleh] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_rd_cb[cycleh] = &this_class::read_cycle; csr_rd_cb[instret] = &this_class::read_instret; - if(traits::XLEN==32) csr_rd_cb[instreth] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_rd_cb[instreth] = &this_class::read_instret; csr_rd_cb[mcycle] = &this_class::read_cycle; csr_wr_cb[mcycle] = &this_class::write_cycle; - if(traits::XLEN==32) csr_rd_cb[mcycleh] = &this_class::read_cycle; - if(traits::XLEN==32) csr_wr_cb[mcycleh] = &this_class::write_cycle; + if(traits::XLEN == 32) + csr_rd_cb[mcycleh] = &this_class::read_cycle; + if(traits::XLEN == 32) + csr_wr_cb[mcycleh] = &this_class::write_cycle; csr_rd_cb[minstret] = &this_class::read_instret; csr_wr_cb[minstret] = &this_class::write_instret; - if(traits::XLEN==32) csr_rd_cb[minstreth] = &this_class::read_instret; - if(traits::XLEN==32) csr_wr_cb[minstreth] = &this_class::write_instret; + if(traits::XLEN == 32) + csr_rd_cb[minstreth] = &this_class::read_instret; + if(traits::XLEN == 32) + csr_wr_cb[minstreth] = &this_class::write_instret; csr_rd_cb[mstatus] = &this_class::read_status; csr_wr_cb[mstatus] = &this_class::write_status; csr_rd_cb[mcause] = &this_class::read_cause; @@ -542,17 +553,17 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_wr_cb[marchid] = &this_class::write_null; csr_wr_cb[mimpid] = &this_class::write_null; - if(FEAT & FEAT_PMP){ - for(size_t i=pmpaddr0; i<=pmpaddr15; ++i){ + if(FEAT & FEAT_PMP) { + for(size_t i = pmpaddr0; i <= pmpaddr15; ++i) { csr_rd_cb[i] = &this_class::read_csr_reg; csr_wr_cb[i] = &this_class::write_csr_reg; } - for(size_t i=pmpcfg0; i::riscv_hart_mu_p(feature_config cfg) if(FEAT & FEAT_CLIC) { csr_rd_cb[mtvt] = &this_class::read_csr_reg; csr_wr_cb[mtvt] = &this_class::write_xtvt; -// csr_rd_cb[mxnti] = &this_class::read_csr_reg; -// csr_wr_cb[mxnti] = &this_class::write_csr_reg; + // csr_rd_cb[mxnti] = &this_class::read_csr_reg; + // csr_wr_cb[mxnti] = &this_class::write_csr_reg; csr_rd_cb[mintstatus] = &this_class::read_intstatus; csr_wr_cb[mintstatus] = &this_class::write_null; -// csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; -// csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; -// csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; -// csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; + // csr_rd_cb[mscratchcsw] = &this_class::read_csr_reg; + // csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; + // csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; + // csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_wr_cb[mintthresh] = &this_class::write_intthresh; - if(FEAT & FEAT_EXT_N){ + if(FEAT & FEAT_EXT_N) { csr_rd_cb[utvt] = &this_class::read_csr_reg; csr_wr_cb[utvt] = &this_class::write_xtvt; csr_rd_cb[uintstatus] = &this_class::read_intstatus; @@ -589,31 +600,32 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_rd_cb[uintthresh] = &this_class::read_csr_reg; csr_wr_cb[uintthresh] = &this_class::write_intthresh; } - clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw=0}); - clic_cfg_reg=0x30; - clic_mact_lvl = clic_mprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; - clic_uact_lvl = clic_uprev_lvl = (1<<(cfg.clic_int_ctl_bits)) - 1; - csr[mintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; - csr[uintthresh] = (1<<(cfg.clic_int_ctl_bits)) - 1; - insert_mem_range(cfg.clic_base, 0x5000UL, - [this](phys_addr_t addr, unsigned length, uint8_t * const data) { return read_clic(addr.val, length, data);}, - [this](phys_addr_t addr, unsigned length, uint8_t const * const data) {return write_clic(addr.val, length, data);}); + clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0}); + clic_cfg_reg = 0x30; + clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1; + clic_uact_lvl = clic_uprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1; + csr[mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1; + csr[uintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1; + insert_mem_range( + cfg.clic_base, 0x5000UL, + [this](phys_addr_t addr, unsigned length, uint8_t* const data) { return read_clic(addr.val, length, data); }, + [this](phys_addr_t addr, unsigned length, uint8_t const* const data) { return write_clic(addr.val, length, data); }); } if(FEAT & FEAT_TCM) { tcm.resize(cfg.tcm_size); - std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t * const data) { - auto offset=addr.val-this->cfg.tcm_base; + std::function read_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t* const data) { + auto offset = addr.val - this->cfg.tcm_base; std::copy(tcm.data() + offset, tcm.data() + offset + length, data); return iss::Ok; }; - std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const * const data) { - auto offset=addr.val-this->cfg.tcm_base; + std::function write_clic_cb = [this](phys_addr_t addr, unsigned length, uint8_t const* const data) { + auto offset = addr.val - this->cfg.tcm_base; std::copy(data, data + length, tcm.data() + offset); return iss::Ok; }; insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb); } - if(FEAT & FEAT_DEBUG){ + if(FEAT & FEAT_DEBUG) { csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg; @@ -623,255 +635,253 @@ riscv_hart_mu_p::riscv_hart_mu_p(feature_config cfg) csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; } - hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { - return this->read_mem(a, l, d); - }; - hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { - return this->write_mem(a, l, d); - }; + hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); }; + hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); }; } template std::pair riscv_hart_mu_p::load_file(std::string name, int type) { - FILE *fp = fopen(name.c_str(), "r"); - if (fp) { + FILE* fp = fopen(name.c_str(), "r"); + if(fp) { std::array buf; auto n = fread(buf.data(), 1, 4, fp); fclose(fp); - if (n != 4) throw std::runtime_error("input file has insufficient size"); + if(n != 4) + throw std::runtime_error("input file has insufficient size"); buf[4] = 0; - if (strcmp(buf.data() + 1, "ELF") == 0) { + if(strcmp(buf.data() + 1, "ELF") == 0) { // Create elfio reader ELFIO::elfio reader; // Load ELF data - if (!reader.load(name)) throw std::runtime_error("could not process elf file"); + if(!reader.load(name)) + throw std::runtime_error("could not process elf file"); // check elf properties - if (reader.get_class() != ELFCLASS32) - if (sizeof(reg_t) == 4) throw std::runtime_error("wrong elf class in file"); - if (reader.get_type() != ET_EXEC) throw std::runtime_error("wrong elf type in file"); - if (reader.get_machine() != EM_RISCV) throw std::runtime_error("wrong elf machine in file"); + if(reader.get_class() != ELFCLASS32) + if(sizeof(reg_t) == 4) + throw std::runtime_error("wrong elf class in file"); + if(reader.get_type() != ET_EXEC) + throw std::runtime_error("wrong elf type in file"); + if(reader.get_machine() != EM_RISCV) + throw std::runtime_error("wrong elf machine in file"); auto entry = reader.get_entry(); - for (const auto pseg : reader.segments) { + 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) { - auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, - traits::MEM, pseg->get_physical_address(), - fsize, reinterpret_cast(seg_data)); - if (res != iss::Ok) - LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex - << pseg->get_physical_address(); + if(fsize > 0) { + auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits::MEM, + pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); + if(res != iss::Ok) + LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); } } for(const auto sec : reader.sections) { if(sec->get_name() == ".symtab") { - if ( SHT_SYMTAB == sec->get_type() || - SHT_DYNSYM == sec->get_type() ) { - ELFIO::symbol_section_accessor symbols( reader, sec ); + if(SHT_SYMTAB == sec->get_type() || SHT_DYNSYM == sec->get_type()) { + ELFIO::symbol_section_accessor symbols(reader, sec); auto sym_no = symbols.get_symbols_num(); - std::string name; - ELFIO::Elf64_Addr value = 0; - ELFIO::Elf_Xword size = 0; - unsigned char bind = 0; - unsigned char type = 0; - ELFIO::Elf_Half section = 0; - unsigned char other = 0; - for ( auto i = 0U; i < sym_no; ++i ) { - symbols.get_symbol( i, name, value, size, bind, type, section, other ); - if(name=="tohost") { + std::string name; + ELFIO::Elf64_Addr value = 0; + ELFIO::Elf_Xword size = 0; + unsigned char bind = 0; + unsigned char type = 0; + ELFIO::Elf_Half section = 0; + unsigned char other = 0; + for(auto i = 0U; i < sym_no; ++i) { + symbols.get_symbol(i, name, value, size, bind, type, section, other); + if(name == "tohost") { tohost = value; - } else if(name=="fromhost") { + } else if(name == "fromhost") { fromhost = value; } } } - } else if (sec->get_name() == ".tohost") { + } else if(sec->get_name() == ".tohost") { tohost = sec->get_address(); fromhost = tohost + 0x40; } - } return std::make_pair(entry, true); } - throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file",name)); + throw std::runtime_error(fmt::format("memory load file {} is not a valid elf file", name)); } throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name)); } -template +template inline void riscv_hart_mu_p::insert_mem_range(uint64_t base, uint64_t size, std::function rd_f, - std::function wr_fn) { + std::function wr_fn) { std::tuple entry{base, size}; - auto it = std::upper_bound( memfn_range.begin(), memfn_range.end(), entry, - [](std::tuple const& a, std::tuple const& b){ - return std::get<0>(a)(b); - }); + auto it = std::upper_bound( + memfn_range.begin(), memfn_range.end(), entry, + [](std::tuple const& a, std::tuple const& b) { return std::get<0>(a) < std::get<0>(b); }); auto idx = std::distance(memfn_range.begin(), it); memfn_range.insert(it, entry); - memfn_read.insert(std::begin(memfn_read)+idx, rd_f); - memfn_write.insert(std::begin(memfn_write)+idx, wr_fn); + memfn_read.insert(std::begin(memfn_read) + idx, rd_f); + memfn_write.insert(std::begin(memfn_write) + idx, wr_fn); } -template -inline iss::status riscv_hart_mu_p::write_pmpcfg_reg(unsigned addr, reg_t val) { +template inline iss::status riscv_hart_mu_p::write_pmpcfg_reg(unsigned addr, reg_t val) { csr[addr] = val & 0x9f9f9f9f; return iss::Ok; } -template bool riscv_hart_mu_p::pmp_check(const access_type type, const uint64_t addr, const unsigned len) { - constexpr auto PMP_SHIFT=2U; +template +bool riscv_hart_mu_p::pmp_check(const access_type type, const uint64_t addr, const unsigned len) { + constexpr auto PMP_SHIFT = 2U; constexpr auto PMP_R = 0x1U; constexpr auto PMP_W = 0x2U; constexpr auto PMP_X = 0x4U; constexpr auto PMP_A = 0x18U; constexpr auto PMP_L = 0x80U; - constexpr auto PMP_TOR =0x1U; - constexpr auto PMP_NA4 =0x2U; - constexpr auto PMP_NAPOT =0x3U; + constexpr auto PMP_TOR = 0x1U; + constexpr auto PMP_NA4 = 0x2U; + constexpr auto PMP_NAPOT = 0x3U; reg_t base = 0; auto any_active = false; - auto const cfg_reg_size=sizeof(reg_t); - for (size_t i = 0; i < 16; i++) { - reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; - uint8_t cfg = csr[pmpcfg0+(i/cfg_reg_size)]>>(i%cfg_reg_size); - if (cfg & PMP_A) { - any_active=true; + auto const cfg_reg_size = sizeof(reg_t); + for(size_t i = 0; i < 16; i++) { + reg_t tor = csr[pmpaddr0 + i] << PMP_SHIFT; + uint8_t cfg = csr[pmpcfg0 + (i / cfg_reg_size)] >> (i % cfg_reg_size); + if(cfg & PMP_A) { + any_active = true; auto pmp_a = (cfg & PMP_A) >> 3; auto is_tor = pmp_a == PMP_TOR; auto is_na4 = pmp_a == PMP_NA4; - reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4); + reg_t mask = (csr[pmpaddr0 + i] << 1) | (!is_na4); mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; // Check each 4-byte sector of the access auto any_match = false; auto all_match = true; - for (reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) { + for(reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) { reg_t cur_addr = addr + offset; auto napot_match = ((cur_addr ^ tor) & mask) == 0; - auto tor_match = base <= (cur_addr+len-1) && cur_addr < tor; + auto tor_match = base <= (cur_addr + len - 1) && cur_addr < tor; auto match = is_tor ? tor_match : napot_match; any_match |= match; all_match &= match; } - if (any_match) { + if(any_match) { // If the PMP matches only a strict subset of the access, fail it - if (!all_match) + if(!all_match) return false; - return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || - (type == access_type::READ && (cfg & PMP_R)) || - (type == access_type::WRITE && (cfg & PMP_W)) || - (type == access_type::FETCH && (cfg & PMP_X)); + return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || (type == access_type::READ && (cfg & PMP_R)) || + (type == access_type::WRITE && (cfg & PMP_W)) || (type == access_type::FETCH && (cfg & PMP_X)); } } base = tor; } -// constexpr auto pmp_num_regs = 16; -// reg_t tor_base = 0; -// auto any_active = false; -// auto lower_addr = addr >>2; -// auto upper_addr = (addr+len-1)>>2; -// for (size_t i = 0; i < pmp_num_regs; i++) { -// uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); -// uint8_t cfg_next = i==(pmp_num_regs-1)? 0 : csr[pmpcfg0+((i+1)/4)]>>((i+1)%4); -// auto pmpaddr = csr[pmpaddr0+i]; -// if (cfg & PMP_A) { -// any_active=true; -// auto is_tor = bit_sub<3, 2>(cfg) == PMP_TOR; -// auto is_napot = bit_sub<4, 1>(cfg) && bit_sub<3, 2>(cfg_next)!= PMP_TOR; -// if(is_napot) { -// reg_t mask = bit_sub<3, 1>(cfg)?~( pmpaddr & ~(pmpaddr + 1)): 0x3fffffff; -// auto mpmpaddr = pmpaddr & mask; -// if((lower_addr&mask) == mpmpaddr && (upper_addr&mask)==mpmpaddr) -// return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || -// (type == access_type::READ && (cfg & PMP_R)) || -// (type == access_type::WRITE && (cfg & PMP_W)) || -// (type == access_type::FETCH && (cfg & PMP_X)); -// } else if(is_tor) { -// if(lower_addr>=tor_base && upper_addr<=pmpaddr) -// return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || -// (type == access_type::READ && (cfg & PMP_R)) || -// (type == access_type::WRITE && (cfg & PMP_W)) || -// (type == access_type::FETCH && (cfg & PMP_X)); -// } -// } -// tor_base = pmpaddr; -// } + // constexpr auto pmp_num_regs = 16; + // reg_t tor_base = 0; + // auto any_active = false; + // auto lower_addr = addr >>2; + // auto upper_addr = (addr+len-1)>>2; + // for (size_t i = 0; i < pmp_num_regs; i++) { + // uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); + // uint8_t cfg_next = i==(pmp_num_regs-1)? 0 : csr[pmpcfg0+((i+1)/4)]>>((i+1)%4); + // auto pmpaddr = csr[pmpaddr0+i]; + // if (cfg & PMP_A) { + // any_active=true; + // auto is_tor = bit_sub<3, 2>(cfg) == PMP_TOR; + // auto is_napot = bit_sub<4, 1>(cfg) && bit_sub<3, 2>(cfg_next)!= PMP_TOR; + // if(is_napot) { + // reg_t mask = bit_sub<3, 1>(cfg)?~( pmpaddr & ~(pmpaddr + 1)): 0x3fffffff; + // auto mpmpaddr = pmpaddr & mask; + // if((lower_addr&mask) == mpmpaddr && (upper_addr&mask)==mpmpaddr) + // return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || + // (type == access_type::READ && (cfg & PMP_R)) || + // (type == access_type::WRITE && (cfg & PMP_W)) || + // (type == access_type::FETCH && (cfg & PMP_X)); + // } else if(is_tor) { + // if(lower_addr>=tor_base && upper_addr<=pmpaddr) + // return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || + // (type == access_type::READ && (cfg & PMP_R)) || + // (type == access_type::WRITE && (cfg & PMP_W)) || + // (type == access_type::FETCH && (cfg & PMP_X)); + // } + // } + // tor_base = pmpaddr; + // } return !any_active || this->reg.PRIV == PRIV_M; } - template -iss::status riscv_hart_mu_p::read(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, uint8_t *const data) { +iss::status riscv_hart_mu_p::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, uint8_t* const data) { #ifndef NDEBUG - if (access && iss::access_type::DEBUG) { + if(access && iss::access_type::DEBUG) { LOG(TRACEALL) << "debug read of " << length << " bytes @addr 0x" << std::hex << addr; - } else if(is_fetch(access)){ + } else if(is_fetch(access)) { LOG(TRACEALL) << "fetch of " << length << " bytes @addr 0x" << std::hex << addr; } else { LOG(TRACE) << "read of " << length << " bytes @addr 0x" << std::hex << addr; - } + } #endif try { - switch (space) { + switch(space) { case traits::MEM: { - if(FEAT & FEAT_PMP){ + if(FEAT & FEAT_PMP) { if(!pmp_check(access, addr, length) && !is_debug(access)) { fault_data = addr; - if (is_debug(access)) throw trap_access(0, addr); - this->reg.trap_state = (1UL << 31) | ((access==access_type::FETCH?1:5) << 16); // issue trap 1 + if(is_debug(access)) + throw trap_access(0, addr); + this->reg.trap_state = (1UL << 31) | ((access == access_type::FETCH ? 1 : 5) << 16); // issue trap 1 return iss::Err; } } - auto alignment = is_fetch(access)? (has_compressed()? 2 : 4) : length; - if (unlikely(is_fetch(access) && (addr&(alignment-1)))) { + auto alignment = is_fetch(access) ? (has_compressed() ? 2 : 4) : length; + if(unlikely(is_fetch(access) && (addr & (alignment - 1)))) { fault_data = addr; - if (is_debug(access)) throw trap_access(0, addr); + if(is_debug(access)) + throw trap_access(0, addr); this->reg.trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { - if(!is_debug(access) && (addr&(alignment-1))){ - this->reg.trap_state = (1UL << 31) | 4<<16; - fault_data=addr; + if(!is_debug(access) && (addr & (alignment - 1))) { + this->reg.trap_state = (1UL << 31) | 4 << 16; + fault_data = addr; return iss::Err; } phys_addr_t phys_addr{access, space, addr}; auto res = iss::Err; - if(!is_fetch(access) && memfn_range.size()){ - auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ - return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; - }); - if(it!=std::end(memfn_range)) { + if(!is_fetch(access) && memfn_range.size()) { + auto it = + std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a) { + return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; + }); + if(it != std::end(memfn_range)) { auto idx = std::distance(std::begin(memfn_range), it); res = memfn_read[idx](phys_addr, length, data); } else - res = hart_mem_rd_delegate( phys_addr, length, data); + res = hart_mem_rd_delegate(phys_addr, length, data); } else { - res = hart_mem_rd_delegate( phys_addr, length, data); + res = hart_mem_rd_delegate(phys_addr, length, data); } - if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)){ + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { this->reg.trap_state = (1UL << 31) | (5 << 16); // issue trap 5 (load access fault - fault_data=addr; + fault_data = addr; } return res; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1UL << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } } break; case traits::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return read_csr(addr, *reinterpret_cast(data)); + if(length != sizeof(reg_t)) + return iss::Err; + return read_csr(addr, *reinterpret_cast(data)); } break; case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; + if((addr + length) > mem.size()) + return iss::Err; return iss::Ok; } break; case traits::RES: { auto it = atomic_reservation.find(addr); - if (it != atomic_reservation.end() && it->second != 0) { + if(it != atomic_reservation.end() && it->second != 0) { memset(data, 0xff, length); atomic_reservation.erase(addr); } else @@ -881,93 +891,97 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acc return iss::Err; // assert("Not supported"); } return iss::Ok; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1UL << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } } template -iss::status riscv_hart_mu_p::write(const address_type type, const access_type access, const uint32_t space, - const uint64_t addr, const unsigned length, const uint8_t *const data) { +iss::status riscv_hart_mu_p::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, + const unsigned length, const uint8_t* const data) { #ifndef NDEBUG - const char *prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; - switch (length) { + const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; + switch(length) { case 8: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint64_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 4: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint32_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 2: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t *)&data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << *(uint16_t*)&data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; case 1: - LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec - << ") @addr 0x" << std::hex << addr; + LOG(TRACE) << prefix << "write of " << length << " bytes (0x" << std::hex << (uint16_t)data[0] << std::dec << ") @addr 0x" + << std::hex << addr; break; default: LOG(TRACE) << prefix << "write of " << length << " bytes @addr " << addr; } #endif try { - switch (space) { + switch(space) { case traits::MEM: { - if(FEAT & FEAT_PMP){ - if(!pmp_check(access, addr, length) && (access&access_type::DEBUG) != access_type::DEBUG) { + if(FEAT & FEAT_PMP) { + if(!pmp_check(access, addr, length) && (access & access_type::DEBUG) != access_type::DEBUG) { fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); + if(access && iss::access_type::DEBUG) + throw trap_access(0, addr); this->reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 1 return iss::Err; } } - if (unlikely(is_fetch(access) && (addr & 0x1) == 1)) { + if(unlikely(is_fetch(access) && (addr & 0x1) == 1)) { fault_data = addr; - if (access && iss::access_type::DEBUG) throw trap_access(0, addr); + if(access && iss::access_type::DEBUG) + throw trap_access(0, addr); this->reg.trap_state = (1UL << 31); // issue trap 0 return iss::Err; } try { - if(length>1 && (addr&(length-1)) && (access&access_type::DEBUG) != access_type::DEBUG){ - this->reg.trap_state = (1UL << 31) | 6<<16; - fault_data=addr; + if(length > 1 && (addr & (length - 1)) && (access & access_type::DEBUG) != access_type::DEBUG) { + this->reg.trap_state = (1UL << 31) | 6 << 16; + fault_data = addr; return iss::Err; } phys_addr_t phys_addr{access, space, addr}; auto res = iss::Err; - if(!is_fetch(access) && memfn_range.size()){ - auto it = std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a){ - return std::get<0>(a)<=phys_addr.val && (std::get<0>(a)+std::get<1>(a))>phys_addr.val; - }); - if(it!=std::end(memfn_range)) { + if(!is_fetch(access) && memfn_range.size()) { + auto it = + std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple const& a) { + return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; + }); + if(it != std::end(memfn_range)) { auto idx = std::distance(std::begin(memfn_range), it); - res = memfn_write[idx]( phys_addr, length, data); + res = memfn_write[idx](phys_addr, length, data); } else - res = hart_mem_wr_delegate( phys_addr, length, data); + res = hart_mem_wr_delegate(phys_addr, length, data); } else { - res = hart_mem_wr_delegate( phys_addr, length, data); + res = hart_mem_wr_delegate(phys_addr, length, data); } - if (unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { + if(unlikely(res != iss::Ok && (access & access_type::DEBUG) == 0)) { this->reg.trap_state = (1UL << 31) | (7UL << 16); // issue trap 7 (Store/AMO access fault) - fault_data=addr; + fault_data = addr; } return res; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1UL << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } - if ((addr + length) > mem.size()) return iss::Err; - switch (addr) { + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { 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) { + if(((char)data[0]) == '\n' || data[0] == 0) { // LOG(INFO)<<"UART"<<((addr>>16)&0x3)<<" send // '"<::write(const address_type type, const ac } return iss::Ok; case 0x10008000: { // HFROSC base, hfrosccfg reg - auto &p = mem(addr / mem.page_size); + auto& p = mem(addr / mem.page_size); auto offs = addr & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); - auto &x = *(p.data() + offs + 3); - if (x & 0x40) x |= 0x80; // hfroscrdy = 1 if hfroscen==1 + auto& x = *(p.data() + offs + 3); + if(x & 0x40) + x |= 0x80; // hfroscrdy = 1 if hfroscen==1 return iss::Ok; } case 0x10008008: { // HFROSC base, pllcfg reg - auto &p = mem(addr / mem.page_size); + auto& p = mem(addr / mem.page_size); auto offs = addr & mem.page_addr_mask; std::copy(data, data + length, p.data() + offs); - auto &x = *(p.data() + offs + 3); + auto& x = *(p.data() + offs + 3); x |= 0x80; // set pll lock upon writing return iss::Ok; } break; @@ -994,12 +1009,14 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac } } break; case traits::CSR: { - if (length != sizeof(reg_t)) return iss::Err; - return write_csr(addr, *reinterpret_cast(data)); + if(length != sizeof(reg_t)) + return iss::Err; + return write_csr(addr, *reinterpret_cast(data)); } break; case traits::FENCE: { - if ((addr + length) > mem.size()) return iss::Err; - switch (addr) { + if((addr + length) > mem.size()) + return iss::Err; + switch(addr) { case 2: case 3: { ptw.clear(); @@ -1015,43 +1032,45 @@ iss::status riscv_hart_mu_p::write(const address_type type, const ac return iss::Err; } return iss::Ok; - } catch (trap_access &ta) { + } catch(trap_access& ta) { this->reg.trap_state = (1UL << 31) | ta.id; - fault_data=ta.addr; + fault_data = ta.addr; return iss::Err; } } -template iss::status riscv_hart_mu_p::read_csr(unsigned addr, reg_t &val) { - if (addr >= csr.size()) return iss::Err; +template iss::status riscv_hart_mu_p::read_csr(unsigned addr, reg_t& val) { + if(addr >= csr.size()) + return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges + if(this->reg.PRIV < req_priv_lvl) // not having required privileges throw illegal_instruction_fault(this->fault_data); auto it = csr_rd_cb.find(addr); - if (it == csr_rd_cb.end() || !it->second) // non existent register + if(it == csr_rd_cb.end() || !it->second) // non existent register throw illegal_instruction_fault(this->fault_data); return (this->*(it->second))(addr, val); } template iss::status riscv_hart_mu_p::write_csr(unsigned addr, reg_t val) { - if (addr >= csr.size()) return iss::Err; + if(addr >= csr.size()) + return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) // not having required privileges + if(this->reg.PRIV < req_priv_lvl) // not having required privileges throw illegal_instruction_fault(this->fault_data); - if((addr&0xc00)==0xc00) // writing to read-only region + if((addr & 0xc00) == 0xc00) // writing to read-only region throw illegal_instruction_fault(this->fault_data); auto it = csr_wr_cb.find(addr); - if (it == csr_wr_cb.end() || !it->second) // non existent register + if(it == csr_wr_cb.end() || !it->second) // non existent register throw illegal_instruction_fault(this->fault_data); return (this->*(it->second))(addr, val); } -template iss::status riscv_hart_mu_p::read_csr_reg(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_csr_reg(unsigned addr, reg_t& val) { val = csr[addr]; return iss::Ok; } -template iss::status riscv_hart_mu_p::read_null(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_null(unsigned addr, reg_t& val) { val = 0; return iss::Ok; } @@ -1061,69 +1080,70 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_cycle(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_cycle(unsigned addr, reg_t& val) { auto cycle_val = this->reg.icount + cycle_offset; - if (addr == mcycle) { + if(addr == mcycle) { val = static_cast(cycle_val); - } else if (addr == mcycleh) { + } else if(addr == mcycleh) { val = static_cast(cycle_val >> 32); } return iss::Ok; } template iss::status riscv_hart_mu_p::write_cycle(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { + if(sizeof(typename traits::reg_t) != 4) { mcycle_csr = static_cast(val); } else { - if (addr == mcycle) { + if(addr == mcycle) { mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val; - } else { - mcycle_csr = (static_cast(val)<<32) + (mcycle_csr & 0xffffffff); + } else { + mcycle_csr = (static_cast(val) << 32) + (mcycle_csr & 0xffffffff); } } - cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around + cycle_offset = mcycle_csr - this->reg.icount; // TODO: relying on wrap-around return iss::Ok; } -template iss::status riscv_hart_mu_p::read_instret(unsigned addr, reg_t &val) { - if ((addr&0xff) == (minstret&0xff)) { +template iss::status riscv_hart_mu_p::read_instret(unsigned addr, reg_t& val) { + if((addr & 0xff) == (minstret & 0xff)) { val = static_cast(this->reg.instret); - } else if ((addr&0xff) == (minstreth&0xff)) { + } else if((addr & 0xff) == (minstreth & 0xff)) { val = static_cast(this->reg.instret >> 32); } return iss::Ok; } template iss::status riscv_hart_mu_p::write_instret(unsigned addr, reg_t val) { - if (sizeof(typename traits::reg_t) != 4) { + if(sizeof(typename traits::reg_t) != 4) { this->reg.instret = static_cast(val); } else { - if ((addr&0xff) == (minstret&0xff)) { + if((addr & 0xff) == (minstret & 0xff)) { this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; - } else { - this->reg.instret = (static_cast(val)<<32) + (this->reg.instret & 0xffffffff); + } else { + this->reg.instret = (static_cast(val) << 32) + (this->reg.instret & 0xffffffff); } } this->reg.instret--; return iss::Ok; } -template iss::status riscv_hart_mu_p::read_time(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_time(unsigned addr, reg_t& val) { uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; - if (addr == time) { + if(addr == time) { val = static_cast(time_val); - } else if (addr == timeh) { - if (sizeof(typename traits::reg_t) != 4) return iss::Err; + } else if(addr == timeh) { + if(sizeof(typename traits::reg_t) != 4) + return iss::Err; val = static_cast(time_val >> 32); } return iss::Ok; } -template iss::status riscv_hart_mu_p::read_tvec(unsigned addr, reg_t &val) { - val = FEAT & features_e::FEAT_CLIC? csr[addr] : csr[addr] & ~2; +template iss::status riscv_hart_mu_p::read_tvec(unsigned addr, reg_t& val) { + val = FEAT & features_e::FEAT_CLIC ? csr[addr] : csr[addr] & ~2; return iss::Ok; } -template iss::status riscv_hart_mu_p::read_status(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_status(unsigned addr, reg_t& val) { val = state.mstatus & hart_state_type::get_mask((addr >> 8) & 0x3); return iss::Ok; } @@ -1134,58 +1154,58 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_cause(unsigned addr, reg_t &val) { - if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { - val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); +template iss::status riscv_hart_mu_p::read_cause(unsigned addr, reg_t& val) { + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) { + val = csr[addr] & ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16)); auto mode = (addr >> 8) & 0x3; switch(mode) { case 0: - val |= clic_uprev_lvl<<16; - val |= state.mstatus.UPIE<<27; + val |= clic_uprev_lvl << 16; + val |= state.mstatus.UPIE << 27; break; default: - val |= clic_mprev_lvl<<16; - val |= state.mstatus.MPIE<<27; - val |= state.mstatus.MPP<<28; + val |= clic_mprev_lvl << 16; + val |= state.mstatus.MPIE << 27; + val |= state.mstatus.MPP << 28; break; } } else - val = csr[addr] & ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); + val = csr[addr] & ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1)); return iss::Ok; } template iss::status riscv_hart_mu_p::write_cause(unsigned addr, reg_t val) { - if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec]&0x3)==3) { - auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1) | (0xfUL<<16)); + if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) { + auto mask = ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16)); csr[addr] = (val & mask) | (csr[addr] & ~mask); auto mode = (addr >> 8) & 0x3; switch(mode) { case 0: - clic_uprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; - state.mstatus.UPIE=(val>>27)&0x1; + clic_uprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1; + state.mstatus.UPIE = (val >> 27) & 0x1; break; default: - clic_mprev_lvl = ((val>>16)&0xff) | (1<<(8-cfg. clic_int_ctl_bits)) - 1; - state.mstatus.MPIE=(val>>27)&0x1; - state.mstatus.MPP=(val>>28)&0x3; + clic_mprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1; + state.mstatus.MPIE = (val >> 27) & 0x1; + state.mstatus.MPP = (val >> 28) & 0x3; break; } } else { - auto mask = ((1UL<<(traits::XLEN-1)) | (mcause_max_irq-1)); + auto mask = ((1UL << (traits::XLEN - 1)) | (mcause_max_irq - 1)); csr[addr] = (val & mask) | (csr[addr] & ~mask); } return iss::Ok; } -template iss::status riscv_hart_mu_p::read_hartid(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_hartid(unsigned addr, reg_t& val) { val = mhartid_reg; return iss::Ok; } -template iss::status riscv_hart_mu_p::read_ie(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_ie(unsigned addr, reg_t& val) { auto mask = get_irq_mask((addr >> 8) & 0x3); val = csr[mie] & mask; - if(this->reg.PRIV!=3) + if(this->reg.PRIV != 3) val &= csr[mideleg]; return iss::Ok; } @@ -1197,10 +1217,10 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_ip(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_ip(unsigned addr, reg_t& val) { auto mask = get_irq_mask((addr >> 8) & 0x3); val = csr[mip] & mask; - if(this->reg.PRIV!=3) + if(this->reg.PRIV != 3) val &= csr[mideleg]; return iss::Ok; } @@ -1233,7 +1253,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_dcsr_reg(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_dcsr_reg(unsigned addr, reg_t& val) { if(!debug_mode_active()) throw illegal_instruction_fault(this->fault_data); val = csr[addr]; @@ -1247,7 +1267,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_dpc_reg(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_dpc_reg(unsigned addr, reg_t& val) { if(!debug_mode_active()) throw illegal_instruction_fault(this->fault_data); val = this->reg.DPC; @@ -1261,33 +1281,30 @@ template iss::status riscv_hart_mu_p -iss::status riscv_hart_mu_p::read_intstatus(unsigned addr, reg_t& val) { +template iss::status riscv_hart_mu_p::read_intstatus(unsigned addr, reg_t& val) { auto mode = (addr >> 8) & 0x3; - val = clic_uact_lvl&0xff; - if(mode==0x3) - val += (clic_mact_lvl&0xff) <<24; + val = clic_uact_lvl & 0xff; + if(mode == 0x3) + val += (clic_mact_lvl & 0xff) << 24; return iss::Ok; } -template -iss::status riscv_hart_mu_p::write_intthresh(unsigned addr, reg_t val) { - csr[addr]= (val &0xff) | (1<<(cfg.clic_int_ctl_bits)) - 1; +template iss::status riscv_hart_mu_p::write_intthresh(unsigned addr, reg_t val) { + csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1; return iss::Ok; } -template -iss::status riscv_hart_mu_p::write_xtvt(unsigned addr, reg_t val) { - csr[addr]= val & ~0x3fULL; +template iss::status riscv_hart_mu_p::write_xtvt(unsigned addr, reg_t val) { + csr[addr] = val & ~0x3fULL; return iss::Ok; } template -iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { - switch (paddr.val) { +iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) { + switch(paddr.val) { default: { - for(auto offs=0U; offs::read_mem(phys_addr_t paddr, unsigned le } template -iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { - switch (paddr.val) { +iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) { + switch(paddr.val) { case 0xFFFF0000: // UART0 base, TXFIFO reg - if (((char)data[0]) == '\n' || data[0] == 0) { - LOG(INFO)<<"UART"<<((paddr.val>>12)&0x3)<<" send '"<> 12) & 0x3) << " send '" << uart_buf.str() << "'"; uart_buf.str(""); } else if(((char)data[0]) != '\r') uart_buf << (char)data[0]; break; default: { - mem_type::page_type &p = mem(paddr.val / mem.page_size); + mem_type::page_type& p = mem(paddr.val / mem.page_size); std::copy(data, data + length, p.data() + (paddr.val & mem.page_addr_mask)); // tohost handling in case of riscv-test - if (paddr.access && iss::access_type::FUNC) { - auto tohost_upper = (traits::XLEN == 32 && paddr.val == (tohost + 4)) || - (traits::XLEN == 64 && paddr.val == tohost); - auto tohost_lower = - (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.val == tohost); - if (tohost_lower || tohost_upper) { - uint64_t hostvar = *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)); - if (tohost_upper || (tohost_lower && to_host_wr_cnt > 0)) { - switch (hostvar >> 48) { + if(paddr.access && iss::access_type::FUNC) { + auto tohost_upper = + (traits::XLEN == 32 && paddr.val == (tohost + 4)) || (traits::XLEN == 64 && paddr.val == tohost); + auto tohost_lower = (traits::XLEN == 32 && paddr.val == tohost) || (traits::XLEN == 64 && paddr.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) { + if(hostvar != 0x1) { LOG(FATAL) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } else { LOG(INFO) << "tohost value is 0x" << std::hex << hostvar << std::dec << " (" << hostvar << "), stopping simulation"; } - this->reg.trap_state=std::numeric_limits::max(); - this->interrupt_sim=hostvar; + this->reg.trap_state = std::numeric_limits::max(); + this->interrupt_sim = hostvar; break; - //throw(iss::simulation_stopped(hostvar)); + // throw(iss::simulation_stopped(hostvar)); case 0x0101: { char c = static_cast(hostvar & 0xff); - if (c == '\n' || c == 0) { + if(c == '\n' || c == 0) { LOG(INFO) << "tohost send '" << uart_buf.str() << "'"; uart_buf.str(""); } else @@ -1341,12 +1357,11 @@ iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned l default: break; } - } else if (tohost_lower) + } else if(tohost_lower) to_host_wr_cnt++; - } else if ((traits::XLEN == 32 && paddr.val == fromhost + 4) || - (traits::XLEN == 64 && paddr.val == fromhost)) { - uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); - *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; + } else if((traits::XLEN == 32 && paddr.val == fromhost + 4) || (traits::XLEN == 64 && paddr.val == fromhost)) { + uint64_t fhostvar = *reinterpret_cast(p.data() + (fromhost & mem.page_addr_mask)); + *reinterpret_cast(p.data() + (tohost & mem.page_addr_mask)) = fhostvar; } } } @@ -1354,32 +1369,36 @@ iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned l return iss::Ok; } -template -iss::status riscv_hart_mu_p::read_clic(uint64_t addr, unsigned length, uint8_t *const data) { - if(addr==cfg.clic_base) { // cliccfg - *data=clic_cfg_reg; - for(auto i=1; i=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig - auto offset = ((addr&0x7fff)-0x40)/4; +template +iss::status riscv_hart_mu_p::read_clic(uint64_t addr, unsigned length, uint8_t* const data) { + if(addr == cfg.clic_base) { // cliccfg + *data = clic_cfg_reg; + for(auto i = 1; i < length; ++i) + *(data + i) = 0; + } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig + auto offset = ((addr & 0x7fff) - 0x40) / 4; read_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl - auto offset = ((addr&0x7fff)-0x1000)/4; + } else if(addr >= (cfg.clic_base + 0x1000) && + (addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl + auto offset = ((addr & 0x7fff) - 0x1000) / 4; read_reg_uint32(addr, clic_int_reg[offset].raw, data, length); } else { - for(auto i = 0U; i -iss::status riscv_hart_mu_p::write_clic(uint64_t addr, unsigned length, const uint8_t *const data) { - if(addr==cfg.clic_base) { // cliccfg - clic_cfg_reg = (clic_cfg_reg&~0x1e) | (*data&0x1e); - } else if(addr>=(cfg.clic_base+0x40) && (addr+length)<=(cfg.clic_base+0x40+cfg.clic_num_trigger*4)){ // clicinttrig - auto offset = ((addr&0x7fff)-0x40)/4; +template +iss::status riscv_hart_mu_p::write_clic(uint64_t addr, unsigned length, const uint8_t* const data) { + if(addr == cfg.clic_base) { // cliccfg + clic_cfg_reg = (clic_cfg_reg & ~0x1e) | (*data & 0x1e); + } else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig + auto offset = ((addr & 0x7fff) - 0x40) / 4; write_reg_uint32(addr, clic_inttrig_reg[offset], data, length); - } else if(addr>=(cfg.clic_base+0x1000) && (addr+length)<=(cfg.clic_base+0x1000+cfg.clic_num_irq*4)){ // clicintip/clicintie/clicintattr/clicintctl - auto offset = ((addr&0x7fff)-0x1000)/4; + } else if(addr >= (cfg.clic_base + 0x1000) && + (addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl + auto offset = ((addr & 0x7fff) - 0x1000) / 4; write_reg_uint32(addr, clic_int_reg[offset].raw, data, length); clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1 } @@ -1392,7 +1411,7 @@ template inline void riscv_hart_mu_p void riscv_hart_mu_p::check_interrupt() { - //TODO: Implement CLIC functionality + // TODO: Implement CLIC functionality auto ideleg = csr[mideleg]; // Multiple simultaneous interrupts and traps at the same privilege level are // handled in the following decreasing priority order: @@ -1404,11 +1423,11 @@ template void riscv_hart_mu_p::chec auto m_enabled = this->reg.PRIV < PRIV_M || mstatus_mie; auto enabled_interrupts = m_enabled ? ena_irq & ~ideleg : 0; - if (enabled_interrupts != 0) { + if(enabled_interrupts != 0) { int res = 0; - while ((enabled_interrupts & 1) == 0) { - enabled_interrupts >>= 1; - res++; + while((enabled_interrupts & 1) == 0) { + enabled_interrupts >>= 1; + res++; } this->reg.pending_trap = res << 16 | 1; // 0x80 << 24 | (cause << 16) | trap_id } @@ -1417,14 +1436,16 @@ template void riscv_hart_mu_p::chec template uint64_t riscv_hart_mu_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val - if(flags==std::numeric_limits::max()) flags=this->reg.trap_state; + if(flags == std::numeric_limits::max()) + flags = this->reg.trap_state; auto trap_id = bit_sub<0, 16>(flags); auto cause = bit_sub<16, 15>(flags); - if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause + if(trap_id == 0 && cause == 11) + cause = 0x8 + this->reg.PRIV; // adjust environment call cause // calculate effective privilege level unsigned new_priv = PRIV_M; - if (trap_id == 0) { // exception - if (this->reg.PRIV != PRIV_M && ((csr[medeleg] >> cause) & 0x1) != 0) + if(trap_id == 0) { // exception + if(this->reg.PRIV != PRIV_M && ((csr[medeleg] >> cause) & 0x1) != 0) new_priv = PRIV_U; // store ret addr in xepc register csr[uepc | (new_priv << 8)] = static_cast(addr); // store actual address instruction of exception @@ -1435,17 +1456,17 @@ template uint64_t riscv_hart_mu_p:: * access, or page-fault exception occurs, mtval is written with the * faulting effective address. */ - switch(cause){ + switch(cause) { case 0: csr[utval | (new_priv << 8)] = static_cast(addr); break; case 2: - csr[utval | (new_priv << 8)] = (!has_compressed() || (instr & 0x3)==3)?instr:instr&0xffff; + csr[utval | (new_priv << 8)] = (!has_compressed() || (instr & 0x3) == 3) ? instr : instr & 0xffff; break; case 3: if((FEAT & FEAT_DEBUG) && (csr[dcsr] & 0x8000)) { this->reg.DPC = addr; - csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) + csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1 << 6) | PRIV_M; // FIXME: cause should not be 4 (stepi) new_priv = this->reg.PRIV | PRIV_D; } else { csr[utval | (new_priv << 8)] = addr; @@ -1461,13 +1482,13 @@ template uint64_t riscv_hart_mu_p:: } fault_data = 0; } else { - if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) + if(this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) new_priv = PRIV_U; csr[uepc | (new_priv << 8)] = this->reg.NEXT_PC; // store next address if interrupt this->reg.pending_trap = 0; } size_t adr = ucause | (new_priv << 8); - csr[adr] = (trap_id << (traits::XLEN-1)) + cause; + csr[adr] = (trap_id << (traits::XLEN - 1)) + 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 @@ -1475,11 +1496,11 @@ template uint64_t riscv_hart_mu_p:: // the trap; and the x IE field of mstatus // is cleared // store the actual privilege level in yPP and store interrupt enable flags - switch (new_priv) { + switch(new_priv) { case PRIV_M: state.mstatus.MPP = this->reg.PRIV; - state.mstatus.MPIE = state.mstatus.MIE; - state.mstatus.MIE = false; + state.mstatus.MPIE = state.mstatus.MIE; + state.mstatus.MIE = false; break; case PRIV_U: state.mstatus.UPIE = state.mstatus.UIE; @@ -1493,7 +1514,7 @@ template uint64_t riscv_hart_mu_p:: auto xtvec = csr[utvec | (new_priv << 8)]; // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE // bits in mtvec - if((FEAT & features_e::FEAT_CLIC) && trap_id!=0 && (xtvec & 0x3UL)==3UL) { + if((FEAT & features_e::FEAT_CLIC) && trap_id != 0 && (xtvec & 0x3UL) == 3UL) { reg_t data; auto ret = read(address_type::LOGICAL, access_type::READ, 0, csr[mtvt], sizeof(reg_t), reinterpret_cast(&data)); if(ret == iss::Err) @@ -1501,7 +1522,7 @@ template uint64_t riscv_hart_mu_p:: this->reg.NEXT_PC = data; } else { this->reg.NEXT_PC = xtvec & ~0x3UL; - if ((xtvec & 0x1) == 1 && trap_id != 0) + if((xtvec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; } std::array buffer; @@ -1510,11 +1531,11 @@ template uint64_t riscv_hart_mu_p:: #else sprintf(buffer.data(), "0x%016lx", addr); #endif - if((flags&0xffffffff) != 0xffffffff) - CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" - << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" - << " at address " << buffer.data() << " occurred, changing privilege level from " - << lvl[this->reg.PRIV] << " to " << lvl[new_priv]; + if((flags & 0xffffffff) != 0xffffffff) + CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" + << cause << ")" + << " at address " << buffer.data() << " occurred, changing privilege level from " << lvl[this->reg.PRIV] + << " to " << lvl[new_priv]; // reset trap state this->reg.PRIV = new_priv; this->reg.trap_state = 0; @@ -1523,16 +1544,16 @@ template uint64_t riscv_hart_mu_p:: template uint64_t riscv_hart_mu_p::leave_trap(uint64_t flags) { auto cur_priv = this->reg.PRIV; - auto inst_priv = (flags & 0x3)? 3:0; - if(inst_priv>cur_priv){ - auto trap_val = 0x80ULL << 24 | (2 << 16); // illegal instruction + auto inst_priv = (flags & 0x3) ? 3 : 0; + if(inst_priv > cur_priv) { + auto trap_val = 0x80ULL << 24 | (2 << 16); // illegal instruction this->reg.trap_state = trap_val; this->reg.NEXT_PC = std::numeric_limits::max(); } else { auto status = state.mstatus; // pop the relevant lower-privilege interrupt enable and privilege mode stack // clear respective yIE - switch (inst_priv) { + switch(inst_priv) { case PRIV_M: this->reg.PRIV = state.mstatus.MPP; state.mstatus.MPP = 0; // clear mpp to U mode @@ -1547,8 +1568,7 @@ template uint64_t riscv_hart_mu_p:: } // sets the pc to the value stored in the x epc register. this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; - CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " - << lvl[this->reg.PRIV]; + CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.PRIV]; check_interrupt(); } return this->reg.NEXT_PC; diff --git a/src/iss/arch/tgc5c.cpp b/src/iss/arch/tgc5c.cpp index 6996cb8..eab100d 100644 --- a/src/iss/arch/tgc5c.cpp +++ b/src/iss/arch/tgc5c.cpp @@ -32,38 +32,35 @@ #include "tgc5c.h" #include "util/ities.h" -#include #include #include #include +#include using namespace iss::arch; -constexpr std::array iss::arch::traits::reg_names; -constexpr std::array iss::arch::traits::reg_aliases; +constexpr std::array iss::arch::traits::reg_names; +constexpr std::array iss::arch::traits::reg_aliases; constexpr std::array iss::arch::traits::reg_bit_widths; constexpr std::array iss::arch::traits::reg_byte_offsets; -tgc5c::tgc5c() = default; +tgc5c::tgc5c() = default; tgc5c::~tgc5c() = default; void tgc5c::reset(uint64_t address) { auto base_ptr = reinterpret_cast::reg_t*>(get_regs_base_ptr()); - for(size_t i=0; i::NUM_REGS; ++i) - *(base_ptr+i)=0; - reg.PC=address; - reg.NEXT_PC=reg.PC; - reg.PRIV=0x3; - reg.trap_state=0; - reg.icount=0; + for(size_t i = 0; i < traits::NUM_REGS; ++i) + *(base_ptr + i) = 0; + reg.PC = address; + reg.NEXT_PC = reg.PC; + reg.PRIV = 0x3; + reg.trap_state = 0; + reg.icount = 0; } -uint8_t *tgc5c::get_regs_base_ptr() { - return reinterpret_cast(®); -} +uint8_t* tgc5c::get_regs_base_ptr() { return reinterpret_cast(®); } -tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t &addr) { - return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); +tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t& addr) { + return phys_addr_t(addr.access, addr.space, addr.val & traits::addr_mask); } - diff --git a/src/iss/arch/tgc5c.h b/src/iss/arch/tgc5c.h index 2dddbb3..ee712b7 100644 --- a/src/iss/arch/tgc5c.h +++ b/src/iss/arch/tgc5c.h @@ -46,43 +46,103 @@ struct tgc5c; template <> struct traits { constexpr static char const* const core_type = "TGC5C"; - - static constexpr std::array reg_names{ - {"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc", "next_pc", "priv", "dpc"}}; - - static constexpr std::array reg_aliases{ - {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}}; - enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL}; + static constexpr std::array reg_names{{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", + "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", + "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", + "x27", "x28", "x29", "x30", "x31", "pc", "next_pc", "priv", "dpc"}}; + + static constexpr std::array reg_aliases{ + {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", + "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "next_pc", "priv", "dpc"}}; + + enum constants { + MISA_VAL = 1073746180ULL, + MARCHID_VAL = 2147483651ULL, + XLEN = 32ULL, + INSTR_ALIGNMENT = 2ULL, + RFS = 32ULL, + fence = 0ULL, + fencei = 1ULL, + fencevmal = 2ULL, + fencevmau = 3ULL, + CSR_SIZE = 4096ULL, + MUL_LEN = 64ULL + }; constexpr static unsigned FP_REGS_SIZE = 0; enum reg_e { - X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH + 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, + NEXT_PC, + PRIV, + DPC, + NUM_REGS, + TRAP_STATE = NUM_REGS, + PENDING_TRAP, + ICOUNT, + CYCLE, + INSTRET, + INSTRUCTION, + LAST_BRANCH }; using reg_t = uint32_t; using addr_t = uint32_t; - using code_word_t = uint32_t; //TODO: check removal + using code_word_t = uint32_t; // TODO: check removal using virt_addr_t = iss::typed_addr_t; using phys_addr_t = iss::typed_addr_t; - static constexpr std::array reg_bit_widths{ - {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64,32,32}}; + static constexpr std::array reg_bit_widths{{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 8, 32, 32, 32, 64, 64, 64, 32, 32}}; static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165,173,177}}; + {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, 137, 141, 145, 149, 157, 165, 173, 177}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); enum sreg_flag_e { FLAGS }; enum mem_type_e { MEM, FENCE, RES, CSR }; - + enum class opcode_e { LUI = 0, AUIPC = 1, @@ -175,17 +235,17 @@ template <> struct traits { }; }; -struct tgc5c: public arch_if { +struct tgc5c : public arch_if { using virt_addr_t = typename traits::virt_addr_t; using phys_addr_t = typename traits::phys_addr_t; - using reg_t = typename traits::reg_t; + using reg_t = typename traits::reg_t; using addr_t = typename traits::addr_t; tgc5c(); ~tgc5c(); - void reset(uint64_t address=0) override; + void reset(uint64_t address = 0) override; uint8_t* get_regs_base_ptr() override; @@ -201,44 +261,43 @@ struct tgc5c: public arch_if { inline uint32_t get_last_branch() { return reg.last_branch; } - #pragma pack(push, 1) - struct TGC5C_regs { - uint32_t X0 = 0; - uint32_t X1 = 0; - uint32_t X2 = 0; - uint32_t X3 = 0; - uint32_t X4 = 0; - uint32_t X5 = 0; - uint32_t X6 = 0; - uint32_t X7 = 0; - uint32_t X8 = 0; - uint32_t X9 = 0; - uint32_t X10 = 0; - uint32_t X11 = 0; - uint32_t X12 = 0; - uint32_t X13 = 0; - uint32_t X14 = 0; - uint32_t X15 = 0; - uint32_t X16 = 0; - uint32_t X17 = 0; - uint32_t X18 = 0; - uint32_t X19 = 0; - uint32_t X20 = 0; - uint32_t X21 = 0; - uint32_t X22 = 0; - uint32_t X23 = 0; - uint32_t X24 = 0; - uint32_t X25 = 0; - uint32_t X26 = 0; - uint32_t X27 = 0; - uint32_t X28 = 0; - uint32_t X29 = 0; - uint32_t X30 = 0; - uint32_t X31 = 0; - uint32_t PC = 0; - uint32_t NEXT_PC = 0; - uint8_t PRIV = 0; + struct TGC5C_regs { + uint32_t X0 = 0; + uint32_t X1 = 0; + uint32_t X2 = 0; + uint32_t X3 = 0; + uint32_t X4 = 0; + uint32_t X5 = 0; + uint32_t X6 = 0; + uint32_t X7 = 0; + uint32_t X8 = 0; + uint32_t X9 = 0; + uint32_t X10 = 0; + uint32_t X11 = 0; + uint32_t X12 = 0; + uint32_t X13 = 0; + uint32_t X14 = 0; + uint32_t X15 = 0; + uint32_t X16 = 0; + uint32_t X17 = 0; + uint32_t X18 = 0; + uint32_t X19 = 0; + uint32_t X20 = 0; + uint32_t X21 = 0; + uint32_t X22 = 0; + uint32_t X23 = 0; + uint32_t X24 = 0; + uint32_t X25 = 0; + uint32_t X26 = 0; + uint32_t X27 = 0; + uint32_t X28 = 0; + uint32_t X29 = 0; + uint32_t X30 = 0; + uint32_t X31 = 0; + uint32_t PC = 0; + uint32_t NEXT_PC = 0; + uint8_t PRIV = 0; uint32_t DPC = 0; uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; @@ -249,14 +308,13 @@ struct tgc5c: public arch_if { } reg; #pragma pack(pop) std::array addr_mode; - - uint64_t interrupt_sim=0; - uint32_t get_fcsr(){return 0;} - void set_fcsr(uint32_t val){} + uint64_t interrupt_sim = 0; + uint32_t get_fcsr() { return 0; } + void set_fcsr(uint32_t val) {} }; -} -} +} // namespace arch +} // namespace iss #endif /* _TGC5C_H_ */ diff --git a/src/iss/arch/tgc_mapper.h b/src/iss/arch/tgc_mapper.h index 83f82da..02ebacc 100644 --- a/src/iss/arch/tgc_mapper.h +++ b/src/iss/arch/tgc_mapper.h @@ -15,36 +15,43 @@ using tgc5a_plat_type = iss::arch::riscv_hart_m_p; using tgc5b_plat_type = iss::arch::riscv_hart_m_p; #endif #ifdef CORE_TGC5C_XRB_NN -#include "riscv_hart_m_p.h" #include "hwl.h" +#include "riscv_hart_m_p.h" #include using tgc5c_xrb_nn_plat_type = iss::arch::hwl>; #endif #ifdef CORE_TGC5D #include "riscv_hart_mu_p.h" #include -using tgc5d_plat_type = iss::arch::riscv_hart_mu_p; +using tgc5d_plat_type = iss::arch::riscv_hart_mu_p; #endif #ifdef CORE_TGC5D_XRB_MAC #include "riscv_hart_mu_p.h" #include -using tgc5d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p; +using tgc5d_xrb_mac_plat_type = + iss::arch::riscv_hart_mu_p; #endif #ifdef CORE_TGC5D_XRB_NN -#include "riscv_hart_mu_p.h" #include "hwl.h" +#include "riscv_hart_mu_p.h" #include -using tgc5d_xrb_nn_plat_type = iss::arch::hwl>; +using tgc5d_xrb_nn_plat_type = + iss::arch::hwl>; #endif #ifdef CORE_TGC5E #include "riscv_hart_mu_p.h" #include -using tgc5e_plat_type = iss::arch::riscv_hart_mu_p; +using tgc5e_plat_type = iss::arch::riscv_hart_mu_p; #endif #ifdef CORE_TGC5X #include "riscv_hart_mu_p.h" #include -using tgc5x_plat_type = iss::arch::riscv_hart_mu_p; +using tgc5x_plat_type = iss::arch::riscv_hart_mu_p; #endif #endif diff --git a/src/iss/arch/wt_cache.h b/src/iss/arch/wt_cache.h index 7108b9d..e762f22 100644 --- a/src/iss/arch/wt_cache.h +++ b/src/iss/arch/wt_cache.h @@ -36,25 +36,27 @@ #define _RISCV_HART_M_P_WT_CACHE_H #include -#include -#include #include #include +#include +#include namespace iss { namespace arch { namespace cache { -enum class state { INVALID, VALID}; +enum class state { INVALID, VALID }; struct line { uint64_t tag_addr{0}; state st{state::INVALID}; std::vector data; - line(unsigned line_sz): data(line_sz) {} + line(unsigned line_sz) + : data(line_sz) {} }; struct set { std::vector ways; - set(unsigned ways_count, line const& l): ways(ways_count, l) {} + set(unsigned ways_count, line const& l) + : ways(ways_count, l) {} }; struct cache { std::vector sets; @@ -62,14 +64,14 @@ struct cache { cache(unsigned size, unsigned line_sz, unsigned ways) { line const ref_line{line_sz}; set const ref_set{ways, ref_line}; - sets.resize(size/(ways*line_sz), ref_set); + sets.resize(size / (ways * line_sz), ref_set); } }; struct wt_policy { - bool is_cacheline_hit(cache& c ); + bool is_cacheline_hit(cache& c); }; -} +} // namespace cache // write thru, allocate on read, direct mapped or set-associative with round-robin replacement policy template class wt_cache : public BASE { @@ -89,78 +91,73 @@ public: unsigned ways{1}; uint64_t io_address{0xf0000000}; uint64_t io_addr_mask{0xf0000000}; + protected: - iss::status read_cache(phys_addr_t addr, unsigned, uint8_t *const); - iss::status write_cache(phys_addr_t addr, unsigned, uint8_t const *const); + iss::status read_cache(phys_addr_t addr, unsigned, uint8_t* const); + iss::status write_cache(phys_addr_t addr, unsigned, uint8_t const* const); std::function cache_mem_rd_delegate; std::function cache_mem_wr_delegate; std::unique_ptr dcache_ptr; std::unique_ptr icache_ptr; - size_t get_way_select() { - return 0; - } + size_t get_way_select() { return 0; } }; - -template +template inline wt_cache::wt_cache(feature_config cfg) -:BASE(cfg) +: BASE(cfg) , io_address{cfg.io_address} -, io_addr_mask{cfg.io_addr_mask} -{ +, io_addr_mask{cfg.io_addr_mask} { auto cb = base_class::replace_mem_access( - [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return read_cache(a, l,d);}, - [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return write_cache(a, l,d);}); + [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return read_cache(a, l, d); }, + [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return write_cache(a, l, d); }); cache_mem_rd_delegate = cb.first; cache_mem_wr_delegate = cb.second; } -template -iss::status iss::arch::wt_cache::read_cache(phys_addr_t a, unsigned l, uint8_t* const d) { +template iss::status iss::arch::wt_cache::read_cache(phys_addr_t a, unsigned l, uint8_t* const d) { if(!icache_ptr) { icache_ptr.reset(new cache::cache(size, line_sz, ways)); dcache_ptr.reset(new cache::cache(size, line_sz, ways)); } - if((a.val&io_addr_mask) != io_address) { - auto set_addr=(a.val&(size-1))>>util::ilog2(line_sz*ways); - auto tag_addr=a.val>>util::ilog2(line_sz); - auto& set = (is_fetch(a.access)?icache_ptr:dcache_ptr)->sets[set_addr]; - for(auto& cl: set.ways) { - if(cl.st==cache::state::VALID && cl.tag_addr==tag_addr) { - auto start_addr = a.val&(line_sz-1); - for(auto i = 0U; i> util::ilog2(line_sz * ways); + auto tag_addr = a.val >> util::ilog2(line_sz); + auto& set = (is_fetch(a.access) ? icache_ptr : dcache_ptr)->sets[set_addr]; + for(auto& cl : set.ways) { + if(cl.st == cache::state::VALID && cl.tag_addr == tag_addr) { + auto start_addr = a.val & (line_sz - 1); + for(auto i = 0U; i < l; ++i) + d[i] = cl.data[start_addr + i]; return iss::Ok; } } auto& cl = set.ways[get_way_select()]; phys_addr_t cl_addr{a}; - cl_addr.val=tag_addr< -iss::status iss::arch::wt_cache::write_cache(phys_addr_t a, unsigned l, const uint8_t* const d) { +template iss::status iss::arch::wt_cache::write_cache(phys_addr_t a, unsigned l, const uint8_t* const d) { if(!dcache_ptr) dcache_ptr.reset(new cache::cache(size, line_sz, ways)); auto res = cache_mem_wr_delegate(a, l, d); - if(res == iss::Ok && ((a.val&io_addr_mask) != io_address)) { - auto set_addr=(a.val&(size-1))>>util::ilog2(line_sz*ways); - auto tag_addr=a.val>>util::ilog2(line_sz); + if(res == iss::Ok && ((a.val & io_addr_mask) != io_address)) { + auto set_addr = (a.val & (size - 1)) >> util::ilog2(line_sz * ways); + auto tag_addr = a.val >> util::ilog2(line_sz); auto& set = dcache_ptr->sets[set_addr]; - for(auto& cl: set.ways) { - if(cl.st==cache::state::VALID && cl.tag_addr==tag_addr) { - auto start_addr = a.val&(line_sz-1); - for(auto i = 0U; i::write_cache(phys_addr_t a, unsigned l, co return res; } - - } // namespace arch } // namespace iss diff --git a/src/iss/debugger/riscv_target_adapter.h b/src/iss/debugger/riscv_target_adapter.h index d8d105e..6a2a527 100644 --- a/src/iss/debugger/riscv_target_adapter.h +++ b/src/iss/debugger/riscv_target_adapter.h @@ -53,20 +53,20 @@ using namespace iss::debugger; template class riscv_target_adapter : public target_adapter_base { public: - riscv_target_adapter(server_if *srv, iss::arch_if *core) + riscv_target_adapter(server_if* srv, iss::arch_if* core) : target_adapter_base(srv) , core(core) {} /*============== Thread Control ===============================*/ /* Set generic thread */ - status set_gen_thread(rp_thread_ref &thread) override; + status set_gen_thread(rp_thread_ref& thread) override; /* Set control thread */ - status set_ctrl_thread(rp_thread_ref &thread) override; + status set_ctrl_thread(rp_thread_ref& thread) override; /* Get thread status */ - status is_thread_alive(rp_thread_ref &thread, bool &alive) override; + status is_thread_alive(rp_thread_ref& thread, bool& alive) override; /*============= Register Access ================================*/ @@ -74,79 +74,77 @@ public: target byte order. If register is not available corresponding bytes in avail_buf are 0, otherwise avail buf is 1 */ - status read_registers(std::vector &data, std::vector &avail) override; + status read_registers(std::vector& data, std::vector& avail) override; /* Write all registers. buf is 4-byte aligned and it is in target byte order */ - status write_registers(const std::vector &data) override; + status write_registers(const std::vector& data) override; /* Read one register. buf is 4-byte aligned and it is in target byte order. If register is not available corresponding bytes in avail_buf are 0, otherwise avail buf is 1 */ - status read_single_register(unsigned int reg_no, std::vector &buf, - std::vector &avail_buf) override; + status read_single_register(unsigned int reg_no, std::vector& buf, std::vector& avail_buf) override; /* Write one register. buf is 4-byte aligned and it is in target byte order */ - status write_single_register(unsigned int reg_no, const std::vector &buf) override; + status write_single_register(unsigned int reg_no, const std::vector& buf) override; /*=================== Memory Access =====================*/ /* Read memory, buf is 4-bytes aligned and it is in target byte order */ - status read_mem(uint64_t addr, std::vector &buf) override; + status read_mem(uint64_t addr, std::vector& buf) override; /* Write memory, buf is 4-bytes aligned and it is in target byte order */ - status write_mem(uint64_t addr, const std::vector &buf) override; + status write_mem(uint64_t addr, const std::vector& buf) override; - status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override; + status process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) override; - status thread_list_query(int first, const rp_thread_ref &arg, std::vector &result, size_t max_num, - size_t &num, bool &done) override; + status thread_list_query(int first, const rp_thread_ref& arg, std::vector& result, size_t max_num, size_t& num, + bool& done) override; - status current_thread_query(rp_thread_ref &thread) override; + status current_thread_query(rp_thread_ref& thread) override; - status offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) override; + status offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) override; - status crc_query(uint64_t addr, size_t len, uint32_t &val) override; + status crc_query(uint64_t addr, size_t len, uint32_t& val) override; - status raw_query(std::string in_buf, std::string &out_buf) override; + status raw_query(std::string in_buf, std::string& out_buf) override; - status threadinfo_query(int first, std::string &out_buf) override; + status threadinfo_query(int first, std::string& out_buf) override; - status threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) override; + status threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) override; - status packetsize_query(std::string &out_buf) override; + status packetsize_query(std::string& out_buf) override; status add_break(break_type type, uint64_t addr, unsigned int length) override; status remove_break(break_type type, uint64_t addr, unsigned int length) override; - status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, - std::function stop_callback) override; + status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, std::function stop_callback) override; - status target_xml_query(std::string &out_buf) override; + status target_xml_query(std::string& out_buf) override; protected: - static inline constexpr addr_t map_addr(const addr_t &i) { return i; } + static inline constexpr addr_t map_addr(const addr_t& i) { return i; } - iss::arch_if *core; + iss::arch_if* core; rp_thread_ref thread_idx; }; -template status riscv_target_adapter::set_gen_thread(rp_thread_ref &thread) { +template status riscv_target_adapter::set_gen_thread(rp_thread_ref& thread) { thread_idx = thread; return Ok; } -template status riscv_target_adapter::set_ctrl_thread(rp_thread_ref &thread) { +template status riscv_target_adapter::set_ctrl_thread(rp_thread_ref& thread) { thread_idx = thread; return Ok; } -template status riscv_target_adapter::is_thread_alive(rp_thread_ref &thread, bool &alive) { +template status riscv_target_adapter::is_thread_alive(rp_thread_ref& thread, bool& alive) { alive = 1; return Ok; } @@ -158,10 +156,9 @@ template status riscv_target_adapter::is_thread_alive(rp_t * set if all threads are processed. */ template -status riscv_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) { +status riscv_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; @@ -171,23 +168,22 @@ status riscv_target_adapter::thread_list_query(int first, const rp_thread_ return NotSupported; } -template status riscv_target_adapter::current_thread_query(rp_thread_ref &thread) { +template status riscv_target_adapter::current_thread_query(rp_thread_ref& thread) { thread = thread_idx; return Ok; } -template -status riscv_target_adapter::read_registers(std::vector &data, std::vector &avail) { +template status riscv_target_adapter::read_registers(std::vector& data, std::vector& avail) { LOG(TRACE) << "reading target registers"; // return idx<0?:; data.clear(); avail.clear(); - const uint8_t *reg_base = core->get_regs_base_ptr(); - auto start_reg=arch::traits::X0; - for (size_t reg_no = start_reg; reg_no < start_reg+33/*arch::traits::NUM_REGS*/; ++reg_no) { + const uint8_t* reg_base = core->get_regs_base_ptr(); + auto start_reg = arch::traits::X0; + for(size_t reg_no = start_reg; reg_no < start_reg + 33 /*arch::traits::NUM_REGS*/; ++reg_no) { auto reg_width = arch::traits::reg_bit_widths[reg_no] / 8; unsigned offset = traits::reg_byte_offsets[reg_no]; - for (size_t j = 0; j < reg_width; ++j) { + for(size_t j = 0; j < reg_width; ++j) { data.push_back(*(reg_base + offset + j)); avail.push_back(0xff); } @@ -210,19 +206,19 @@ status riscv_target_adapter::read_registers(std::vector &data, st return Ok; } -template status riscv_target_adapter::write_registers(const std::vector &data) { - auto start_reg=arch::traits::X0; - auto *reg_base = core->get_regs_base_ptr(); +template status riscv_target_adapter::write_registers(const std::vector& data) { + auto start_reg = arch::traits::X0; + auto* reg_base = core->get_regs_base_ptr(); auto iter = data.data(); - bool e_ext = arch::traits::PC<32; - for (size_t reg_no = 0; reg_no < start_reg+33/*arch::traits::NUM_REGS*/; ++reg_no) { - if(e_ext && reg_no>15){ - if(reg_no==32){ + bool e_ext = arch::traits::PC < 32; + for(size_t reg_no = 0; reg_no < start_reg + 33 /*arch::traits::NUM_REGS*/; ++reg_no) { + if(e_ext && reg_no > 15) { + if(reg_no == 32) { auto reg_width = arch::traits::reg_bit_widths[arch::traits::PC] / 8; auto offset = traits::reg_byte_offsets[arch::traits::PC]; std::copy(iter, iter + reg_width, reg_base); } else { - const uint64_t zero_val=0; + const uint64_t zero_val = 0; auto reg_width = arch::traits::reg_bit_widths[15] / 8; auto iter = (uint8_t*)&zero_val; std::copy(iter, iter + reg_width, reg_base); @@ -239,12 +235,11 @@ template status riscv_target_adapter::write_registers(cons } template -status riscv_target_adapter::read_single_register(unsigned int reg_no, std::vector &data, - std::vector &avail) { - if (reg_no < 65) { +status riscv_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; - auto *reg_base = core->get_regs_base_ptr(); + auto* reg_base = core->get_regs_base_ptr(); auto reg_width = arch::traits::reg_bit_widths[reg_no] / 8; data.resize(reg_width); avail.resize(reg_width); @@ -261,10 +256,9 @@ status riscv_target_adapter::read_single_register(unsigned int reg_no, std return data.size() > 0 ? Ok : Err; } -template -status riscv_target_adapter::write_single_register(unsigned int reg_no, const std::vector &data) { - if (reg_no < 65) { - auto *reg_base = core->get_regs_base_ptr(); +template status riscv_target_adapter::write_single_register(unsigned int reg_no, const std::vector& data) { + if(reg_no < 65) { + auto* reg_base = core->get_regs_base_ptr(); auto reg_width = arch::traits::reg_bit_widths[static_cast::reg_e>(reg_no)] / 8; auto offset = traits::reg_byte_offsets[reg_no]; std::copy(data.begin(), data.begin() + reg_width, reg_base + offset); @@ -275,41 +269,36 @@ status riscv_target_adapter::write_single_register(unsigned int reg_no, co return Ok; } -template status riscv_target_adapter::read_mem(uint64_t addr, std::vector &data) { +template status riscv_target_adapter::read_mem(uint64_t addr, std::vector& data) { auto a = map_addr({iss::access_type::DEBUG_READ, iss::address_type::VIRTUAL, 0, addr}); auto f = [&]() -> status { return core->read(a, data.size(), data.data()); }; return srv->execute_syncronized(f); } -template status riscv_target_adapter::write_mem(uint64_t addr, const std::vector &data) { +template status riscv_target_adapter::write_mem(uint64_t addr, const std::vector& data) { auto a = map_addr({iss::access_type::DEBUG_READ, iss::address_type::VIRTUAL, 0, addr}); auto f = [&]() -> status { return core->write(a, data.size(), data.data()); }; return srv->execute_syncronized(f); } template -status riscv_target_adapter::process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) { +status riscv_target_adapter::process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) { return NotSupported; } -template -status riscv_target_adapter::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) { +template status riscv_target_adapter::offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) { text = 0; data = 0; bss = 0; return Ok; } -template status riscv_target_adapter::crc_query(uint64_t addr, size_t len, uint32_t &val) { - return NotSupported; -} +template status riscv_target_adapter::crc_query(uint64_t addr, size_t len, uint32_t& val) { return NotSupported; } -template status riscv_target_adapter::raw_query(std::string in_buf, std::string &out_buf) { - return NotSupported; -} +template status riscv_target_adapter::raw_query(std::string in_buf, std::string& out_buf) { return NotSupported; } -template status riscv_target_adapter::threadinfo_query(int first, std::string &out_buf) { - if (first) { +template status riscv_target_adapter::threadinfo_query(int first, std::string& out_buf) { + if(first) { out_buf = fmt::format("m{:x}", thread_idx.val); } else { out_buf = "l"; @@ -317,8 +306,7 @@ template status riscv_target_adapter::threadinfo_query(int return Ok; } -template -status riscv_target_adapter::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) { +template status riscv_target_adapter::threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) { std::array buf; memset(buf.data(), 0, 20); sprintf(buf.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); @@ -326,7 +314,7 @@ status riscv_target_adapter::threadextrainfo_query(const rp_thread_ref &th return Ok; } -template status riscv_target_adapter::packetsize_query(std::string &out_buf) { +template status riscv_target_adapter::packetsize_query(std::string& out_buf) { out_buf = "PacketSize=1000"; return Ok; } @@ -340,8 +328,8 @@ template status riscv_target_adapter::add_break(break_type auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length}); target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); - LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex - << saddr.val << std::dec; + LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex << saddr.val + << std::dec; LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; return Ok; } @@ -356,9 +344,8 @@ template status riscv_target_adapter::remove_break(break_t case HW_EXEC: { auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr}); unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); - if (handle) { - LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val - << std::dec; + if(handle) { + LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val << std::dec; // TODO: check length of addr range target_adapter_base::bp_lut.removeEntry(handle); LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; @@ -372,53 +359,53 @@ template status riscv_target_adapter::remove_break(break_t template status riscv_target_adapter::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, - std::function stop_callback) { - auto *reg_base = core->get_regs_base_ptr(); + std::function stop_callback) { + auto* reg_base = core->get_regs_base_ptr(); auto reg_width = arch::traits::reg_bit_widths[arch::traits::PC] / 8; auto offset = traits::reg_byte_offsets[arch::traits::PC]; - const uint8_t *iter = reinterpret_cast(&addr); + const uint8_t* iter = reinterpret_cast(&addr); std::copy(iter, iter + reg_width, reg_base); return resume_from_current(step, sig, thread, stop_callback); } -template status riscv_target_adapter::target_xml_query(std::string &out_buf) { +template status riscv_target_adapter::target_xml_query(std::string& out_buf) { const std::string res{"" - "riscv:rv32" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - //" \n" - ""}; + "riscv:rv32" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + //" \n" + ""}; out_buf = res; return Ok; } @@ -468,7 +455,7 @@ template status riscv_target_adapter::target_xml_query(std */ -} -} +} // namespace debugger +} // namespace iss #endif /* _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */ diff --git a/src/iss/factory.h b/src/iss/factory.h index c24fefb..a2a1943 100644 --- a/src/iss/factory.h +++ b/src/iss/factory.h @@ -33,21 +33,20 @@ #ifndef _ISS_FACTORY_H_ #define _ISS_FACTORY_H_ +#include +#include #include #include -#include -#include #include -#include +#include #include namespace iss { using cpu_ptr = std::unique_ptr; -using vm_ptr= std::unique_ptr; +using vm_ptr = std::unique_ptr; -template -std::tuple create_cpu(std::string const& backend, unsigned gdb_port){ +template std::tuple create_cpu(std::string const& backend, unsigned gdb_port) { using core_type = typename PLAT::core; core_type* lcpu = new PLAT(); if(backend == "interp") @@ -63,44 +62,45 @@ std::tuple create_cpu(std::string const& backend, unsigned gdb_ return {nullptr, nullptr}; } - class core_factory { using cpu_ptr = std::unique_ptr; - using vm_ptr= std::unique_ptr; + using vm_ptr = std::unique_ptr; using base_t = std::tuple; - using create_fn = std::function; - using registry_t = std::unordered_map ; + using create_fn = std::function; + using registry_t = std::unordered_map; registry_t registry; core_factory() = default; - core_factory(const core_factory &) = delete; - core_factory & operator=(const core_factory &) = delete; + core_factory(const core_factory&) = delete; + core_factory& operator=(const core_factory&) = delete; public: - static core_factory & instance() { static core_factory bf; return bf; } + static core_factory& instance() { + static core_factory bf; + return bf; + } - bool register_creator(const std::string & className, create_fn const& fn) { + bool register_creator(const std::string& className, create_fn const& fn) { registry[className] = fn; return true; } - base_t create(std::string const& className, unsigned gdb_port=0, void* init_data=nullptr) const { + base_t create(std::string const& className, unsigned gdb_port = 0, void* init_data = nullptr) const { registry_t::const_iterator regEntry = registry.find(className); - if (regEntry != registry.end()) + if(regEntry != registry.end()) return regEntry->second(gdb_port, init_data); return {nullptr, nullptr}; } std::vector get_names() { std::vector keys{registry.size()}; - std::transform(std::begin(registry), std::end(registry), std::begin(keys), [](std::pair const& p){ - return p.first; - }); + std::transform(std::begin(registry), std::end(registry), std::begin(keys), + [](std::pair const& p) { return p.first; }); return keys; } }; -} +} // namespace iss #endif /* _ISS_FACTORY_H_ */ diff --git a/src/iss/plugin/cycle_estimate.cpp b/src/iss/plugin/cycle_estimate.cpp index f5bac69..69e466a 100644 --- a/src/iss/plugin/cycle_estimate.cpp +++ b/src/iss/plugin/cycle_estimate.cpp @@ -36,17 +36,15 @@ #include #include +#include #include #include -#include using namespace std; iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name) : instr_if(nullptr) -, config_file_name(config_file_name) -{ -} +, config_file_name(config_file_name) {} iss::plugin::cycle_estimate::~cycle_estimate() = default; @@ -54,23 +52,24 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& instr_if = vm.get_arch()->get_instrumentation_if(); assert(instr_if && "No instrumentation interface available but callback executed"); reg_base_ptr = reinterpret_cast(vm.get_arch()->get_regs_base_ptr()); - if(!instr_if) return false; - const string core_name = instr_if->core_type_name(); - if (config_file_name.length() > 0) { + if(!instr_if) + return false; + const string core_name = instr_if->core_type_name(); + if(config_file_name.length() > 0) { std::ifstream is(config_file_name); - if (is.is_open()) { + if(is.is_open()) { try { auto root = YAML::LoadAll(is); - if(root.size()!=1) { + if(root.size() != 1) { LOG(ERR) << "Too many root nodes in YAML file " << config_file_name; } - for (auto p : root[0]) { + for(auto p : root[0]) { auto isa_subset = p.first; auto instructions = p.second; - for (auto const& instr : instructions) { + for(auto const& instr : instructions) { auto idx = instr.second["index"].as(); - if(delays.size()<=idx) - delays.resize(idx+1); + if(delays.size() <= idx) + delays.resize(idx + 1); auto& res = delays[idx]; res.is_branch = instr.second["branch"].as(); auto delay = instr.second["delay"]; @@ -81,13 +80,13 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& try { res.not_taken = delay.as(); res.taken = res.not_taken; - } catch (const YAML::BadConversion& e) { + } catch(const YAML::BadConversion& e) { res.f = iss::plugin::calculator(reg_base_ptr, delay.as()); } } } } - } catch (YAML::ParserException &e) { + } catch(YAML::ParserException& e) { LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); return false; } @@ -101,14 +100,14 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& void iss::plugin::cycle_estimate::callback(instr_info_t instr_info) { size_t instr_id = instr_info.instr_id; - auto& entry = instr_idget_instr_word()); } else { if(!entry.f) - current_delay = instr_if->is_branch_taken()? entry.taken: entry.not_taken; - if(current_delay>1) + current_delay = instr_if->is_branch_taken() ? entry.taken : entry.not_taken; + if(current_delay > 1) instr_if->update_last_instr_cycles(current_delay); current_delay = 1; } diff --git a/src/iss/plugin/cycle_estimate.h b/src/iss/plugin/cycle_estimate.h index 07cdd61..c2f6d13 100644 --- a/src/iss/plugin/cycle_estimate.h +++ b/src/iss/plugin/cycle_estimate.h @@ -37,16 +37,16 @@ #include "iss/instrumentation_if.h" #include "iss/vm_plugin.h" +#include #include #include #include -#include namespace iss { namespace plugin { -class cycle_estimate: public vm_plugin { +class cycle_estimate : public vm_plugin { struct instr_desc { size_t size{0}; bool is_branch{false}; @@ -58,32 +58,32 @@ class cycle_estimate: public vm_plugin { public: cycle_estimate() = delete; - cycle_estimate(const cycle_estimate &) = delete; + cycle_estimate(const cycle_estimate&) = delete; - cycle_estimate(const cycle_estimate &&) = delete; + cycle_estimate(const cycle_estimate&&) = delete; cycle_estimate(std::string const& config_file_name); virtual ~cycle_estimate(); - cycle_estimate &operator=(const cycle_estimate &) = delete; + cycle_estimate& operator=(const cycle_estimate&) = delete; - cycle_estimate &operator=(const cycle_estimate &&) = delete; + cycle_estimate& operator=(const cycle_estimate&&) = delete; - bool registration(const char *const version, vm_if &arch) override; + bool registration(const char* const version, vm_if& arch) override; sync_type get_sync() override { return ALL_SYNC; }; void callback(instr_info_t instr_info) override; private: - iss::instrumentation_if *instr_if{nullptr}; - uint32_t* reg_base_ptr {nullptr}; + iss::instrumentation_if* instr_if{nullptr}; + uint32_t* reg_base_ptr{nullptr}; instr_desc illegal_desc{}; std::vector delays; unsigned current_delay{0}; struct pair_hash { - size_t operator()(const std::pair &p) const { + size_t operator()(const std::pair& p) const { std::hash hash; return hash(p.first) + hash(p.second); } @@ -91,7 +91,7 @@ private: std::unordered_map, uint64_t, pair_hash> blocks; std::string config_file_name; }; -} -} +} // namespace plugin +} // namespace iss #endif /* _ISS_PLUGIN_CYCLE_ESTIMATE_H_ */ diff --git a/src/iss/plugin/instruction_count.cpp b/src/iss/plugin/instruction_count.cpp index 01fb45c..bb47e53 100644 --- a/src/iss/plugin/instruction_count.cpp +++ b/src/iss/plugin/instruction_count.cpp @@ -36,26 +36,26 @@ #include #include +#include #include #include -#include iss::plugin::instruction_count::instruction_count(std::string config_file_name) { - if (config_file_name.length() > 0) { + if(config_file_name.length() > 0) { std::ifstream is(config_file_name); - if (is.is_open()) { + if(is.is_open()) { try { auto root = YAML::LoadAll(is); - if(root.size()!=1) { + if(root.size() != 1) { LOG(ERR) << "Too many rro nodes in YAML file " << config_file_name; } - for (auto p : root[0]) { + for(auto p : root[0]) { auto isa_subset = p.first; auto instructions = p.second; - for (auto const& instr : instructions) { + for(auto const& instr : instructions) { instr_delay res; res.instr_name = instr.first.as(); - res.size = instr.second["encoding"].as().size()-2; // not counting 0b + res.size = instr.second["encoding"].as().size() - 2; // not counting 0b auto delay = instr.second["delay"]; if(delay.IsSequence()) { res.not_taken_delay = delay[0].as(); @@ -68,30 +68,29 @@ iss::plugin::instruction_count::instruction_count(std::string config_file_name) } } rep_counts.resize(delays.size()); - } catch (YAML::ParserException &e) { - LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); + } catch(YAML::ParserException& e) { + LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); } } else { - LOG(ERR) << "Could not open input file " << config_file_name; + LOG(ERR) << "Could not open input file " << config_file_name; } } } iss::plugin::instruction_count::~instruction_count() { - size_t idx=0; - for(auto it:delays){ - if(rep_counts[idx]>0 && it.instr_name.find("__"!=0)) - LOG(INFO)< 0 && it.instr_name.find("__" != 0)) + LOG(INFO) << it.instr_name << ";" << rep_counts[idx]; + idx++; + } } bool iss::plugin::instruction_count::registration(const char* const version, vm_if& vm) { auto instr_if = vm.get_arch()->get_instrumentation_if(); - if(!instr_if) return false; - return true; + if(!instr_if) + return false; + return true; } -void iss::plugin::instruction_count::callback(instr_info_t instr_info) { - rep_counts[instr_info.instr_id]++; -} +void iss::plugin::instruction_count::callback(instr_info_t instr_info) { rep_counts[instr_info.instr_id]++; } diff --git a/src/iss/plugin/instruction_count.h b/src/iss/plugin/instruction_count.h index 38c7f05..b31979c 100644 --- a/src/iss/plugin/instruction_count.h +++ b/src/iss/plugin/instruction_count.h @@ -53,19 +53,19 @@ class instruction_count : public iss::vm_plugin { public: instruction_count() = delete; - instruction_count(const instruction_count &) = delete; + instruction_count(const instruction_count&) = delete; - instruction_count(const instruction_count &&) = delete; + instruction_count(const instruction_count&&) = delete; instruction_count(std::string config_file_name); virtual ~instruction_count(); - instruction_count &operator=(const instruction_count &) = delete; + instruction_count& operator=(const instruction_count&) = delete; - instruction_count &operator=(const instruction_count &&) = delete; + instruction_count& operator=(const instruction_count&&) = delete; - bool registration(const char *const version, vm_if &arch) override; + bool registration(const char* const version, vm_if& arch) override; sync_type get_sync() override { return POST_SYNC; }; @@ -75,7 +75,7 @@ private: std::vector delays; std::vector rep_counts; }; -} -} +} // namespace plugin +} // namespace iss #endif /* _ISS_PLUGIN_INSTRUCTION_COUNTER_H_ */ diff --git a/src/main.cpp b/src/main.cpp index 03a68d0..61f3947 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,20 +30,20 @@ * *******************************************************************************/ -#include -#include #include +#include #include +#include +#include "iss/arch/tgc_mapper.h" #include #include -#include "iss/arch/tgc_mapper.h" #ifdef WITH_LLVM #include #endif -#include #include "iss/plugin/cycle_estimate.h" #include "iss/plugin/instruction_count.h" +#include #ifndef WIN32 #include #endif @@ -53,7 +53,7 @@ namespace po = boost::program_options; -int main(int argc, char *argv[]) { +int main(int argc, char* argv[]) { /* * Define and parse the program options */ @@ -79,12 +79,12 @@ int main(int argc, char *argv[]) { try { po::store(parsed, clim); // can throw // --help option - if (clim.count("help")) { + if(clim.count("help")) { std::cout << "DBT-RISE-TGC simulator for TGC RISC-V cores" << std::endl << desc << std::endl; return 0; } po::notify(clim); // throws on error, so do after help in case - } catch (po::error &e) { + } catch(po::error& e) { // there are problems std::cerr << "ERROR: " << e.what() << std::endl << std::endl; std::cerr << desc << std::endl; @@ -97,14 +97,14 @@ int main(int argc, char *argv[]) { auto l = logging::as_log_level(clim["verbose"].as()); LOGGER(DEFAULT)::reporting_level() = l; LOGGER(connection)::reporting_level() = l; - if (clim.count("logfile")) { + if(clim.count("logfile")) { // configure the connection logger auto f = fopen(clim["logfile"].as().c_str(), "w"); LOG_OUTPUT(DEFAULT)::stream() = f; LOG_OUTPUT(connection)::stream() = f; } - std::vector plugin_list; + std::vector plugin_list; auto res = 0; try { #ifdef WITH_LLVM @@ -112,51 +112,51 @@ int main(int argc, char *argv[]) { iss::init_jit_debug(argc, argv); #endif bool dump = clim.count("dump-ir"); - auto & f = iss::core_factory::instance(); + auto& f = iss::core_factory::instance(); // instantiate the simulator iss::vm_ptr vm{nullptr}; iss::cpu_ptr cpu{nullptr}; std::string isa_opt(clim["isa"].as()); - if(isa_opt.size()==0 || isa_opt == "?") { + if(isa_opt.size() == 0 || isa_opt == "?") { auto list = f.get_names(); std::sort(std::begin(list), std::end(list)); - std::cout<<"Available implementations (core|platform|backend):\n - "<(), clim["gdb-port"].as()); + } else if(isa_opt.find('|') != std::string::npos) { + std::tie(cpu, vm) = f.create(isa_opt + "|" + clim["backend"].as(), clim["gdb-port"].as()); } else { auto base_isa = isa_opt.substr(0, 5); - if(base_isa=="tgc5d" || base_isa=="tgc5e") { - isa_opt += "|mu_p_clic_pmp|"+clim["backend"].as(); + if(base_isa == "tgc5d" || base_isa == "tgc5e") { + isa_opt += "|mu_p_clic_pmp|" + clim["backend"].as(); } else { - isa_opt += "|m_p|"+clim["backend"].as(); + isa_opt += "|m_p|" + clim["backend"].as(); } std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as()); } - if(!cpu ){ - LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " <()<< std::endl; + if(!cpu) { + LOG(ERR) << "Could not create cpu for isa " << isa_opt << " and backend " << clim["backend"].as() << std::endl; return 127; } - if(!vm ){ - LOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " <()<< std::endl; + if(!vm) { + LOG(ERR) << "Could not create vm for isa " << isa_opt << " and backend " << clim["backend"].as() << std::endl; return 127; } - if (clim.count("plugin")) { - for (std::string const& opt_val : clim["plugin"].as>()) { - std::string plugin_name=opt_val; + if(clim.count("plugin")) { + for(std::string const& opt_val : clim["plugin"].as>()) { + std::string plugin_name = opt_val; std::string arg{""}; std::size_t found = opt_val.find('='); - if (found != std::string::npos) { + if(found != std::string::npos) { plugin_name = opt_val.substr(0, found); arg = opt_val.substr(found + 1, opt_val.size()); } #if defined(WITH_PLUGINS) - if (plugin_name == "ic") { - auto *ic_plugin = new iss::plugin::instruction_count(arg); + if(plugin_name == "ic") { + auto* ic_plugin = new iss::plugin::instruction_count(arg); vm->register_plugin(*ic_plugin); plugin_list.push_back(ic_plugin); - } else if (plugin_name == "ce") { - auto *ce_plugin = new iss::plugin::cycle_estimate(arg); + } else if(plugin_name == "ce") { + auto* ce_plugin = new iss::plugin::cycle_estimate(arg); vm->register_plugin(*ce_plugin); plugin_list.push_back(ce_plugin); } else @@ -168,7 +168,7 @@ int main(int argc, char *argv[]) { a.push_back({arg.c_str()}); iss::plugin::loader l(plugin_name, {{"initPlugin"}}); auto* plugin = l.call_function("initPlugin", a.size(), a.data()); - if(plugin){ + if(plugin) { vm->register_plugin(*plugin); plugin_list.push_back(plugin); } else @@ -180,42 +180,43 @@ int main(int argc, char *argv[]) { } } } - if (clim.count("disass")) { + if(clim.count("disass")) { vm->setDisassEnabled(true); LOGGER(disass)::reporting_level() = logging::INFO; LOGGER(disass)::print_time() = false; auto file_name = clim["disass"].as(); - if (file_name.length() > 0) { + if(file_name.length() > 0) { LOG_OUTPUT(disass)::stream() = fopen(file_name.c_str(), "w"); LOGGER(disass)::print_severity() = false; } } uint64_t start_address = 0; - if (clim.count("mem")) + if(clim.count("mem")) vm->get_arch()->load_file(clim["mem"].as()); - if (clim.count("elf")) - for (std::string input : clim["elf"].as>()) { + if(clim.count("elf")) + for(std::string input : clim["elf"].as>()) { auto start_addr = vm->get_arch()->load_file(input); - if (start_addr.second) start_address = start_addr.first; + if(start_addr.second) + start_address = start_addr.first; } - for (std::string input : args) { + for(std::string input : args) { auto start_addr = vm->get_arch()->load_file(input); // treat remaining arguments as elf files - if (start_addr.second) start_address = start_addr.first; + if(start_addr.second) + start_address = start_addr.first; } - if (clim.count("reset")) { + if(clim.count("reset")) { auto str = clim["reset"].as(); start_address = str.find("0x") == 0 ? std::stoull(str.substr(2), nullptr, 16) : std::stoull(str, nullptr, 10); } vm->reset(start_address); auto cycles = clim["instructions"].as(); res = vm->start(cycles, dump); - } catch (std::exception &e) { - LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" - << std::endl; + } catch(std::exception& e) { + LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl; res = 2; } // cleanup to let plugins report of needed - for (auto *p : plugin_list) { + for(auto* p : plugin_list) { delete p; } return res; diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index 051b0d7..e7cfbbc 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -55,8 +55,10 @@ // clang-format on #define STR(X) #X -#define CREATE_CORE(CN) \ -if (type == STR(CN)) { std::tie(cpu, vm) = create_core(backend, gdb_port, hart_id); } else +#define CREATE_CORE(CN) \ + if(type == STR(CN)) { \ + std::tie(cpu, vm) = create_core(backend, gdb_port, hart_id); \ + } else #ifdef HAS_SCV #include @@ -87,23 +89,22 @@ using namespace sc_core; namespace { iss::debugger::encoder_decoder encdec; std::array lvl = {{'U', 'S', 'H', 'M'}}; -} +} // namespace -int cmd_sysc(int argc, char *argv[], debugger::out_func of, debugger::data_func df, - debugger::target_adapter_if *tgt_adapter) { - if (argc > 1) { - if (strcasecmp(argv[1], "print_time") == 0) { +int cmd_sysc(int argc, char* argv[], debugger::out_func of, debugger::data_func df, debugger::target_adapter_if* tgt_adapter) { + if(argc > 1) { + if(strcasecmp(argv[1], "print_time") == 0) { std::string t = sc_time_stamp().to_string(); of(t.c_str()); std::array buf; encdec.enc_string(t.c_str(), buf.data(), 63); df(buf.data()); return Ok; - } else if (strcasecmp(argv[1], "break") == 0) { + } else if(strcasecmp(argv[1], "break") == 0) { sc_time t; - if (argc == 4) { + if(argc == 4) { t = scc::parse_from_string(argv[2], argv[3]); - } else if (argc == 3) { + } else if(argc == 3) { t = scc::parse_from_string(argv[2]); } else return Err; @@ -120,17 +121,19 @@ int cmd_sysc(int argc, char *argv[], debugger::out_func of, debugger::data_func } using cpu_ptr = std::unique_ptr; -using vm_ptr= std::unique_ptr; +using vm_ptr = std::unique_ptr; class core_wrapper { public: - core_wrapper(core_complex *owner) : owner(owner) { } + core_wrapper(core_complex* owner) + : owner(owner) {} - void reset(uint64_t addr){vm->reset(addr);} - inline void start(bool dump = false){vm->start(std::numeric_limits::max(), dump);} - inline std::pair load_file(std::string const& name){ + void reset(uint64_t addr) { vm->reset(addr); } + inline void start(bool dump = false) { vm->start(std::numeric_limits::max(), dump); } + inline std::pair load_file(std::string const& name) { iss::arch_if* cc = cpu->get_arch_if(); - return cc->load_file(name);}; + return cc->load_file(name); + }; std::function get_mode; std::function get_state; @@ -138,26 +141,26 @@ public: std::function set_interrupt_execution; std::function local_irq; - void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id){ - auto & f = sysc::iss_factory::instance(); - if(type.size()==0 || type == "?") { - std::cout<<"Available cores: "<(cpu.get()); sc_cpu_if->set_mhartid(hart_id); @@ -167,59 +170,59 @@ public: set_interrupt_execution = [sc_cpu_if](bool b) { return sc_cpu_if->set_interrupt_execution(b); }; local_irq = [sc_cpu_if](short s, bool b) { return sc_cpu_if->local_irq(s, b); }; - auto *srv = debugger::server::get(); - if (srv) tgt_adapter = srv->get_target(); - if (tgt_adapter) - tgt_adapter->add_custom_command( - {"sysc", [this](int argc, char *argv[], debugger::out_func of, - debugger::data_func df) -> int { return cmd_sysc(argc, argv, of, df, tgt_adapter); }, - "SystemC sub-commands: break