diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl new file mode 100644 index 0000000..94147f2 --- /dev/null +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (C) 2017 - 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. + * + *******************************************************************************/ +<% +def getRegisterSizes(){ + def regs = registers.collect{it.size} + regs[-1]=64 // correct for NEXT_PC + regs+=[32, 32, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT + return regs +} +%> +#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.PRIV=0x3; + reg.trap_state=0; + 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/gen_input/templates/interp/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl similarity index 98% rename from gen_input/templates/interp/CORENAME.h.gtl rename to gen_input/templates/CORENAME.h.gtl index 6c982d3..c8198ae 100644 --- a/gen_input/templates/interp/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -168,14 +168,16 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { inline uint32_t get_last_branch() { return reg.last_branch; } protected: +#pragma pack(push, 1) struct ${coreDef.name}_regs {<% registers.each { reg -> if(reg.size>0) {%> uint${byteSize(reg.size)}_t ${reg.name} = 0;<% }}%> - uint32_t trap_state = 0, pending_trap = 0, machine_state = 0, last_branch = 0; + uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; + uint32_t last_branch; } reg; - +#pragma pack(pop) std::array addr_mode; uint64_t interrupt_sim=0; diff --git a/gen_input/templates/interp/CORENAME_cyles.txt.gtl b/gen_input/templates/CORENAME_cyles.txt.gtl similarity index 100% rename from gen_input/templates/interp/CORENAME_cyles.txt.gtl rename to gen_input/templates/CORENAME_cyles.txt.gtl diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 010bcb7..688437d 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (C) 2017 - 2020 MINRES Technologies GmbH + * Copyright (C) 2021 MINRES Technologies GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,48 +29,273 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ -<% -def getRegisterSizes(){ - def regs = registers.collect{it.size} - regs[-1]=64 // correct for NEXT_PC - regs+=[32, 32, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT - return regs -} -%> -#include "util/ities.h" -#include + +#include "../fp_functions.h" #include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#ifndef FMT_HEADER_ONLY +#define FMT_HEADER_ONLY +#endif +#include + +#include +#include + +namespace iss { +namespace interp { +namespace ${coreDef.name.toLowerCase()} { using namespace iss::arch; +using namespace iss::debugger; -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; +template class vm_impl : public iss::interp::vm_base { +public: + using traits = arch::traits; + using super = typename iss::interp::vm_base; + using virt_addr_t = typename super::virt_addr_t; + using phys_addr_t = typename super::phys_addr_t; + using code_word_t = typename super::code_word_t; + using addr_t = typename super::addr_t; + using reg_t = typename traits::reg_t; + using mem_type_e = typename traits::mem_type_e; -${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { - reg.icount = 0; + vm_impl(); + + vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); + + void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } + + target_adapter_if *accquire_target_adapter(server_if *srv) override { + debugger_if::dbg_enabled = true; + if (super::tgt_adapter == nullptr) + super::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return super::tgt_adapter; + } + +protected: + using this_class = vm_impl; + using compile_ret_t = virt_addr_t; + using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); + + inline const char *name(size_t index){return traits::reg_aliases.at(index);} + + virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; + + // some compile time constants + // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; + enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; + enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; + enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + + std::array lut; + + std::array lut_00, lut_01, lut_10; + std::array lut_11; + + std::array qlut; + + std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; + + void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], + compile_func f) { + if (pos < 0) { + lut[idx] = f; + } else { + auto bitmask = 1UL << pos; + if ((mask & bitmask) == 0) { + expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); + } else { + if ((valid & bitmask) == 0) { + expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); + expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); + } else { + auto new_val = idx << 1; + if ((value & bitmask) != 0) new_val++; + expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); + } + } + } + } + + inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } + + uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { + if (pos >= 0) { + auto bitmask = 1UL << pos; + if ((mask & bitmask) == 0) { + lut_val = extract_fields(pos - 1, val, mask, lut_val); + } else { + auto new_val = lut_val << 1; + if ((val & bitmask) != 0) new_val++; + lut_val = extract_fields(pos - 1, val, mask, new_val); + } + } + return lut_val; + } + + 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->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); + } + + inline void leave(unsigned lvl){ + this->core.leave_trap(lvl); + auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); + this->template get_reg(traits::NEXT_PC) = pc_val; + } + + inline void wait(unsigned type){ + this->core.wait_until(type); + } + + 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){return super::template read_mem(space, addr);} + inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} + inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} + inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} + inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){super::write_mem(space, addr, data);} + inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){super::write_mem(space, addr, data);} + inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){super::write_mem(space, addr, data);} + inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){super::write_mem(space, addr, data);} + +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 */<%instructions.each{instr -> %> + /* instruction ${instr.instruction.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){ + // pre execution stuff + this->do_sync(PRE_SYNC, ${idx}); + <%instr.fields.eachLine{%>${it} + <%}%>if(this->disass_enabled){ + /* generate console output when executing the command */ + <%instr.disass.eachLine{%>${it} + <%}%> + } + // prepare execution + uint${addrDataWidth}_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); + uint${addrDataWidth}_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + uint${addrDataWidth}_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *NEXT_PC = *PC + ${instr.length/8}; + // execute instruction + <%instr.behavior.eachLine{%>${it} + <%}%>// post execution stuff + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, ${idx}); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + // trap check + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); + } + pc.val=*NEXT_PC; + return pc; + } + <%}%> + /**************************************************************************** + * end opcode definitions + ****************************************************************************/ + compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr) { + this->do_sync(PRE_SYNC, static_cast(arch::traits::opcode_e::MAX_OPCODE)); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); + raise(0, 11); + // post execution stuff + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(arch::traits::opcode_e::MAX_OPCODE)); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + // trap check + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); + } + pc.val=*NEXT_PC; + return pc; + } + + 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; + } +}; + +template void debug_fn(CODE_WORD insn) { + volatile CODE_WORD x = insn; + insn = 2 * x; } -${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default; +template vm_impl::vm_impl() { this(new ARCH()); } -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; +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); + } } -uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() { - return reinterpret_cast(®); +template +typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { + // we fetch at max 4 byte, alignment is 2 + enum {TRAP_ID=1<<16}; + code_word_t insn = 0; + auto *const data = (uint8_t *)&insn; + auto pc=start; + while(pred(pc)){ + auto res = fetch_ins(pc, data); + if(res!=iss::Ok){ + auto new_pc = super::core.enter_trap(TRAP_ID, pc.val); + res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data); + if(res!=iss::Ok) throw simulation_stopped(0); + } + auto lut_val = extract_fields(insn); + auto f = qlut[insn & 0x3][lut_val]; + if (!f) + f = &this_class::illegal_intruction; + pc = (this->*f)(pc, insn); + } + return pc; } -${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 -} +} // namespace mnrv32 +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 interp +} // namespace iss diff --git a/gen_input/templates/interp/vm_CORENAME.cpp.gtl b/gen_input/templates/interp/vm_CORENAME.cpp.gtl deleted file mode 100644 index 1e7701e..0000000 --- a/gen_input/templates/interp/vm_CORENAME.cpp.gtl +++ /dev/null @@ -1,280 +0,0 @@ -/******************************************************************************* - * 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. - * - *******************************************************************************/ - -#include "../fp_functions.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef FMT_HEADER_ONLY -#define FMT_HEADER_ONLY -#endif -#include - -#include -#include - -namespace iss { -namespace interp { -namespace ${coreDef.name.toLowerCase()} { -using namespace iss::arch; -using namespace iss::debugger; - -template class vm_impl : public iss::interp::vm_base { -public: - using traits = arch::traits; - using super = typename iss::interp::vm_base; - using virt_addr_t = typename super::virt_addr_t; - using phys_addr_t = typename super::phys_addr_t; - using code_word_t = typename super::code_word_t; - using addr_t = typename super::addr_t; - using reg_t = typename traits::reg_t; - using mem_type_e = typename traits::mem_type_e; - - vm_impl(); - - vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); - - void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } - - target_adapter_if *accquire_target_adapter(server_if *srv) override { - debugger_if::dbg_enabled = true; - if (super::tgt_adapter == nullptr) - super::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); - return super::tgt_adapter; - } - -protected: - using this_class = vm_impl; - using compile_ret_t = virt_addr_t; - using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr); - - inline const char *name(size_t index){return traits::reg_aliases.at(index);} - - virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; - - // some compile time constants - // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; - enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; - enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; - - std::array lut; - - std::array lut_00, lut_01, lut_10; - std::array lut_11; - - std::array qlut; - - std::array lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}}; - - void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], - compile_func f) { - if (pos < 0) { - lut[idx] = f; - } else { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); - } else { - if ((valid & bitmask) == 0) { - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); - expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); - } else { - auto new_val = idx << 1; - if ((value & bitmask) != 0) new_val++; - expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); - } - } - } - } - - inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } - - uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { - if (pos >= 0) { - auto bitmask = 1UL << pos; - if ((mask & bitmask) == 0) { - lut_val = extract_fields(pos - 1, val, mask, lut_val); - } else { - auto new_val = lut_val << 1; - if ((val & bitmask) != 0) new_val++; - lut_val = extract_fields(pos - 1, val, mask, new_val); - } - } - return lut_val; - } - - void raise(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->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); - } - - void leave(unsigned lvl){ - this->core.leave_trap(lvl); - auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); - this->template get_reg(traits::NEXT_PC) = pc_val; - } - - void wait(unsigned type){ - this->core.wait_until(type); - } - - 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){return super::template read_mem(space, addr);} - inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} - inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} - inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){return super::template read_mem(space, addr);} - inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){super::write_mem(space, addr, data);} - inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){super::write_mem(space, addr, data);} - inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){super::write_mem(space, addr, data);} - inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){super::write_mem(space, addr, data);} - -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 */<%instructions.each{instr -> %> - /* instruction ${instr.instruction.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){ - // pre execution stuff - this->do_sync(PRE_SYNC, ${idx}); - <%instr.fields.eachLine{%>${it} - <%}%>if(this->disass_enabled){ - /* generate console output when executing the command */ - <%instr.disass.eachLine{%>${it} - <%}%> - } - // prepare execution - uint${addrDataWidth}_t* X = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::X0]); - uint${addrDataWidth}_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); - uint${addrDataWidth}_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); - *NEXT_PC = *PC + ${instr.length/8}; - // execute instruction - <%instr.behavior.eachLine{%>${it} - <%}%>// post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, ${idx}); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); - // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); - } - pc.val=super::template get_reg(arch::traits::NEXT_PC); - return pc; - } - <%}%> - /**************************************************************************** - * end opcode definitions - ****************************************************************************/ - compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr) { - pc = pc + ((instr & 3) == 3 ? 4 : 2); - return pc; - } -}; - -template void debug_fn(CODE_WORD insn) { - volatile CODE_WORD x = insn; - insn = 2 * x; -} - -template vm_impl::vm_impl() { this(new ARCH()); } - -template -vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) -: vm_base(core, core_id, cluster_id) { - qlut[0] = lut_00.data(); - qlut[1] = lut_01.data(); - qlut[2] = lut_10.data(); - qlut[3] = lut_11.data(); - for (auto instr : instr_descr) { - auto quantrant = instr.value & 0x3; - expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); - } -} - -template -typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { - // we fetch at max 4 byte, alignment is 2 - enum {TRAP_ID=1<<16}; - const typename traits::addr_t upper_bits = ~traits::PGMASK; - code_word_t insn = 0; - auto *const data = (uint8_t *)&insn; - auto pc=start; - while(pred){ - auto paddr = this->core.v2p(pc); - if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary - if (this->core.read(paddr, 2, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val); - if ((insn & 0x3) == 0x3) // this is a 32bit instruction - if (this->core.read(this->core.v2p(pc + 2), 2, data + 2) != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } else { - if (this->core.read(paddr, 4, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val); - } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' - auto lut_val = extract_fields(insn); - auto f = qlut[insn & 0x3][lut_val]; - if (!f) - f = &this_class::illegal_intruction; - pc = (this->*f)(pc, insn); - } - return pc; -} - -} // namespace mnrv32 - -template <> -std::unique_ptr create(arch::${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 interp -} // namespace iss diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index 2f7de9b..d13d42f 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -354,6 +354,10 @@ public: mem_write_cb = memWriteCb; } + void set_csr(unsigned addr, reg_t val){ + csr[addr & csr.page_addr_mask] = val; + } + protected: struct riscv_instrumentation_if : public iss::instrumentation_if { @@ -405,6 +409,8 @@ protected: 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); iss::status read_cycle(unsigned addr, reg_t &val); iss::status read_time(unsigned addr, reg_t &val); iss::status read_status(unsigned addr, reg_t &val); @@ -450,6 +456,12 @@ riscv_hart_m_p::riscv_hart_m_p() csr_rd_cb[mie] = &riscv_hart_m_p::read_ie; csr_wr_cb[mie] = &riscv_hart_m_p::write_ie; csr_rd_cb[mhartid] = &riscv_hart_m_p::read_hartid; + // common regs + const std::array addrs{{mepc, mtvec, mscratch, mcause, mtval, mscratch}}; + for(auto addr: addrs) { + csr_rd_cb[addr] = &riscv_hart_m_p::read_reg; + csr_wr_cb[addr] = &riscv_hart_m_p::write_reg; + } } template std::pair riscv_hart_m_p::load_file(std::string name, int type) { @@ -664,32 +676,35 @@ iss::status riscv_hart_m_p::write(const address_type type, const access_ty 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) 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()) { - val = csr[addr & csr.page_addr_mask]; - return iss::Ok; - } - rd_csr_f f = it->second; - if (f == nullptr) throw illegal_instruction_fault(this->fault_data); - return (this->*f)(addr, val); + 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; auto req_priv_lvl = (addr >> 8) & 0x3; - if (this->reg.PRIV < req_priv_lvl) + if (this->reg.PRIV < req_priv_lvl) // not having required privileges throw illegal_instruction_fault(this->fault_data); - if((addr&0xc00)==0xc00) + 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()) { - csr[addr & csr.page_addr_mask] = val; - return iss::Ok; - } - wr_csr_f f = it->second; - if (f == nullptr) throw illegal_instruction_fault(this->fault_data); - return (this->*f)(addr, val); + 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_reg(unsigned addr, reg_t &val) { + val = csr[addr]; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_reg(unsigned addr, reg_t val) { + csr[addr] = val; + return iss::Ok; } template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { @@ -931,6 +946,7 @@ template uint64_t riscv_hart_m_p::enter_trap(uint64_t flag } template uint64_t riscv_hart_m_p::leave_trap(uint64_t flags) { + /* TODO: configurable support of User mode auto cur_priv = this->reg.PRIV; auto inst_priv = flags & 0x3; auto status = state.mstatus; @@ -943,8 +959,7 @@ template uint64_t riscv_hart_m_p::leave_trap(uint64_t flag state.mstatus.MIE = state.mstatus.MPIE; } else { CLOG(ERROR, disass) << "Unsupported mode:" << inst_priv; - } - + }*/ // sets the pc to the value stored in the x epc register. this->reg.NEXT_PC = csr[mepc]; CLOG(INFO, disass) << "Executing xRET"; diff --git a/incl/iss/arch/tgf_c.h b/incl/iss/arch/tgf_c.h index 4d3a334..44ad849 100644 --- a/incl/iss/arch/tgf_c.h +++ b/incl/iss/arch/tgf_c.h @@ -53,7 +53,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"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"}}; - enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000000000001000100000100, PGSIZE=0x1000, PGMASK=0b111111111111, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; + enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b01000000000000000001000100000100, PGSIZE=0x1000, PGMASK=0b111111111111, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, eei_aligned_addresses=1, MUL_LEN=64}; constexpr static unsigned FP_REGS_SIZE = 0; @@ -78,8 +78,7 @@ template <> struct traits { {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,64}}; 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}}; + {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}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); diff --git a/src/vm/interp/vm_tgf_b.cpp b/src/vm/interp/vm_tgf_b.cpp index e3e2571..47cc2c3 100644 --- a/src/vm/interp/vm_tgf_b.cpp +++ b/src/vm/interp/vm_tgf_b.cpp @@ -85,7 +85,7 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} - virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; + virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; // some compile time constants // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; @@ -2055,14 +2055,14 @@ vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) } template -typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { +typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; const typename traits::addr_t upper_bits = ~traits::PGMASK; code_word_t insn = 0; auto *const data = (uint8_t *)&insn; auto pc=start; - while(pred){ + while(pred(pc)){ auto paddr = this->core.v2p(pc); if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary if (this->core.read(paddr, 2, data) != iss::Ok) throw trap_access(TRAP_ID, pc.val); diff --git a/src/vm/interp/vm_tgf_c.cpp b/src/vm/interp/vm_tgf_c.cpp index 9497faa..1954fe5 100644 --- a/src/vm/interp/vm_tgf_c.cpp +++ b/src/vm/interp/vm_tgf_c.cpp @@ -85,7 +85,7 @@ protected: inline const char *name(size_t index){return traits::reg_aliases.at(index);} - virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; + virt_addr_t execute_inst(virt_addr_t start, std::function pred) override; // some compile time constants // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; @@ -139,19 +139,19 @@ protected: return lut_val; } - void raise(uint16_t trap_id, uint16_t cause){ + 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->template get_reg(traits::NEXT_PC) = std::numeric_limits::max(); } - void leave(unsigned lvl){ + inline void leave(unsigned lvl){ this->core.leave_trap(lvl); auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); this->template get_reg(traits::NEXT_PC) = pc_val; } - void wait(unsigned type){ + inline void wait(unsigned type){ this->core.wait_until(type); } @@ -180,17 +180,17 @@ private: const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI */ - {32, 0b0000000000000000000000000110111, 0b0000000000000000000000000111111, &this_class::__lui}, + {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, /* instruction AUIPC */ - {32, 0b000000000000000000000000010111, 0b000000000000000000000000011111, &this_class::__auipc}, + {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, /* instruction JAL */ {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, /* instruction JALR */ - {32, 0b000000000000000000000001100111, 0b000000000000000001000001111111, &this_class::__jalr}, + {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, /* instruction BEQ */ - {32, 0b000000000000000000000001100011, 0b000000000000000001000001111111, &this_class::__beq}, + {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, /* instruction BNE */ - {32, 0b000000000000000001000001100011, 0b000000000000000001000001111111, &this_class::__bne}, + {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, /* instruction BLT */ {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, /* instruction BGE */ @@ -200,83 +200,83 @@ private: /* instruction BGEU */ {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, /* instruction LB */ - {32, 0b0000000000000000000000011, 0b0000000000000000010000011, &this_class::__lb}, + {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, /* instruction LH */ - {32, 0b0000000000000000010000011, 0b0000000000000000010000011, &this_class::__lh}, + {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, /* instruction LW */ - {32, 0b00000000000000000100000011, 0b00000000000000000110000011, &this_class::__lw}, + {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, /* instruction LBU */ - {32, 0b000000000000000001000000011, 0b000000000000000001110000011, &this_class::__lbu}, + {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, /* instruction LHU */ - {32, 0b000000000000000001010000011, 0b000000000000000001110000011, &this_class::__lhu}, + {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, /* instruction SB */ - {32, 0b00000000000000000000000100011, 0b00000000000000000100000111111, &this_class::__sb}, + {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, /* instruction SH */ - {32, 0b00000000000000000100000100011, 0b00000000000000000100000111111, &this_class::__sh}, + {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, /* instruction SW */ - {32, 0b000000000000000001000000100011, 0b000000000000000001100000111111, &this_class::__sw}, + {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, /* instruction ADDI */ - {32, 0b0000000000000000000000010011, 0b0000000000000000010000011111, &this_class::__addi}, + {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, /* instruction SLTI */ - {32, 0b00000000000000000100000010011, 0b00000000000000000110000011111, &this_class::__slti}, + {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, /* instruction SLTIU */ - {32, 0b00000000000000000110000010011, 0b00000000000000000110000011111, &this_class::__sltiu}, + {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, /* instruction XORI */ - {32, 0b000000000000000001000000010011, 0b000000000000000001110000011111, &this_class::__xori}, + {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, /* instruction ORI */ - {32, 0b000000000000000001100000010011, 0b000000000000000001110000011111, &this_class::__ori}, + {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, /* instruction ANDI */ - {32, 0b000000000000000001110000010011, 0b000000000000000001110000011111, &this_class::__andi}, + {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, /* instruction SLLI */ - {32, 0b0000000000010000010011, 0b1000000000010000011111, &this_class::__slli}, + {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, /* instruction SRLI */ - {32, 0b000000000001010000010011, 0b100000000001110000011111, &this_class::__srli}, + {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, /* instruction SRAI */ - {32, 0b10000000000000001010000010011, 0b11111100000000001110000011111, &this_class::__srai}, + {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, /* instruction ADD */ - {32, 0b00000000000000000110011, 0b10000000000100000111111, &this_class::__add}, + {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, /* instruction SUB */ - {32, 0b1000000000000000000000110011, 0b1111110000000000100000111111, &this_class::__sub}, + {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, /* instruction SLL */ - {32, 0b00000000000100000110011, 0b10000000000100000111111, &this_class::__sll}, + {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, /* instruction SLT */ - {32, 0b000000000001000000110011, 0b100000000001100000111111, &this_class::__slt}, + {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, /* instruction SLTU */ - {32, 0b000000000001100000110011, 0b100000000001100000111111, &this_class::__sltu}, + {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, /* instruction XOR */ - {32, 0b0000000000010000000110011, 0b1000000000011100000111111, &this_class::__xor}, + {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, /* instruction SRL */ - {32, 0b0000000000010100000110011, 0b1000000000011100000111111, &this_class::__srl}, + {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, /* instruction SRA */ - {32, 0b100000000000000010100000110011, 0b111111000000000011100000111111, &this_class::__sra}, + {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, /* instruction OR */ - {32, 0b0000000000011000000110011, 0b1000000000011100000111111, &this_class::__or}, + {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, /* instruction AND */ - {32, 0b0000000000011100000110011, 0b1000000000011100000111111, &this_class::__and}, + {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, /* instruction FENCE */ - {32, 0b000000000000000000001111, 0b100000000000001000001111, &this_class::__fence}, + {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, /* instruction FENCE_I */ - {32, 0b000000000000000001000001111, 0b000000000000000001000001111, &this_class::__fence_i}, + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, /* instruction ECALL */ - {32, 0b00001110011, 0b11111111111, &this_class::__ecall}, + {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, /* instruction EBREAK */ - {32, 0b10001110011, 0b11111111111, &this_class::__ebreak}, + {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, /* instruction URET */ - {32, 0b0100001110011, 0b1111111111111, &this_class::__uret}, + {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, /* instruction SRET */ - {32, 0b1000100001110011, 0b1111111111111111, &this_class::__sret}, + {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, /* instruction MRET */ - {32, 0b11000100001110011, 0b11111111111111111, &this_class::__mret}, + {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, /* instruction WFI */ - {32, 0b10001010001110011, 0b11111111111111111, &this_class::__wfi}, + {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, /* instruction SFENCE_VMA */ - {32, 0b10010000000000001110011, 0b11110000000000111111111, &this_class::__sfence_vma}, + {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, /* instruction CSRRW */ - {32, 0b000000000000000001000001110011, 0b000000000000000001000001111111, &this_class::__csrrw}, + {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, /* instruction CSRRS */ - {32, 0b0000000000000000010000001110011, 0b0000000000000000011000001111111, &this_class::__csrrs}, + {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, /* instruction CSRRC */ - {32, 0b0000000000000000011000001110011, 0b0000000000000000011000001111111, &this_class::__csrrc}, + {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, /* instruction CSRRWI */ {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, /* instruction CSRRSI */ @@ -284,77 +284,77 @@ private: /* instruction CSRRCI */ {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, /* instruction MUL */ - {32, 0b10000000000000000110011, 0b10000000000100000111111, &this_class::__mul}, + {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, /* instruction MULH */ - {32, 0b10000000000100000110011, 0b10000000000100000111111, &this_class::__mulh}, + {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, /* instruction MULHSU */ - {32, 0b100000000001000000110011, 0b100000000001100000111111, &this_class::__mulhsu}, + {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, /* instruction MULHU */ - {32, 0b100000000001100000110011, 0b100000000001100000111111, &this_class::__mulhu}, + {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, /* instruction DIV */ - {32, 0b1000000000010000000110011, 0b1000000000011100000111111, &this_class::__div}, + {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, /* instruction DIVU */ - {32, 0b1000000000010100000110011, 0b1000000000011100000111111, &this_class::__divu}, + {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, /* instruction REM */ - {32, 0b1000000000011000000110011, 0b1000000000011100000111111, &this_class::__rem}, + {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, /* instruction REMU */ - {32, 0b1000000000011100000110011, 0b1000000000011100000111111, &this_class::__remu}, + {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, /* instruction CADDI4SPN */ - {16, 0b0000000000000, 0b1000000000001, &this_class::__caddi4spn}, + {16, 0b0000000000000000, 0b1110000000000011, &this_class::__caddi4spn}, /* instruction CLW */ - {16, 0b10000000000000, 0b11000000000001, &this_class::__clw}, + {16, 0b0100000000000000, 0b1110000000000011, &this_class::__clw}, /* instruction CSW */ - {16, 0b110000000000000, 0b111000000000001, &this_class::__csw}, + {16, 0b1100000000000000, 0b1110000000000011, &this_class::__csw}, /* instruction CADDI */ - {16, 0b0000000000001, 0b1000000000001, &this_class::__caddi}, + {16, 0b0000000000000001, 0b1110000000000011, &this_class::__caddi}, /* instruction CNOP */ - {16, 0b00001, 0b11111, &this_class::__cnop}, + {16, 0b0000000000000001, 0b1110111110000011, &this_class::__cnop}, /* instruction CJAL */ - {16, 0b1000000000001, 0b1000000000001, &this_class::__cjal}, + {16, 0b0010000000000001, 0b1110000000000011, &this_class::__cjal}, /* instruction CLI */ - {16, 0b10000000000001, 0b11000000000001, &this_class::__cli}, + {16, 0b0100000000000001, 0b1110000000000011, &this_class::__cli}, /* instruction CLUI */ - {16, 0b11000000000001, 0b11000000000001, &this_class::__clui}, + {16, 0b0110000000000001, 0b1110000000000011, &this_class::__clui}, /* instruction CADDI16SP */ - {16, 0b11010000001, 0b11011000001, &this_class::__caddi16sp}, + {16, 0b0110000100000001, 0b1110111110000011, &this_class::__caddi16sp}, /* instruction CSRLI */ - {16, 0b10000000000001, 0b11111000000001, &this_class::__csrli}, + {16, 0b1000000000000001, 0b1111110000000011, &this_class::__csrli}, /* instruction CSRAI */ - {16, 0b10001000000001, 0b11111000000001, &this_class::__csrai}, + {16, 0b1000010000000001, 0b1111110000000011, &this_class::__csrai}, /* instruction CANDI */ - {16, 0b100010000000001, 0b111011000000001, &this_class::__candi}, + {16, 0b1000100000000001, 0b1110110000000011, &this_class::__candi}, /* instruction CSUB */ - {16, 0b10001100000001, 0b11111100010001, &this_class::__csub}, + {16, 0b1000110000000001, 0b1111110001100011, &this_class::__csub}, /* instruction CXOR */ - {16, 0b10001100010001, 0b11111100010001, &this_class::__cxor}, + {16, 0b1000110000100001, 0b1111110001100011, &this_class::__cxor}, /* instruction COR */ - {16, 0b100011000100001, 0b111111000110001, &this_class::__cor}, + {16, 0b1000110001000001, 0b1111110001100011, &this_class::__cor}, /* instruction CAND */ - {16, 0b100011000110001, 0b111111000110001, &this_class::__cand}, + {16, 0b1000110001100001, 0b1111110001100011, &this_class::__cand}, /* instruction CJ */ - {16, 0b101000000000001, 0b111000000000001, &this_class::__cj}, + {16, 0b1010000000000001, 0b1110000000000011, &this_class::__cj}, /* instruction CBEQZ */ - {16, 0b110000000000001, 0b111000000000001, &this_class::__cbeqz}, + {16, 0b1100000000000001, 0b1110000000000011, &this_class::__cbeqz}, /* instruction CBNEZ */ - {16, 0b111000000000001, 0b111000000000001, &this_class::__cbnez}, + {16, 0b1110000000000001, 0b1110000000000011, &this_class::__cbnez}, /* instruction CSLLI */ - {16, 0b00000000000010, 0b11000000000011, &this_class::__cslli}, + {16, 0b0000000000000010, 0b1111000000000011, &this_class::__cslli}, /* instruction CLWSP */ - {16, 0b100000000000010, 0b110000000000011, &this_class::__clwsp}, + {16, 0b0100000000000010, 0b1110000000000011, &this_class::__clwsp}, /* instruction CMV */ {16, 0b1000000000000010, 0b1111000000000011, &this_class::__cmv}, /* instruction CJR */ - {16, 0b100000000010, 0b111100000111, &this_class::__cjr}, + {16, 0b1000000000000010, 0b1111000001111111, &this_class::__cjr}, /* instruction CADD */ {16, 0b1001000000000010, 0b1111000000000011, &this_class::__cadd}, /* instruction CJALR */ - {16, 0b100100000010, 0b111100000111, &this_class::__cjalr}, + {16, 0b1001000000000010, 0b1111000001111111, &this_class::__cjalr}, /* instruction CEBREAK */ - {16, 0b10010010, 0b11111111, &this_class::__cebreak}, + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__cebreak}, /* instruction CSWSP */ {16, 0b1100000000000010, 0b1110000000000011, &this_class::__cswsp}, /* instruction DII */ - {16, 0b00000, 0b11111, &this_class::__dii}, + {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, }}; /* instruction definitions */ @@ -381,12 +381,12 @@ private: if(rd != 0) *(X+rd) = (int32_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 0); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -413,12 +413,12 @@ private: if(rd != 0) *(X+rd) = *PC + (int32_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 1); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -448,12 +448,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 2); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -485,12 +485,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 3); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -518,12 +518,12 @@ private: if(*(X+rs1) == *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 4); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -551,12 +551,12 @@ private: if(*(X+rs1) != *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 5); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -584,12 +584,12 @@ private: if(*(X+rs1) < *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 6); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -617,12 +617,12 @@ private: if(*(X+rs1) >= *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 7); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -650,12 +650,12 @@ private: if(*(X+rs1) < *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 8); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -683,12 +683,12 @@ private: if(*(X+rs1) >= *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 9); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -713,15 +713,18 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - if(rd != 0) *(X+rd) = readSpace1(traits::MEM, *(X+rs1) + (int16_t)imm); + { + int8_t res = (int8_t)readSpace1(traits::MEM, *(X+rs1) + (int16_t)imm); + if(rd != 0) *(X+rd) = res; + } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 10); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -746,15 +749,22 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - if(rd != 0) *(X+rd) = (int16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)imm); + { + uint32_t load_address = *(X+rs1) + (int16_t)imm; + if(traits::eei_aligned_addresses && (load_address & 0x1)) raise(0, 4); + else { + int16_t res = (int16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)imm); + if(rd != 0) *(X+rd) = res; + } + } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 11); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -779,15 +789,22 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - if(rd != 0) *(X+rd) = (uint32_t)readSpace4(traits::MEM, *(X+rs1) + (int16_t)imm); + { + uint32_t load_address = *(X+rs1) + (int16_t)imm; + if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 4); + else { + int32_t res = (int32_t)readSpace4(traits::MEM, *(X+rs1) + (int16_t)imm); + if(rd != 0) *(X+rd) = (uint32_t)res; + } + } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 12); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -812,15 +829,18 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - if(rd != 0) *(X+rd) = (uint8_t)readSpace1(traits::MEM, *(X+rs1) + (int16_t)imm); + { + uint8_t res = (uint8_t)readSpace1(traits::MEM, *(X+rs1) + (int16_t)imm); + if(rd != 0) *(X+rd) = res; + } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 13); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -845,15 +865,22 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - if(rd != 0) *(X+rd) = (uint16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)imm); + { + uint32_t load_address = *(X+rs1) + (int16_t)imm; + if(traits::eei_aligned_addresses && (load_address & 0x1)) raise(0, 4); + else { + uint16_t res = (uint16_t)readSpace2(traits::MEM, *(X+rs1) + (int16_t)imm); + if(rd != 0) *(X+rd) = res; + } + } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 14); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -881,12 +908,12 @@ private: writeSpace1(traits::MEM, *(X+rs1) + (int16_t)imm, (int8_t)*(X+rs2)); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 15); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -911,7 +938,11 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - writeSpace2(traits::MEM, *(X+rs1) + (int16_t)imm, (int16_t)*(X+rs2)); + { + uint32_t store_address = *(X+rs1) + (int16_t)imm; + if(traits::eei_aligned_addresses && (store_address & 0x1)) raise(0, 6); + else writeSpace2(traits::MEM, store_address, (int16_t)*(X+rs2)); + } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 16); auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); @@ -944,15 +975,19 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - writeSpace4(traits::MEM, *(X+rs1) + (int16_t)imm, *(X+rs2)); + { + uint32_t store_address = *(X+rs1) + (int16_t)imm; + if(traits::eei_aligned_addresses && (store_address & 0x3)) raise(0, 6); + else writeSpace4(traits::MEM, store_address, *(X+rs2)); + } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 17); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -980,12 +1015,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) + (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 18); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1013,12 +1048,12 @@ private: if(rd != 0) *(X+rd) = (int32_t)*(X+rs1) < (int16_t)imm? 1 : 0; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 19); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1046,12 +1081,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) < imm? 1 : 0; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 20); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1079,12 +1114,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) ^ (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 21); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1112,12 +1147,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) | (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 22); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1145,12 +1180,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) & (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 23); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1176,19 +1211,19 @@ private: *NEXT_PC = *PC + 4; // execute instruction if(shamt > 31) { - (0, 0); + raise(0, 0); } else { if(rd != 0) *(X+rd) = *(X+rs1) << shamt; } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 24); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1214,19 +1249,19 @@ private: *NEXT_PC = *PC + 4; // execute instruction if(shamt > 31) { - (0, 0); + raise(0, 0); } else { if(rd != 0) *(X+rd) = ((uint8_t)*(X+rs1)) >> shamt; } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 25); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1252,19 +1287,19 @@ private: *NEXT_PC = *PC + 4; // execute instruction if(shamt > 31) { - (0, 0); + raise(0, 0); } else { if(rd != 0) *(X+rd) = *(X+rs1) >> shamt; } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 26); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1292,12 +1327,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) + *(X+rs2); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 27); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1325,12 +1360,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) - *(X+rs2); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 28); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1358,12 +1393,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 29); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1391,12 +1426,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) < *(X+rs2)? 1 : 0; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 30); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1424,12 +1459,12 @@ private: if(rd != 0) *(X+rd) = (uint32_t)*(X+rs1) < (uint32_t)*(X+rs2)? 1 : 0; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 31); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1457,12 +1492,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) ^ *(X+rs2); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 32); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1490,12 +1525,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) << (*(X+rs2) & (traits::XLEN - 1)); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 33); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1523,12 +1558,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) >> (*(X+rs2) & (traits::XLEN - 1)); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 34); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1556,12 +1591,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) | *(X+rs2); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 35); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1589,12 +1624,12 @@ private: if(rd != 0) *(X+rd) = *(X+rs1) & *(X+rs2); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 36); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1623,12 +1658,12 @@ private: writeSpace1(traits::FENCE, traits::fence, pred << 4 | succ); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 37); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1656,12 +1691,12 @@ private: writeSpace2(traits::FENCE, traits::fencei, imm); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 38); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1680,15 +1715,15 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - (0, 11); + raise(0, 11); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 39); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1707,15 +1742,15 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - (0, 3); + raise(0, 3); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 40); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1734,15 +1769,15 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - (0); + leave(0); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 41); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1761,15 +1796,15 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - (1); + leave(1); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 42); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1788,15 +1823,15 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - (3); + leave(3); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 43); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1815,15 +1850,15 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 4; // execute instruction - (1); + wait(1); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 44); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1853,12 +1888,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 45); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1896,12 +1931,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 46); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1934,12 +1969,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 47); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -1972,12 +2007,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 48); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2008,12 +2043,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 49); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2045,12 +2080,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 50); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2082,12 +2117,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 51); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2120,12 +2155,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 52); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2158,12 +2193,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 53); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2196,12 +2231,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 54); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2234,12 +2269,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 55); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2276,12 +2311,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 56); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2314,12 +2349,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 57); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2356,12 +2391,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 58); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2394,12 +2429,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 59); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2424,17 +2459,17 @@ private: *NEXT_PC = *PC + 2; // execute instruction { - if(imm == 0) (0, 2); + if(imm == 0) raise(0, 2); *(X+(rd + 8)) = *(X+2) + imm; } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 60); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2460,17 +2495,18 @@ private: *NEXT_PC = *PC + 2; // execute instruction { - uint32_t offs = *(X+(rs1 + 8)) + uimm; - *(X+(rd + 8)) = (int32_t)readSpace4(traits::MEM, offs); + uint32_t load_address = *(X+(rs1 + 8)) + uimm; + if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 4); + else *(X+(rd + 8)) = (int32_t)readSpace4(traits::MEM, load_address); } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 61); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2496,17 +2532,18 @@ private: *NEXT_PC = *PC + 2; // execute instruction { - uint8_t offs = *(X+(rs1 + 8)) + uimm; - writeSpace4(traits::MEM, offs, *(X+(rs2 + 8))); + uint32_t load_address = *(X+(rs1 + 8)) + uimm; + if(traits::eei_aligned_addresses && (load_address & 0x3)) raise(0, 6); + else writeSpace4(traits::MEM, load_address, *(X+(rs2 + 8))); } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 62); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2533,12 +2570,12 @@ private: *(X+rs1) = *(X+rs1) + (int8_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 63); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2546,6 +2583,7 @@ private: compile_ret_t __cnop(virt_addr_t& pc, code_word_t instr){ // pre execution stuff this->do_sync(PRE_SYNC, 64); + 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"); @@ -2561,12 +2599,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 64); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2591,16 +2629,16 @@ private: // execute instruction { *(X+1) = *PC + 2; - pc_assign(*NEXT_PC) = (int8_t)*PC + (int16_t)imm; + pc_assign(*NEXT_PC) = *PC + (int16_t)imm; } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 65); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2625,17 +2663,16 @@ private: *NEXT_PC = *PC + 2; // execute instruction { - if(rd == 0) (0, 2); - *(X+rd) = (int8_t)imm; + if(rd == 0) *(X+rd) = (int8_t)imm; } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 66); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2660,18 +2697,18 @@ private: *NEXT_PC = *PC + 2; // execute instruction { - if(rd == 0) (0, 2); - if(imm == 0) (0, 2); + if(rd == 0) raise(0, 2); + if(imm == 0) raise(0, 2); *(X+rd) = (int32_t)imm; } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 67); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2679,12 +2716,13 @@ private: compile_ret_t __caddi16sp(virt_addr_t& pc, code_word_t instr){ // pre execution stuff this->do_sync(PRE_SYNC, 68); - uint16_t imm = ((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)); + 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)); + uint16_t imm = ((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", "caddi16sp"), - fmt::arg("imm", imm)); + fmt::arg("imm", nzimm)); this->core.disass_output(pc.val, mnemonic); } @@ -2694,15 +2732,16 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 2; // execute instruction - *(X+2) = *(X+2) + (int16_t)imm; + if(nzimm) *(X+2) = *(X+2) + (int16_t)nzimm; + else raise(0, 2); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 68); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2732,12 +2771,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 69); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2761,18 +2800,22 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 2; // execute instruction - { + if(shamt) { uint8_t rs1_idx = rs1 + 8; - *(X+rs1_idx) = ((int8_t)*(X+rs1_idx)) >> shamt; + *(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; } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 70); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2802,12 +2845,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 71); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2837,12 +2880,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 72); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2872,12 +2915,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 73); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2907,12 +2950,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 74); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2942,12 +2985,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 75); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -2973,12 +3016,12 @@ private: pc_assign(*NEXT_PC) = *PC + (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 76); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3005,12 +3048,12 @@ private: if(*(X+(rs1 + 8)) == 0) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 77); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3037,12 +3080,12 @@ private: if(*(X+(rs1 + 8)) != 0) pc_assign(*NEXT_PC) = *PC + (int16_t)imm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 78); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3050,13 +3093,13 @@ private: compile_ret_t __cslli(virt_addr_t& pc, code_word_t instr){ // pre execution stuff this->do_sync(PRE_SYNC, 79); - uint8_t shamt = ((bit_sub<2,5>(instr))); + 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", "cslli"), - fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt)); + "{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "cslli"), + fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm)); this->core.disass_output(pc.val, mnemonic); } @@ -3066,18 +3109,15 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 2; // execute instruction - { - if(rs1 == 0) (0, 2); - *(X+rs1) = *(X+rs1) << shamt; - } + if(nzuimm) *(X+rs1) = *(X+rs1) << nzuimm; // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 79); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3101,18 +3141,19 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 2; // execute instruction - { + if(rd) { uint8_t offs = *(X+2) + uimm; *(X+rd) = (int32_t)readSpace4(traits::MEM, offs); } + else raise(0, 2); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 80); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3139,12 +3180,12 @@ private: *(X+rd) = *(X+rs2); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 81); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3167,15 +3208,16 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 2; // execute instruction - pc_assign(*NEXT_PC) = *(X+rs1); + if(rs1) pc_assign(*NEXT_PC) = *(X+rs1); + else raise(0, 2); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 82); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3202,12 +3244,12 @@ private: *(X+rd) = *(X+rd) + *(X+rs2); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 83); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3236,12 +3278,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 84); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3260,15 +3302,15 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 2; // execute instruction - (0, 3); + raise(0, 3); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 85); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3298,12 +3340,12 @@ private: } // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 86); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3322,15 +3364,15 @@ private: uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); *NEXT_PC = *PC + 2; // execute instruction - (0, 2); + raise(0, 2); // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 87); - auto& trap_state = super::template get_reg(arch::traits::TRAP_STATE); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); // trap check - if(trap_state!=0){ - super::core.enter_trap(trap_state, pc.val); + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); } - pc.val=super::template get_reg(arch::traits::NEXT_PC); + pc.val=*NEXT_PC; return pc; } @@ -3338,7 +3380,19 @@ private: * end opcode definitions ****************************************************************************/ compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr) { - pc = pc + ((instr & 3) == 3 ? 4 : 2); + this->do_sync(PRE_SYNC, static_cast(arch::traits::opcode_e::MAX_OPCODE)); + uint32_t* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + uint32_t* NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *NEXT_PC = *PC + ((instr & 3) == 3 ? 4 : 2); + raise(0, 11); + // post execution stuff + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, static_cast(arch::traits::opcode_e::MAX_OPCODE)); + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + // trap check + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val); + } + pc.val=*NEXT_PC; return pc; } @@ -3377,20 +3431,19 @@ vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) } template -typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { +typename vm_base::virt_addr_t vm_impl::execute_inst(virt_addr_t start, std::function pred) { // we fetch at max 4 byte, alignment is 2 enum {TRAP_ID=1<<16}; code_word_t insn = 0; auto *const data = (uint8_t *)&insn; auto pc=start; - while(pred()){ + while(pred(pc)){ auto res = fetch_ins(pc, data); if(res!=iss::Ok){ auto new_pc = super::core.enter_trap(TRAP_ID, pc.val); res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data); if(res!=iss::Ok) throw simulation_stopped(0); } - if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' auto lut_val = extract_fields(insn); auto f = qlut[insn & 0x3][lut_val]; if (!f)