Compare commits
2 Commits
develop
...
featture/i
Author | SHA1 | Date | |
---|---|---|---|
071cb4fdac | |||
dd937710a7 |
@ -12,6 +12,7 @@ include(flink)
|
||||
find_package(elfio QUIET)
|
||||
find_package(jsoncpp)
|
||||
find_package(Boost COMPONENTS coroutine REQUIRED)
|
||||
find_package(absl REQUIRED)
|
||||
|
||||
add_subdirectory(softfloat)
|
||||
|
||||
@ -104,7 +105,7 @@ if(NOT(DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND))
|
||||
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine abseil::abseil)
|
||||
|
||||
if(TARGET yaml-cpp::yaml-cpp)
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_PLUGINS)
|
||||
|
@ -962,20 +962,6 @@ if(vector != null) {%>
|
||||
throw new std::runtime_error("Unsupported sew bit value");
|
||||
}
|
||||
}
|
||||
void vector_unary_op(uint8_t* V, uint8_t unary_op, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t sew_val){
|
||||
switch(sew_val){
|
||||
case 0b000:
|
||||
return softvector::vector_unary_op<${vlen}, uint8_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
|
||||
case 0b001:
|
||||
return softvector::vector_unary_op<${vlen}, uint16_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
|
||||
case 0b010:
|
||||
return softvector::vector_unary_op<${vlen}, uint32_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
|
||||
case 0b011:
|
||||
return softvector::vector_unary_op<${vlen}, uint64_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
|
||||
default:
|
||||
throw new std::runtime_error("Unsupported sew_val");
|
||||
}
|
||||
}
|
||||
<%}%>
|
||||
uint64_t fetch_count{0};
|
||||
uint64_t tval{0};
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include "mstatus.h"
|
||||
#include "util/delegate.h"
|
||||
#include <absl/container/flat_hash_map.h>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <elfio/elfio.hpp>
|
||||
@ -259,8 +260,8 @@ template <typename WORD_TYPE> struct priv_if {
|
||||
std::function<iss::status(unsigned, WORD_TYPE)> write_csr;
|
||||
std::function<iss::status(uint8_t const*)> exec_htif;
|
||||
std::function<void(uint16_t, uint16_t, WORD_TYPE)> raise_trap; // trap_id, cause, fault_data
|
||||
std::unordered_map<unsigned, rd_csr_f>& csr_rd_cb;
|
||||
std::unordered_map<unsigned, wr_csr_f>& csr_wr_cb;
|
||||
absl::flat_hash_map<unsigned, rd_csr_f>& csr_rd_cb;
|
||||
absl::flat_hash_map<unsigned, wr_csr_f>& csr_wr_cb;
|
||||
hart_state<WORD_TYPE>& state;
|
||||
uint8_t& PRIV;
|
||||
WORD_TYPE& PC;
|
||||
@ -775,7 +776,7 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
|
||||
this->fault_data = fault_data;
|
||||
},
|
||||
.csr_rd_cb{this->csr_rd_cb},
|
||||
.csr_wr_cb{csr_wr_cb},
|
||||
.csr_wr_cb{this->csr_wr_cb},
|
||||
.state{this->state},
|
||||
.PRIV{this->reg.PRIV},
|
||||
.PC{this->reg.PC},
|
||||
@ -893,8 +894,8 @@ protected:
|
||||
using csr_page_type = typename csr_type::page_type;
|
||||
csr_type csr;
|
||||
|
||||
std::unordered_map<unsigned, rd_csr_f> csr_rd_cb;
|
||||
std::unordered_map<unsigned, wr_csr_f> csr_wr_cb;
|
||||
absl::flat_hash_map<unsigned, rd_csr_f> csr_rd_cb;
|
||||
absl::flat_hash_map<unsigned, wr_csr_f> csr_wr_cb;
|
||||
|
||||
reg_t mhartid_reg{0x0};
|
||||
uint64_t mcycle_csr{0};
|
||||
|
@ -134,7 +134,7 @@ protected:
|
||||
|
||||
hart_state<reg_t> state;
|
||||
|
||||
std::unordered_map<uint64_t, uint8_t> atomic_reservation;
|
||||
absl::flat_hash_map<uint64_t, uint8_t> atomic_reservation;
|
||||
|
||||
iss::status read_status(unsigned addr, reg_t& val);
|
||||
iss::status write_status(unsigned addr, reg_t val);
|
||||
|
@ -48,9 +48,9 @@
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
#define FMT_HEADER_ONLY
|
||||
#endif
|
||||
#include <fmt/format.h>
|
||||
#include <iss/mem/memory_with_htif.h>
|
||||
#include <iss/mem/mmu.h>
|
||||
#include <fmt/format.h>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
|
||||
@ -150,7 +150,7 @@ protected:
|
||||
|
||||
hart_state<reg_t> state;
|
||||
|
||||
std::unordered_map<uint64_t, uint8_t> atomic_reservation;
|
||||
absl::flat_hash_map<uint64_t, uint8_t> atomic_reservation;
|
||||
|
||||
iss::status read_status(unsigned addr, reg_t& val);
|
||||
iss::status write_status(unsigned addr, reg_t val);
|
||||
|
@ -160,7 +160,7 @@ protected:
|
||||
|
||||
hart_state<reg_t> state;
|
||||
|
||||
std::unordered_map<uint64_t, uint8_t> atomic_reservation;
|
||||
absl::flat_hash_map<uint64_t, uint8_t> atomic_reservation;
|
||||
|
||||
iss::status read_status(unsigned addr, reg_t& val);
|
||||
iss::status write_status(unsigned addr, reg_t val);
|
||||
|
@ -32,9 +32,9 @@
|
||||
* eyck@minres.com - initial implementation
|
||||
******************************************************************************/
|
||||
|
||||
#include "memory_if.h"
|
||||
#include "iss/arch/riscv_hart_common.h"
|
||||
#include "iss/vm_types.h"
|
||||
#include "memory_if.h"
|
||||
#include <util/logging.h>
|
||||
|
||||
namespace iss {
|
||||
@ -238,7 +238,7 @@ private:
|
||||
|
||||
protected:
|
||||
reg_t satp;
|
||||
std::unordered_map<reg_t, uint64_t> ptw;
|
||||
absl::flat_hash_map<reg_t, uint64_t> ptw;
|
||||
std::array<vm_info, 2> vmt;
|
||||
std::array<address_type, 4> addr_mode;
|
||||
|
||||
|
@ -267,10 +267,7 @@ template <unsigned int BUSWIDTH> void core_complex<BUSWIDTH>::before_end_of_elab
|
||||
cpu = new core_wrapper(this);
|
||||
cpu->create_cpu(GET_PROP_VALUE(core_type), GET_PROP_VALUE(backend), GET_PROP_VALUE(gdb_server_port), GET_PROP_VALUE(mhartid));
|
||||
sc_assert(cpu->vm != nullptr);
|
||||
auto disass = GET_PROP_VALUE(enable_disass);
|
||||
if(disass && trc->m_db)
|
||||
SCCINFO(SCMOD)<<"Disasssembly will only be in transaction trace database!";
|
||||
cpu->vm->setDisassEnabled(disass || trc->m_db != nullptr);
|
||||
cpu->vm->setDisassEnabled(GET_PROP_VALUE(enable_disass) || trc->m_db != nullptr);
|
||||
if(GET_PROP_VALUE(plugins).length()) {
|
||||
auto p = util::split(GET_PROP_VALUE(plugins), ';');
|
||||
for(std::string const& opt_val : p) {
|
||||
|
@ -38,14 +38,17 @@
|
||||
#include <iss/iss.h>
|
||||
#include <iss/interp/vm_base.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
#include <util/logging.h>
|
||||
#include <boost/coroutine2/all.hpp>
|
||||
#include <functional>
|
||||
#include <exception>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iss/instruction_decoder.h>
|
||||
|
||||
#include <absl/container/flat_hash_map.h>
|
||||
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
#define FMT_HEADER_ONLY
|
||||
@ -255,6 +258,11 @@ private:
|
||||
return iss::Err;
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
struct translation_buffer {
|
||||
std::vector<std::tuple<opcode_e, uint64_t, uint32_t>> entries;
|
||||
} tb;
|
||||
absl::flat_hash_map<uint64_t, translation_buffer> tb_lut;
|
||||
};
|
||||
|
||||
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
|
||||
@ -312,27 +320,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto& instr = this->core.reg.instruction;
|
||||
// we fetch at max 4 byte, alignment is 2
|
||||
auto *const data = reinterpret_cast<uint8_t*>(&instr);
|
||||
|
||||
while(!this->core.should_stop() &&
|
||||
!(is_icount_limit_enabled(cond) && icount >= count_limit) &&
|
||||
!(is_fcount_limit_enabled(cond) && fetch_count >= count_limit)){
|
||||
if(this->debugging_enabled())
|
||||
this->tgt_adapter->check_continue(*PC);
|
||||
pc.val=*PC;
|
||||
if(fetch_ins(pc, data)!=iss::Ok){
|
||||
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, std::numeric_limits<unsigned>::max());
|
||||
process_spawn_blocks();
|
||||
if(this->sync_exec && POST_SYNC) this->do_sync(PRE_SYNC, std::numeric_limits<unsigned>::max());
|
||||
pc.val = super::core.enter_trap(arch::traits<ARCH>::RV_CAUSE_FETCH_ACCESS<<16, pc.val, 0);
|
||||
} else {
|
||||
if (is_jump_to_self_enabled(cond) &&
|
||||
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||
opcode_e inst_id = arch::traits<ARCH>::opcode_e::MAX_OPCODE;;
|
||||
if(inst_index <instr_descr.size())
|
||||
inst_id = instr_descr[inst_index].op;
|
||||
|
||||
// pre execution stuff
|
||||
auto exec = [this, PC, NEXT_PC](opcode_e inst_id, uint64_t pc, uint32_t instr) {
|
||||
// pre execution stuff
|
||||
this->core.reg.last_branch = 0;
|
||||
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id));
|
||||
try{
|
||||
@ -345,7 +334,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "lui"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -372,7 +361,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {imm:#08x}", fmt::arg("mnemonic", "auipc"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -399,7 +388,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {imm:#0x}", fmt::arg("mnemonic", "jal"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -436,7 +425,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {imm:#0x}", fmt::arg("mnemonic", "jalr"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -474,7 +463,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "beq"),
|
||||
fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -510,7 +499,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bne"),
|
||||
fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -546,7 +535,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "blt"),
|
||||
fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -582,7 +571,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bge"),
|
||||
fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -618,7 +607,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bltu"),
|
||||
fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -654,7 +643,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {rs2}, {imm:#0x}", fmt::arg("mnemonic", "bgeu"),
|
||||
fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -690,7 +679,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lb"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -722,7 +711,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lh"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -754,7 +743,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lw"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -786,7 +775,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lbu"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -818,7 +807,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {imm}({rs1})", fmt::arg("mnemonic", "lhu"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -850,7 +839,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sb"),
|
||||
fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -878,7 +867,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sh"),
|
||||
fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -906,7 +895,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs2}, {imm}({rs1})", fmt::arg("mnemonic", "sw"),
|
||||
fmt::arg("rs2", name(rs2)), fmt::arg("imm", imm), fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -934,7 +923,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "addi"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -962,7 +951,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "slti"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -990,7 +979,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "sltiu"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1018,7 +1007,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "xori"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1046,7 +1035,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "ori"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1074,7 +1063,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {imm}", fmt::arg("mnemonic", "andi"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1102,7 +1091,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "slli"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1130,7 +1119,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srli"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1158,7 +1147,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {shamt}", fmt::arg("mnemonic", "srai"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("shamt", shamt));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1186,7 +1175,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "add"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1214,7 +1203,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sub"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1242,7 +1231,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sll"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1270,7 +1259,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "slt"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1298,7 +1287,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sltu"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1326,7 +1315,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "xor"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1354,7 +1343,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "srl"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1382,7 +1371,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "sra"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1410,7 +1399,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "or"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1438,7 +1427,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "and"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1468,7 +1457,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {pred}, {succ} ({fm} , {rs1}, {rd})", fmt::arg("mnemonic", "fence"),
|
||||
fmt::arg("pred", pred), fmt::arg("succ", succ), fmt::arg("fm", fm), fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -1485,7 +1474,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
/* generate console output when executing the command */
|
||||
//No disass specified, using instruction name
|
||||
std::string mnemonic = "ecall";
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -1501,7 +1490,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
/* generate console output when executing the command */
|
||||
//No disass specified, using instruction name
|
||||
std::string mnemonic = "ebreak";
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -1517,7 +1506,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
/* generate console output when executing the command */
|
||||
//No disass specified, using instruction name
|
||||
std::string mnemonic = "mret";
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -1533,7 +1522,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
/* generate console output when executing the command */
|
||||
//No disass specified, using instruction name
|
||||
std::string mnemonic = "wfi";
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -1553,7 +1542,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrw"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1591,7 +1580,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrs"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1627,7 +1616,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {csr}, {rs1}", fmt::arg("mnemonic", "csrrc"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1663,7 +1652,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrwi"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1696,7 +1685,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrsi"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1731,7 +1720,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {csr}, {zimm:#0x}", fmt::arg("mnemonic", "csrrci"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("csr", csr), fmt::arg("zimm", zimm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1766,7 +1755,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"),
|
||||
fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -1787,7 +1776,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mul"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1816,7 +1805,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulh"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1845,7 +1834,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhsu"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1874,7 +1863,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "mulhu"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1903,7 +1892,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "div"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1944,7 +1933,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "divu"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -1979,7 +1968,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "rem"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2022,7 +2011,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs1}, {rs2}", fmt::arg("mnemonic", "remu"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs1", name(rs1)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2056,7 +2045,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.addi4spn"),
|
||||
fmt::arg("rd", name(8+rd)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2082,7 +2071,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.lw"),
|
||||
fmt::arg("rd", name(8+rd)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2106,7 +2095,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs2}, {uimm:#05x}({rs1})", fmt::arg("mnemonic", "c.sw"),
|
||||
fmt::arg("rs2", name(8+rs2)), fmt::arg("uimm", uimm), fmt::arg("rs1", name(8+rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2128,7 +2117,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.addi"),
|
||||
fmt::arg("rs1", name(rs1)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2153,7 +2142,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
/* generate console output when executing the command */
|
||||
//No disass specified, using instruction name
|
||||
std::string mnemonic = "c.nop";
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -2170,7 +2159,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.jal"),
|
||||
fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2192,7 +2181,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.li"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2219,7 +2208,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {imm:#05x}", fmt::arg("mnemonic", "c.lui"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2243,7 +2232,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {nzimm:#05x}", fmt::arg("mnemonic", "c.addi16sp"),
|
||||
fmt::arg("nzimm", nzimm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2266,7 +2255,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
/* generate console output when executing the command */
|
||||
//No disass specified, using instruction name
|
||||
std::string mnemonic = ".reserved_clui";
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -2285,7 +2274,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srli"),
|
||||
fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2305,7 +2294,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {shamt}", fmt::arg("mnemonic", "c.srai"),
|
||||
fmt::arg("rs1", name(8+rs1)), fmt::arg("shamt", shamt));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2332,7 +2321,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.andi"),
|
||||
fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2352,7 +2341,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.sub"),
|
||||
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2372,7 +2361,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.xor"),
|
||||
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2392,7 +2381,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.or"),
|
||||
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2412,7 +2401,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.and"),
|
||||
fmt::arg("rd", name(8+rd)), fmt::arg("rs2", name(8+rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2431,7 +2420,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {imm:#05x}", fmt::arg("mnemonic", "c.j"),
|
||||
fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -2451,7 +2440,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.beqz"),
|
||||
fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2474,7 +2463,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {imm:#05x}", fmt::arg("mnemonic", "c.bnez"),
|
||||
fmt::arg("rs1", name(8+rs1)), fmt::arg("imm", imm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2497,7 +2486,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}, {nzuimm}", fmt::arg("mnemonic", "c.slli"),
|
||||
fmt::arg("rs1", name(rs1)), fmt::arg("nzuimm", nzuimm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2524,7 +2513,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2552,7 +2541,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.mv"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2578,7 +2567,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jr"),
|
||||
fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2602,7 +2591,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
/* generate console output when executing the command */
|
||||
//No disass specified, using instruction name
|
||||
std::string mnemonic = ".reserved_cmv";
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -2621,7 +2610,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rd}, {rs2}", fmt::arg("mnemonic", "c.add"),
|
||||
fmt::arg("rd", name(rd)), fmt::arg("rs2", name(rs2)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2647,7 +2636,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs1}", fmt::arg("mnemonic", "c.jalr"),
|
||||
fmt::arg("rs1", name(rs1)));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2673,7 +2662,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
/* generate console output when executing the command */
|
||||
//No disass specified, using instruction name
|
||||
std::string mnemonic = "c.ebreak";
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -2692,7 +2681,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
auto mnemonic = fmt::format(
|
||||
"{mnemonic:10} {rs2}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.swsp"),
|
||||
fmt::arg("rs2", name(rs2)), fmt::arg("uimm", uimm));
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
auto* X = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::X0]);
|
||||
@ -2716,7 +2705,7 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
/* generate console output when executing the command */
|
||||
//No disass specified, using instruction name
|
||||
std::string mnemonic = "dii";
|
||||
this->core.disass_output(pc.val, mnemonic);
|
||||
this->core.disass_output(pc, mnemonic);
|
||||
}
|
||||
// used registers
|
||||
// calculate next pc value
|
||||
@ -2739,16 +2728,54 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
||||
// if(!this->core.reg.trap_state) // update trap state if there is a pending interrupt
|
||||
// this->core.reg.trap_state = this->core.reg.pending_trap;
|
||||
// trap check
|
||||
if(trap_state!=0){
|
||||
if(this->core.reg.trap_state!=0){
|
||||
//In case of Instruction address misaligned (cause = 0 and trapid = 0) need the targeted addr (in tval)
|
||||
auto mcause = (trap_state>>16) & 0xff;
|
||||
super::core.enter_trap(trap_state, pc.val, mcause ? instr:tval);
|
||||
auto mcause = (this->core.reg.trap_state>>16) & 0xff;
|
||||
super::core.enter_trap(this->core.reg.trap_state, pc, mcause ? instr:tval);
|
||||
} else {
|
||||
icount++;
|
||||
instret++;
|
||||
this->core.reg.icount++;
|
||||
this->core.reg.instret++;
|
||||
}
|
||||
*PC = *NEXT_PC;
|
||||
this->core.reg.trap_state = this->core.reg.pending_trap;
|
||||
|
||||
};
|
||||
while(!this->core.should_stop() &&
|
||||
!(is_icount_limit_enabled(cond) && icount >= count_limit) &&
|
||||
!(is_fcount_limit_enabled(cond) && fetch_count >= count_limit)){
|
||||
if(this->debugging_enabled())
|
||||
this->tgt_adapter->check_continue(*PC);
|
||||
pc.val=*PC;
|
||||
auto current_tb = tb_lut.find(pc.val);
|
||||
if(current_tb==tb_lut.end()) {
|
||||
auto res = tb_lut.insert(std::make_pair(pc.val,translation_buffer{}));
|
||||
if(!res.second)
|
||||
throw std::runtime_error("");
|
||||
current_tb=res.first;
|
||||
do {
|
||||
if(fetch_ins(pc, data)!=iss::Ok){
|
||||
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, std::numeric_limits<unsigned>::max());
|
||||
process_spawn_blocks();
|
||||
if(this->sync_exec && POST_SYNC) this->do_sync(PRE_SYNC, std::numeric_limits<unsigned>::max());
|
||||
pc.val = super::core.enter_trap(arch::traits<ARCH>::RV_CAUSE_FETCH_ACCESS<<16, pc.val, 0);
|
||||
break;
|
||||
} else {
|
||||
if (is_jump_to_self_enabled(cond) &&
|
||||
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||
opcode_e inst_id = arch::traits<ARCH>::opcode_e::MAX_OPCODE;;
|
||||
if(inst_index <instr_descr.size())
|
||||
inst_id = instr_descr[inst_index].op;
|
||||
if(is_jump_to_self_enabled(cond) &&
|
||||
inst_id==arch::traits<ARCH>::opcode_e::JAL && !bit_sub<7, 25>(instr) ||
|
||||
inst_id == arch::traits<ARCH>::opcode_e::C__J && !bit_sub<2, 11>(instr))
|
||||
throw simulation_stopped(0);
|
||||
exec(inst_id, pc.val, instr);
|
||||
}
|
||||
} while(this->core.reg.last_branch==0);
|
||||
} else {
|
||||
for(auto& e:current_tb->second.entries)
|
||||
exec(std::get<0>(e), std::get<1>(e), std::get<2>(e));
|
||||
}
|
||||
fetch_count++;
|
||||
cycle++;
|
||||
|
@ -34,7 +34,6 @@
|
||||
|
||||
#include "vector_functions.h"
|
||||
#include "iss/vm_types.h"
|
||||
#include "vm/aes_sbox.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
@ -99,309 +98,4 @@ vmask_view read_vmask(uint8_t* V, uint16_t VLEN, uint16_t elem_count, uint8_t re
|
||||
assert(mask_start + elem_count / 8 <= V + VLEN * RFS / 8);
|
||||
return {mask_start, elem_count};
|
||||
}
|
||||
uint8_t xt2(uint8_t x) { return (x << 1) ^ (bit_sub<7, 1>(x) ? 27 : 0); }
|
||||
|
||||
uint8_t xt3(uint8_t x) { return x ^ xt2(x); }
|
||||
|
||||
uint8_t gfmul(uint8_t x, uint8_t y) {
|
||||
return (bit_sub<0, 1>(y) ? x : 0) ^ (bit_sub<1, 1>(y) ? xt2(x) : 0) ^ (bit_sub<2, 1>(y) ? xt2(xt2(x)) : 0) ^
|
||||
(bit_sub<3, 1>(y) ? xt2(xt2(xt2(x))) : 0);
|
||||
}
|
||||
|
||||
uint32_t aes_mixcolumn_byte_fwd(uint8_t so) {
|
||||
return ((uint32_t)gfmul(so, 3) << 24) | ((uint32_t)so << 16) | ((uint32_t)so << 8) | gfmul(so, 2);
|
||||
}
|
||||
|
||||
uint32_t aes_mixcolumn_byte_inv(uint8_t so) {
|
||||
return ((uint32_t)gfmul(so, 11) << 24) | ((uint32_t)gfmul(so, 13) << 16) | ((uint32_t)gfmul(so, 9) << 8) | gfmul(so, 14);
|
||||
}
|
||||
|
||||
uint32_t aes_mixcolumn_fwd(uint32_t x) {
|
||||
uint8_t s0 = bit_sub<0, 7 - 0 + 1>(x);
|
||||
uint8_t s1 = bit_sub<8, 15 - 8 + 1>(x);
|
||||
uint8_t s2 = bit_sub<16, 23 - 16 + 1>(x);
|
||||
uint8_t s3 = bit_sub<24, 31 - 24 + 1>(x);
|
||||
uint8_t b0 = xt2(s0) ^ xt3(s1) ^ (s2) ^ (s3);
|
||||
uint8_t b1 = (s0) ^ xt2(s1) ^ xt3(s2) ^ (s3);
|
||||
uint8_t b2 = (s0) ^ (s1) ^ xt2(s2) ^ xt3(s3);
|
||||
uint8_t b3 = xt3(s0) ^ (s1) ^ (s2) ^ xt2(s3);
|
||||
return ((uint32_t)b3 << 24) | ((uint32_t)b2 << 16) | ((uint32_t)b1 << 8) | b0;
|
||||
}
|
||||
|
||||
uint32_t aes_mixcolumn_inv(uint32_t x) {
|
||||
uint8_t s0 = bit_sub<0, 7 - 0 + 1>(x);
|
||||
uint8_t s1 = bit_sub<8, 15 - 8 + 1>(x);
|
||||
uint8_t s2 = bit_sub<16, 23 - 16 + 1>(x);
|
||||
uint8_t s3 = bit_sub<24, 31 - 24 + 1>(x);
|
||||
uint8_t b0 = gfmul(s0, 14) ^ gfmul(s1, 11) ^ gfmul(s2, 13) ^ gfmul(s3, 9);
|
||||
uint8_t b1 = gfmul(s0, 9) ^ gfmul(s1, 14) ^ gfmul(s2, 11) ^ gfmul(s3, 13);
|
||||
uint8_t b2 = gfmul(s0, 13) ^ gfmul(s1, 9) ^ gfmul(s2, 14) ^ gfmul(s3, 11);
|
||||
uint8_t b3 = gfmul(s0, 11) ^ gfmul(s1, 13) ^ gfmul(s2, 9) ^ gfmul(s3, 14);
|
||||
return ((uint32_t)b3 << 24) | ((uint32_t)b2 << 16) | ((uint32_t)b1 << 8) | b0;
|
||||
}
|
||||
|
||||
uint32_t aes_decode_rcon(uint8_t r) {
|
||||
switch(r) {
|
||||
case 0:
|
||||
return 1;
|
||||
case 1:
|
||||
return 2;
|
||||
case 2:
|
||||
return 4;
|
||||
case 3:
|
||||
return 8;
|
||||
case 4:
|
||||
return 16;
|
||||
case 5:
|
||||
return 32;
|
||||
case 6:
|
||||
return 64;
|
||||
case 7:
|
||||
return 128;
|
||||
case 8:
|
||||
return 27;
|
||||
case 9:
|
||||
return 54;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t aes_subword_fwd(uint32_t x) {
|
||||
return ((uint32_t)aes_sbox_fwd(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint32_t)aes_sbox_fwd(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
|
||||
((uint32_t)aes_sbox_fwd(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_fwd(bit_sub<0, 7 - 0 + 1>(x));
|
||||
}
|
||||
|
||||
uint32_t aes_subword_inv(uint32_t x) {
|
||||
return ((uint32_t)aes_sbox_inv(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint32_t)aes_sbox_inv(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
|
||||
((uint32_t)aes_sbox_inv(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_inv(bit_sub<0, 7 - 0 + 1>(x));
|
||||
}
|
||||
|
||||
uint32_t aes_get_column(__uint128_t state, unsigned c) {
|
||||
assert(c < 4);
|
||||
return static_cast<uint32_t>(state >> (32 * c));
|
||||
};
|
||||
|
||||
uint64_t aes_apply_fwd_sbox_to_each_byte(uint64_t x) {
|
||||
return ((uint64_t)aes_sbox_fwd(bit_sub<56, 63 - 56 + 1>(x)) << 56) | ((uint64_t)aes_sbox_fwd(bit_sub<48, 55 - 48 + 1>(x)) << 48) |
|
||||
((uint64_t)aes_sbox_fwd(bit_sub<40, 47 - 40 + 1>(x)) << 40) | ((uint64_t)aes_sbox_fwd(bit_sub<32, 39 - 32 + 1>(x)) << 32) |
|
||||
((uint64_t)aes_sbox_fwd(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint64_t)aes_sbox_fwd(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
|
||||
((uint64_t)aes_sbox_fwd(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_fwd(bit_sub<0, 7 - 0 + 1>(x));
|
||||
}
|
||||
|
||||
uint64_t aes_apply_inv_sbox_to_each_byte(uint64_t x) {
|
||||
return ((uint64_t)aes_sbox_inv(bit_sub<56, 63 - 56 + 1>(x)) << 56) | ((uint64_t)aes_sbox_inv(bit_sub<48, 55 - 48 + 1>(x)) << 48) |
|
||||
((uint64_t)aes_sbox_inv(bit_sub<40, 47 - 40 + 1>(x)) << 40) | ((uint64_t)aes_sbox_inv(bit_sub<32, 39 - 32 + 1>(x)) << 32) |
|
||||
((uint64_t)aes_sbox_inv(bit_sub<24, 31 - 24 + 1>(x)) << 24) | ((uint64_t)aes_sbox_inv(bit_sub<16, 23 - 16 + 1>(x)) << 16) |
|
||||
((uint64_t)aes_sbox_inv(bit_sub<8, 15 - 8 + 1>(x)) << 8) | aes_sbox_inv(bit_sub<0, 7 - 0 + 1>(x));
|
||||
}
|
||||
|
||||
uint64_t aes_rv64_shiftrows_fwd(uint64_t rs2, uint64_t rs1) {
|
||||
return ((uint64_t)bit_sub<24, 31 - 24 + 1>(rs1) << 56) | ((uint64_t)bit_sub<48, 55 - 48 + 1>(rs2) << 48) |
|
||||
((uint64_t)bit_sub<8, 15 - 8 + 1>(rs2) << 40) | ((uint64_t)bit_sub<32, 39 - 32 + 1>(rs1) << 32) |
|
||||
((uint64_t)bit_sub<56, 63 - 56 + 1>(rs2) << 24) | ((uint64_t)bit_sub<16, 23 - 16 + 1>(rs2) << 16) |
|
||||
((uint64_t)bit_sub<40, 47 - 40 + 1>(rs1) << 8) | bit_sub<0, 7 - 0 + 1>(rs1);
|
||||
}
|
||||
|
||||
uint64_t aes_rv64_shiftrows_inv(uint64_t rs2, uint64_t rs1) {
|
||||
return ((uint64_t)bit_sub<24, 31 - 24 + 1>(rs2) << 56) | ((uint64_t)bit_sub<48, 55 - 48 + 1>(rs2) << 48) |
|
||||
((uint64_t)bit_sub<8, 15 - 8 + 1>(rs1) << 40) | ((uint64_t)bit_sub<32, 39 - 32 + 1>(rs1) << 32) |
|
||||
((uint64_t)bit_sub<56, 63 - 56 + 1>(rs1) << 24) | ((uint64_t)bit_sub<16, 23 - 16 + 1>(rs2) << 16) |
|
||||
((uint64_t)bit_sub<40, 47 - 40 + 1>(rs2) << 8) | bit_sub<0, 7 - 0 + 1>(rs1);
|
||||
}
|
||||
|
||||
uint128_t aes_shift_rows_fwd(uint128_t x) {
|
||||
uint32_t ic3 = aes_get_column(x, 3);
|
||||
uint32_t ic2 = aes_get_column(x, 2);
|
||||
uint32_t ic1 = aes_get_column(x, 1);
|
||||
uint32_t ic0 = aes_get_column(x, 0);
|
||||
uint32_t oc0 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic3) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic2) << 16) |
|
||||
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic1) << 8) | bit_sub<0, 7 - 0 + 1>(ic0);
|
||||
uint32_t oc1 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic0) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic3) << 16) |
|
||||
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic2) << 8) | bit_sub<0, 7 - 0 + 1>(ic1);
|
||||
uint32_t oc2 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic1) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic0) << 16) |
|
||||
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic3) << 8) | bit_sub<0, 7 - 0 + 1>(ic2);
|
||||
uint32_t oc3 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic2) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic1) << 16) |
|
||||
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic0) << 8) | bit_sub<0, 7 - 0 + 1>(ic3);
|
||||
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
|
||||
}
|
||||
|
||||
uint128_t aes_shift_rows_inv(uint128_t x) {
|
||||
uint32_t ic3 = aes_get_column(x, 3);
|
||||
uint32_t ic2 = aes_get_column(x, 2);
|
||||
uint32_t ic1 = aes_get_column(x, 1);
|
||||
uint32_t ic0 = aes_get_column(x, 0);
|
||||
uint32_t oc0 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic1) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic2) << 16) |
|
||||
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic3) << 8) | bit_sub<0, 7 - 0 + 1>(ic0);
|
||||
uint32_t oc1 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic2) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic3) << 16) |
|
||||
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic0) << 8) | bit_sub<0, 7 - 0 + 1>(ic1);
|
||||
uint32_t oc2 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic3) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic0) << 16) |
|
||||
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic1) << 8) | bit_sub<0, 7 - 0 + 1>(ic2);
|
||||
uint32_t oc3 = ((uint32_t)bit_sub<24, 31 - 24 + 1>(ic0) << 24) | ((uint32_t)bit_sub<16, 23 - 16 + 1>(ic1) << 16) |
|
||||
((uint32_t)bit_sub<8, 15 - 8 + 1>(ic2) << 8) | bit_sub<0, 7 - 0 + 1>(ic3);
|
||||
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
|
||||
}
|
||||
|
||||
uint128_t aes_subbytes_fwd(uint128_t x) {
|
||||
uint32_t oc0 = aes_subword_fwd(aes_get_column(x, 0));
|
||||
uint32_t oc1 = aes_subword_fwd(aes_get_column(x, 1));
|
||||
uint32_t oc2 = aes_subword_fwd(aes_get_column(x, 2));
|
||||
uint32_t oc3 = aes_subword_fwd(aes_get_column(x, 3));
|
||||
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
|
||||
}
|
||||
|
||||
uint128_t aes_subbytes_inv(uint128_t x) {
|
||||
uint32_t oc0 = aes_subword_inv(aes_get_column(x, 0));
|
||||
uint32_t oc1 = aes_subword_inv(aes_get_column(x, 1));
|
||||
uint32_t oc2 = aes_subword_inv(aes_get_column(x, 2));
|
||||
uint32_t oc3 = aes_subword_inv(aes_get_column(x, 3));
|
||||
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
|
||||
}
|
||||
|
||||
uint128_t aes_mixcolumns_fwd(uint128_t x) {
|
||||
uint32_t oc0 = aes_mixcolumn_fwd(aes_get_column(x, 0));
|
||||
uint32_t oc1 = aes_mixcolumn_fwd(aes_get_column(x, 1));
|
||||
uint32_t oc2 = aes_mixcolumn_fwd(aes_get_column(x, 2));
|
||||
uint32_t oc3 = aes_mixcolumn_fwd(aes_get_column(x, 3));
|
||||
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
|
||||
}
|
||||
|
||||
uint128_t aes_mixcolumns_inv(uint128_t x) {
|
||||
uint32_t oc0 = aes_mixcolumn_inv(aes_get_column(x, 0));
|
||||
uint32_t oc1 = aes_mixcolumn_inv(aes_get_column(x, 1));
|
||||
uint32_t oc2 = aes_mixcolumn_inv(aes_get_column(x, 2));
|
||||
uint32_t oc3 = aes_mixcolumn_inv(aes_get_column(x, 3));
|
||||
return ((uint128_t)oc3 << 96) | ((uint128_t)oc2 << 64) | ((uint128_t)oc1 << 32) | oc0;
|
||||
}
|
||||
|
||||
uint32_t aes_rotword(uint32_t x) {
|
||||
uint8_t a0 = bit_sub<0, 7 - 0 + 1>(x);
|
||||
uint8_t a1 = bit_sub<8, 15 - 8 + 1>(x);
|
||||
uint8_t a2 = bit_sub<16, 23 - 16 + 1>(x);
|
||||
uint8_t a3 = bit_sub<24, 31 - 24 + 1>(x);
|
||||
return ((uint32_t)a0 << 24) | ((uint32_t)a3 << 16) | ((uint32_t)a2 << 8) | a1;
|
||||
}
|
||||
|
||||
std::function<uint128_t(uint128_t, uint128_t, uint128_t)> get_crypto_funct(unsigned funct6, unsigned vs1) {
|
||||
switch(funct6) {
|
||||
case 0b101000: // VAES.VV
|
||||
case 0b101001: // VAES.VS
|
||||
switch(vs1) {
|
||||
case 0b00000: // VAESDM
|
||||
return [](uint128_t state, uint128_t rkey, uint128_t) {
|
||||
uint128_t sr = aes_shift_rows_inv(state);
|
||||
uint128_t sb = aes_subbytes_inv(sr);
|
||||
uint128_t ark = sb ^ rkey;
|
||||
uint128_t mix = aes_mixcolumns_inv(ark);
|
||||
return mix;
|
||||
};
|
||||
case 0b00001: // VAESDF
|
||||
return [](uint128_t state, uint128_t rkey, uint128_t) {
|
||||
uint128_t sr = aes_shift_rows_inv(state);
|
||||
uint128_t sb = aes_subbytes_inv(sr);
|
||||
uint128_t ark = sb ^ rkey;
|
||||
return ark;
|
||||
};
|
||||
case 0b00010: // VAESEM
|
||||
return [](uint128_t state, uint128_t rkey, uint128_t) {
|
||||
uint128_t sb = aes_subbytes_fwd(state);
|
||||
uint128_t sr = aes_shift_rows_fwd(sb);
|
||||
uint128_t mix = aes_mixcolumns_fwd(sr);
|
||||
uint128_t ark = mix ^ rkey;
|
||||
return ark;
|
||||
};
|
||||
case 0b00011: // VAESEF
|
||||
return [](uint128_t state, uint128_t rkey, uint128_t) {
|
||||
uint128_t sb = aes_subbytes_fwd(state);
|
||||
uint128_t sr = aes_shift_rows_fwd(sb);
|
||||
uint128_t ark = sr ^ rkey;
|
||||
return ark;
|
||||
};
|
||||
case 0b00111: // VAESZ
|
||||
return [](uint128_t state, uint128_t rkey, uint128_t) {
|
||||
uint128_t ark = state ^ rkey;
|
||||
return ark;
|
||||
};
|
||||
case 0b10000: // VSM4R
|
||||
throw new std::runtime_error("Unsupported operation in get_crypto_funct");
|
||||
case 0b10001: // VGMUL
|
||||
return [](uint128_t vd, uint128_t vs2, uint128_t) {
|
||||
uint128_t Y = brev8<uint128_t>(vd);
|
||||
uint128_t H = brev8<uint128_t>(vs2);
|
||||
uint128_t Z = 0;
|
||||
for(size_t bit = 0; bit < 128; bit++) {
|
||||
if((Y >> bit) & 1)
|
||||
Z ^= H;
|
||||
bool reduce = (H >> 127) & 1;
|
||||
H = H << 1;
|
||||
if(reduce)
|
||||
H ^= 0x87;
|
||||
}
|
||||
uint128_t result = brev8<uint128_t>(Z);
|
||||
return result;
|
||||
};
|
||||
default:
|
||||
throw new std::runtime_error("Unsupported operation in get_crypto_funct");
|
||||
}
|
||||
case 0b100000: // VSM3ME
|
||||
case 0b100001: // VSM4K
|
||||
throw new std::runtime_error("Unsupported operation in get_crypto_funct");
|
||||
case 0b100010: // VAESKF1
|
||||
return [](uint128_t vd, uint128_t vs2, uint128_t r) {
|
||||
auto extract_word = [](const uint128_t& value, int index) -> uint32_t {
|
||||
return static_cast<uint32_t>((value >> (32 * index)) & std::numeric_limits<uint32_t>::max());
|
||||
};
|
||||
|
||||
uint32_t k0 = (vs2 >> 32 * 0) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t k1 = (vs2 >> 32 * 1) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t k2 = (vs2 >> 32 * 2) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t k3 = (vs2 >> 32 * 3) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t w0 = aes_subword_fwd(aes_rotword(k3)) ^ aes_decode_rcon(r) ^ k0;
|
||||
uint32_t w1 = w0 ^ k1;
|
||||
uint32_t w2 = w1 ^ k2;
|
||||
uint32_t w3 = w2 ^ k3;
|
||||
uint128_t result = (uint128_t(w3) << 96) | (uint128_t(w2) << 64) | (uint128_t(w1) << 32) | (uint128_t(w0));
|
||||
return result;
|
||||
};
|
||||
case 0b101010: // VAESKF2
|
||||
return [](uint128_t vd, uint128_t vs2, uint128_t r) {
|
||||
uint32_t k0 = (vs2 >> 32 * 0) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t k1 = (vs2 >> 32 * 1) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t k2 = (vs2 >> 32 * 2) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t k3 = (vs2 >> 32 * 3) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t rkb0 = (vd >> 32 * 0) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t rkb1 = (vd >> 32 * 1) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t rkb2 = (vd >> 32 * 2) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t rkb3 = (vd >> 32 * 3) & std::numeric_limits<uint32_t>::max();
|
||||
uint32_t w0 = r & 1 ? aes_subword_fwd(k3) ^ rkb0 : aes_subword_fwd(aes_rotword(k3)) ^ aes_decode_rcon((r >> 1) - 1) ^ rkb0;
|
||||
uint32_t w1 = w0 ^ rkb1;
|
||||
uint32_t w2 = w1 ^ rkb2;
|
||||
uint32_t w3 = w2 ^ rkb3;
|
||||
uint128_t result = (uint128_t(w3) << 96) | (uint128_t(w2) << 64) | (uint128_t(w1) << 32) | (uint128_t(w0));
|
||||
return result;
|
||||
};
|
||||
case 0b101011: // VSM3C
|
||||
throw new std::runtime_error("Unsupported operation in get_crypto_funct");
|
||||
case 0b101100: // VGHSH
|
||||
return [](uint128_t Y, uint128_t vs2, uint128_t X) {
|
||||
auto H = brev8<uint128_t>(vs2);
|
||||
uint128_t Z = 0;
|
||||
uint128_t S = brev8<uint128_t>(Y ^ X);
|
||||
for(size_t bit = 0; bit < 128; bit++) {
|
||||
if((S >> bit) & 1)
|
||||
Z ^= H;
|
||||
bool reduce = (H >> 127) & 1;
|
||||
H = H << 1;
|
||||
if(reduce)
|
||||
H ^= 0x87;
|
||||
}
|
||||
uint128_t result = brev8<uint128_t>(Z);
|
||||
return result;
|
||||
};
|
||||
case 0b101101: // VSHA2MS
|
||||
case 0b101110: // VSHA2CH
|
||||
case 0b101111: // VSHA2CL
|
||||
default:
|
||||
throw new std::runtime_error("Unknown funct6 in get_crypto_funct");
|
||||
}
|
||||
}
|
||||
} // namespace softvector
|
@ -41,10 +41,6 @@
|
||||
#include <functional>
|
||||
#include <stdint.h>
|
||||
namespace softvector {
|
||||
#ifndef _MSC_VER
|
||||
using int128_t = __int128;
|
||||
using uint128_t = unsigned __int128;
|
||||
#endif
|
||||
const unsigned RFS = 32;
|
||||
|
||||
struct vtype_t {
|
||||
@ -74,14 +70,9 @@ struct vmask_view {
|
||||
};
|
||||
vmask_view read_vmask(uint8_t* V, uint16_t VLEN, uint16_t elem_count, uint8_t reg_idx = 0);
|
||||
template <unsigned VLEN> vmask_view read_vmask(uint8_t* V, uint16_t elem_count, uint8_t reg_idx = 0);
|
||||
std::function<uint128_t(uint128_t, uint128_t, uint128_t)> get_crypto_funct(unsigned funct6, unsigned vs1);
|
||||
|
||||
template <typename dest_elem_t, typename src_elem_t = dest_elem_t> dest_elem_t brev(src_elem_t vs2);
|
||||
template <typename dest_elem_t, typename src_elem_t = dest_elem_t> dest_elem_t brev8(src_elem_t vs2);
|
||||
|
||||
bool softvec_read(void* core, uint64_t addr, uint64_t length, uint8_t* data);
|
||||
bool softvec_write(void* core, uint64_t addr, uint64_t length, uint8_t* data);
|
||||
|
||||
template <unsigned VLEN, typename eew_t>
|
||||
uint64_t vector_load_store(void* core, std::function<bool(void*, uint64_t, uint64_t, uint8_t*)> load_store_fn, uint8_t* V, uint64_t vl,
|
||||
uint64_t vstart, vtype_t vtype, bool vm, uint8_t vd, uint64_t rs1, uint8_t segment_size, int64_t stride = 0,
|
||||
@ -176,17 +167,6 @@ void mask_fp_vector_vector_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t
|
||||
template <unsigned VLEN, typename elem_t>
|
||||
void mask_fp_vector_imm_op(uint8_t* V, unsigned funct6, uint64_t vl, uint64_t vstart, vtype_t vtype, bool vm, unsigned vd, unsigned vs2,
|
||||
elem_t imm, uint8_t rm);
|
||||
template <unsigned VLEN, unsigned EGS>
|
||||
void vector_vector_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
|
||||
unsigned vs1);
|
||||
template <unsigned VLEN, unsigned EGS>
|
||||
void vector_scalar_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
|
||||
unsigned vs1);
|
||||
template <unsigned VLEN, unsigned EGS>
|
||||
void vector_imm_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
|
||||
uint8_t imm);
|
||||
template <unsigned VLEN, unsigned EGS, typename elem_type_t>
|
||||
void vector_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2, unsigned vs1);
|
||||
} // namespace softvector
|
||||
#include "vm/vector_functions.hpp"
|
||||
#endif /* _VM_VECTOR_FUNCTIONS_H_ */
|
||||
|
@ -32,7 +32,6 @@
|
||||
// alex@minres.com - initial API and implementation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
#include "iss/interp/vm_base.h"
|
||||
extern "C" {
|
||||
#include <softfloat.h>
|
||||
}
|
||||
@ -56,14 +55,6 @@ extern "C" {
|
||||
#ifdef __SIZEOF_INT128__
|
||||
template <> struct std::make_signed<__uint128_t> { using type = __int128_t; };
|
||||
template <> struct std::make_signed<__int128_t> { using type = __int128_t; };
|
||||
// helper struct to make calling twice<T> on 128-bit datatypes legal at compile time
|
||||
struct poison128_t {
|
||||
poison128_t() { throw std::runtime_error("Attempt to use twice<__uint128_t>::type at runtime"); }
|
||||
poison128_t(const poison128_t&) { throw std::runtime_error("Copy of poison128_t is not allowed"); }
|
||||
template <typename U> poison128_t(U) { throw std::runtime_error("Conversion to poison128_t is not allowed"); }
|
||||
operator __uint128_t() const { throw std::runtime_error("Use of poison128_t as __uint128_t is not allowed"); }
|
||||
};
|
||||
template <> struct std::make_signed<poison128_t> { using type = poison128_t; };
|
||||
#endif
|
||||
|
||||
namespace softvector {
|
||||
@ -117,10 +108,6 @@ template <> struct twice<uint32_t> { using type = uint64_t; };
|
||||
#ifdef __SIZEOF_INT128__
|
||||
template <> struct twice<int64_t> { using type = __int128_t; };
|
||||
template <> struct twice<uint64_t> { using type = __uint128_t; };
|
||||
|
||||
template <> struct twice<__uint128_t> { using type = poison128_t; };
|
||||
template <> struct twice<__int128_t> { using type = poison128_t; };
|
||||
|
||||
#endif
|
||||
template <class T> using twice_t = typename twice<T>::type; // for convenience
|
||||
template <typename TO, typename FROM> constexpr TO sext(FROM val) {
|
||||
@ -193,8 +180,6 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
|
||||
switch(funct6) {
|
||||
case 0b000000: // VADD
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 + vs1; };
|
||||
case 0b000001: // VANDN
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 & ~vs1; };
|
||||
case 0b000010: // VSUB
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 - vs1; };
|
||||
case 0b000011: // VRSUB
|
||||
@ -220,22 +205,6 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
|
||||
return static_cast<std::make_signed_t<dest_elem_t>>(static_cast<std::make_signed_t<src2_elem_t>>(vs2) -
|
||||
static_cast<std::make_signed_t<src1_elem_t>>(vs1));
|
||||
};
|
||||
case 0b010100: // VROR
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
||||
constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
|
||||
auto shamt = vs1 & shift_mask<src1_elem_t>();
|
||||
return (vs2 >> shamt) | (vs2 << (bits - shamt));
|
||||
};
|
||||
case 0b010101: { // VROL
|
||||
if(funct3 == OPIVI)
|
||||
return get_funct<dest_elem_t>(0b010100, funct3);
|
||||
else
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
||||
constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
|
||||
auto shamt = vs1 & shift_mask<src1_elem_t>();
|
||||
return (vs2 << shamt) | (vs2 >> (bits - shamt));
|
||||
};
|
||||
}
|
||||
case 0b100101: // VSLL
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 << (vs1 & shift_mask<src2_elem_t>()); };
|
||||
case 0b101000: // VSRL
|
||||
@ -250,10 +219,6 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
||||
return static_cast<std::make_signed_t<src2_elem_t>>(vs2) >> (vs1 & shift_mask<src2_elem_t>());
|
||||
};
|
||||
case 0b110101: // VWSLL
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
||||
return static_cast<dest_elem_t>(vs2) << (vs1 & (shift_mask<dest_elem_t>()));
|
||||
};
|
||||
default:
|
||||
throw new std::runtime_error("Unknown funct6 in get_funct");
|
||||
}
|
||||
@ -363,24 +328,6 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
||||
return sext<dest_elem_t>(vs1) * static_cast<dest_elem_t>(vs2) + vd;
|
||||
};
|
||||
case 0b001100: // VCLMUL
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
||||
dest_elem_t output = 0;
|
||||
for(size_t i = 0; i <= sizeof(dest_elem_t) * 8 - 1; i++) {
|
||||
if((vs2 >> i) & 1)
|
||||
output = output ^ (vs1 << i);
|
||||
}
|
||||
return output;
|
||||
};
|
||||
case 0b001101: // VCLMULH
|
||||
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
|
||||
dest_elem_t output = 0;
|
||||
for(size_t i = 1; i < sizeof(dest_elem_t) * 8; i++) {
|
||||
if((vs2 >> i) & 1)
|
||||
output = output ^ (vs1 >> (sizeof(dest_elem_t) * 8 - i));
|
||||
}
|
||||
return output;
|
||||
};
|
||||
default:
|
||||
throw new std::runtime_error("Unknown funct6 in get_funct");
|
||||
}
|
||||
@ -417,10 +364,11 @@ void vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl, ui
|
||||
auto fn = get_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
|
||||
for(size_t idx = vstart; idx < vl; idx++) {
|
||||
bool mask_active = vm ? 1 : mask_reg[idx];
|
||||
if(mask_active)
|
||||
if(mask_active) {
|
||||
vd_view[idx] = fn(vd_view[idx], vs2_view[idx], imm);
|
||||
else if(vtype.vma())
|
||||
vd_view[idx] = agnostic_behavior(vd_view[idx]);
|
||||
} else {
|
||||
vd_view[idx] = vtype.vma() ? vd_view[idx] : vd_view[idx];
|
||||
}
|
||||
}
|
||||
if(vtype.vta())
|
||||
for(size_t idx = vl; idx < vlmax; idx++)
|
||||
@ -587,79 +535,6 @@ std::function<dest_elem_t(src2_elem_t)> get_unary_fn(unsigned unary_op) {
|
||||
case 0b00100: // VZEXT.VF4
|
||||
case 0b00010: // VZEXT.VF8
|
||||
return [](src2_elem_t vs2) { return vs2; };
|
||||
case 0b01000: // VBREV8
|
||||
return [](src2_elem_t vs2) { return brev8<dest_elem_t>(vs2); };
|
||||
case 0b01001: // VREV8
|
||||
return [](src2_elem_t vs2) {
|
||||
constexpr unsigned byte_count = sizeof(src2_elem_t);
|
||||
dest_elem_t result = 0;
|
||||
for(size_t i = 0; i < byte_count; ++i) {
|
||||
result <<= 8;
|
||||
result |= (vs2 & 0xFF);
|
||||
vs2 >>= 8;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
case 0b01010: // VBREV
|
||||
return [](src2_elem_t vs2) { return brev<dest_elem_t>(vs2); };
|
||||
case 0b01100: // VCLZ
|
||||
return [](src2_elem_t vs2) {
|
||||
if(std::is_same_v<src2_elem_t, unsigned int>)
|
||||
return static_cast<dest_elem_t>(__builtin_clz(vs2));
|
||||
else if(std::is_same_v<src2_elem_t, unsigned long>)
|
||||
return static_cast<dest_elem_t>(__builtin_clzl(vs2));
|
||||
else if(std::is_same_v<src2_elem_t, unsigned long long>)
|
||||
return static_cast<dest_elem_t>(__builtin_clzll(vs2));
|
||||
else {
|
||||
constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
|
||||
if(vs2 == 0)
|
||||
return bits;
|
||||
dest_elem_t count = 0;
|
||||
for(size_t i = bits - 1; i >= 0; --i) {
|
||||
if((vs2 >> i) & 1)
|
||||
break;
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
};
|
||||
case 0b01101: // VCTZ
|
||||
return [](src2_elem_t vs2) {
|
||||
if(std::is_same_v<src2_elem_t, unsigned int>)
|
||||
return static_cast<dest_elem_t>(__builtin_ctz(vs2));
|
||||
else if(std::is_same_v<src2_elem_t, unsigned long>)
|
||||
return static_cast<dest_elem_t>(__builtin_ctzl(vs2));
|
||||
else if(std::is_same_v<src2_elem_t, unsigned long long>)
|
||||
return static_cast<dest_elem_t>(__builtin_ctzll(vs2));
|
||||
else {
|
||||
constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
|
||||
if(vs2 == 0)
|
||||
return bits;
|
||||
dest_elem_t count = 0;
|
||||
while((vs2 & 1) == 0) {
|
||||
++count;
|
||||
vs2 >>= 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
};
|
||||
case 0b01110: // VCPOP
|
||||
return [](src2_elem_t vs2) {
|
||||
if(std::is_same_v<src2_elem_t, unsigned int>)
|
||||
return static_cast<dest_elem_t>(__builtin_popcount(vs2));
|
||||
else if(std::is_same_v<src2_elem_t, unsigned long>)
|
||||
return static_cast<dest_elem_t>(__builtin_popcountl(vs2));
|
||||
else if(std::is_same_v<src2_elem_t, unsigned long long>)
|
||||
return static_cast<dest_elem_t>(__builtin_popcountll(vs2));
|
||||
else {
|
||||
dest_elem_t count = 0;
|
||||
while(vs2) {
|
||||
count += vs2 & 1;
|
||||
vs2 >>= 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
};
|
||||
default:
|
||||
throw new std::runtime_error("Unknown funct in get_unary_fn");
|
||||
}
|
||||
@ -675,8 +550,8 @@ void vector_unary_op(uint8_t* V, unsigned unary_op, uint64_t vl, uint64_t vstart
|
||||
bool mask_active = vm ? 1 : mask_reg[idx];
|
||||
if(mask_active)
|
||||
vd_view[idx] = fn(vs2_view[idx]);
|
||||
else if(vtype.vma())
|
||||
vd_view[idx] = agnostic_behavior(vd_view[idx]);
|
||||
else
|
||||
vd_view[idx] = vtype.vma() ? vd_view[idx] : vd_view[idx];
|
||||
}
|
||||
if(vtype.vta())
|
||||
for(size_t idx = vl; idx < vlmax; idx++)
|
||||
@ -899,10 +774,11 @@ bool sat_vector_vector_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t
|
||||
auto fn = get_sat_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
|
||||
for(size_t idx = vstart; idx < vl; idx++) {
|
||||
bool mask_active = vm ? 1 : mask_reg[idx];
|
||||
if(mask_active)
|
||||
if(mask_active) {
|
||||
saturated |= fn(vxrm, vtype, vd_view[idx], vs2_view[idx], vs1_view[idx]);
|
||||
else if(vtype.vma())
|
||||
vd_view[idx] = agnostic_behavior(vd_view[idx]);
|
||||
} else {
|
||||
vd_view[idx] = vtype.vma() ? vd_view[idx] : vd_view[idx];
|
||||
}
|
||||
}
|
||||
if(vtype.vta())
|
||||
for(size_t idx = vl; idx < vlmax; idx++) {
|
||||
@ -921,10 +797,11 @@ bool sat_vector_imm_op(uint8_t* V, unsigned funct6, unsigned funct3, uint64_t vl
|
||||
auto fn = get_sat_funct<dest_elem_t, src2_elem_t, src1_elem_t>(funct6, funct3);
|
||||
for(size_t idx = vstart; idx < vl; idx++) {
|
||||
bool mask_active = vm ? 1 : mask_reg[idx];
|
||||
if(mask_active)
|
||||
if(mask_active) {
|
||||
saturated |= fn(vxrm, vtype, vd_view[idx], vs2_view[idx], imm);
|
||||
else if(vtype.vma())
|
||||
vd_view[idx] = agnostic_behavior(vd_view[idx]);
|
||||
} else {
|
||||
vd_view[idx] = vtype.vma() ? vd_view[idx] : vd_view[idx];
|
||||
}
|
||||
}
|
||||
if(vtype.vta())
|
||||
for(size_t idx = vl; idx < vlmax; idx++) {
|
||||
@ -2062,221 +1939,4 @@ template <unsigned VLEN> void vector_whole_move(uint8_t* V, unsigned vd, unsigne
|
||||
memcpy(vd_view.start, vs2_view.start, VLEN / 8 * count);
|
||||
}
|
||||
|
||||
template <unsigned VLEN, unsigned EGS>
|
||||
void vector_vector_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
|
||||
unsigned vs1) {
|
||||
uint64_t vlmax = VLEN * vtype.lmul() / (vtype.sew() * EGS);
|
||||
auto vs1_view = get_vreg<VLEN, uint128_t>(V, vs1, vlmax);
|
||||
auto vs2_view = get_vreg<VLEN, uint128_t>(V, vs2, vlmax);
|
||||
auto vd_view = get_vreg<VLEN, uint128_t>(V, vd, vlmax);
|
||||
auto fn = get_crypto_funct(funct6, vs1);
|
||||
for(size_t idx = eg_start; idx < eg_len; idx++) {
|
||||
vd_view[idx] = fn(vd_view[idx], vs2_view[idx], vs1_view[idx]);
|
||||
}
|
||||
if(vtype.vta())
|
||||
for(size_t idx = eg_len; idx < vlmax; idx++)
|
||||
vd_view[idx] = agnostic_behavior(vd_view[idx]);
|
||||
}
|
||||
template <unsigned VLEN, unsigned EGS>
|
||||
void vector_scalar_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
|
||||
unsigned vs1) {
|
||||
uint64_t vlmax = VLEN * vtype.lmul() / (vtype.sew() * EGS);
|
||||
auto vs2_val = get_vreg<VLEN, uint128_t>(V, vs2, vlmax)[0];
|
||||
auto vd_view = get_vreg<VLEN, uint128_t>(V, vd, vlmax);
|
||||
auto fn = get_crypto_funct(funct6, vs1);
|
||||
for(size_t idx = eg_start; idx < eg_len; idx++) {
|
||||
vd_view[idx] = fn(vd_view[idx], vs2_val, -1);
|
||||
}
|
||||
if(vtype.vta())
|
||||
for(size_t idx = eg_len; idx < vlmax; idx++)
|
||||
vd_view[idx] = agnostic_behavior(vd_view[idx]);
|
||||
}
|
||||
|
||||
template <unsigned VLEN, unsigned EGS>
|
||||
void vector_imm_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
|
||||
uint8_t imm) {
|
||||
uint64_t vlmax = VLEN * vtype.lmul() / (vtype.sew() * EGS);
|
||||
auto vs2_view = get_vreg<VLEN, uint128_t>(V, vs2, vlmax);
|
||||
auto vd_view = get_vreg<VLEN, uint128_t>(V, vd, vlmax);
|
||||
auto fn = get_crypto_funct(funct6, -1);
|
||||
for(size_t idx = eg_start; idx < eg_len; idx++) {
|
||||
vd_view[idx] = fn(vd_view[idx], vs2_view[idx], imm);
|
||||
}
|
||||
if(vtype.vta())
|
||||
for(size_t idx = eg_len; idx < vlmax; idx++)
|
||||
vd_view[idx] = agnostic_behavior(vd_view[idx]);
|
||||
}
|
||||
template <typename T> T rotr(T x, unsigned n) {
|
||||
assert(n < sizeof(T) * 8);
|
||||
return (x >> n) | (x << (sizeof(T) * 8 - n));
|
||||
}
|
||||
template <typename T> T shr(T x, unsigned n) {
|
||||
assert(n < sizeof(T) * 8);
|
||||
return (x >> n);
|
||||
}
|
||||
template <typename T> T sum0(T);
|
||||
template <> inline uint32_t sum0(uint32_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); }
|
||||
template <> inline uint64_t sum0(uint64_t x) { return rotr(x, 28) ^ rotr(x, 34) ^ rotr(x, 39); }
|
||||
template <typename T> T sum1(T);
|
||||
template <> inline uint32_t sum1(uint32_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); }
|
||||
template <> inline uint64_t sum1(uint64_t x) { return rotr(x, 14) ^ rotr(x, 18) ^ rotr(x, 41); }
|
||||
template <typename T> T ch(T x, T y, T z) { return ((x & y) ^ ((~x) & z)); }
|
||||
template <typename T> T maj(T x, T y, T z) { return ((x & y) ^ (x & z) ^ (y & z)); }
|
||||
template <typename T> T sig0(T);
|
||||
template <> inline uint32_t sig0(uint32_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3); }
|
||||
template <> inline uint64_t sig0(uint64_t x) { return rotr(x, 1) ^ rotr(x, 8) ^ shr(x, 7); }
|
||||
template <typename T> T sig1(T);
|
||||
template <> inline uint32_t sig1(uint32_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10); }
|
||||
template <> inline uint64_t sig1(uint64_t x) { return rotr(x, 19) ^ rotr(x, 61) ^ shr(x, 6); }
|
||||
template <typename T> std::function<void(vreg_view<T>&, vreg_view<T>&, vreg_view<T>&)> get_crypto_funct(unsigned int funct6) {
|
||||
switch(funct6) {
|
||||
case 0b101110: // VSHA2CH
|
||||
return [](vreg_view<T>& vd_view, vreg_view<T>& vs2_view, vreg_view<T>& vs1_view) {
|
||||
T a = vs2_view[3];
|
||||
T b = vs2_view[2];
|
||||
T c = vd_view[3];
|
||||
T d = vd_view[2];
|
||||
T e = vs2_view[1];
|
||||
T f = vs2_view[0];
|
||||
T g = vd_view[1];
|
||||
T h = vd_view[0];
|
||||
T W0 = vs1_view[2];
|
||||
T W1 = vs1_view[3];
|
||||
T T1 = h + sum1(e) + ch(e, f, g) + W0;
|
||||
T T2 = sum0(a) + maj(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + T1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = T1 + T2;
|
||||
T1 = h + sum1(e) + ch(e, f, g) + W1;
|
||||
T2 = sum0(a) + maj(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + T1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = T1 + T2;
|
||||
vd_view[0] = f;
|
||||
vd_view[1] = e;
|
||||
vd_view[2] = b;
|
||||
vd_view[3] = a;
|
||||
};
|
||||
case 0b101111: // VSHA2CL
|
||||
return [](vreg_view<T>& vd_view, vreg_view<T>& vs2_view, vreg_view<T>& vs1_view) {
|
||||
T a = vs2_view[3];
|
||||
T b = vs2_view[2];
|
||||
T c = vd_view[3];
|
||||
T d = vd_view[2];
|
||||
T e = vs2_view[1];
|
||||
T f = vs2_view[0];
|
||||
T g = vd_view[1];
|
||||
T h = vd_view[0];
|
||||
T W0 = vs1_view[0];
|
||||
T W1 = vs1_view[1];
|
||||
T T1 = h + sum1(e) + ch(e, f, g) + W0;
|
||||
T T2 = sum0(a) + maj(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + T1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = T1 + T2;
|
||||
T1 = h + sum1(e) + ch(e, f, g) + W1;
|
||||
T2 = sum0(a) + maj(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + T1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = T1 + T2;
|
||||
vd_view[0] = f;
|
||||
vd_view[1] = e;
|
||||
vd_view[2] = b;
|
||||
vd_view[3] = a;
|
||||
};
|
||||
case 0b101101: // VSHA2MS
|
||||
return [](vreg_view<T>& vd_view, vreg_view<T>& vs2_view, vreg_view<T>& vs1_view) {
|
||||
T W0 = vd_view[0];
|
||||
T W1 = vd_view[1];
|
||||
T W2 = vd_view[2];
|
||||
T W3 = vd_view[3];
|
||||
|
||||
T W4 = vs2_view[0];
|
||||
T W9 = vs2_view[1];
|
||||
T W10 = vs2_view[2];
|
||||
T W11 = vs2_view[3];
|
||||
|
||||
T W12 = vs1_view[0];
|
||||
T W13 = vs1_view[1];
|
||||
T W14 = vs1_view[2];
|
||||
T W15 = vs1_view[3];
|
||||
|
||||
T W16 = sig1(W14) + W9 + sig0(W1) + W0;
|
||||
T W17 = sig1(W15) + W10 + sig0(W2) + W1;
|
||||
T W18 = sig1(W16) + W11 + sig0(W3) + W2;
|
||||
T W19 = sig1(W17) + W12 + sig0(W4) + W3;
|
||||
|
||||
vd_view[0] = W16;
|
||||
vd_view[1] = W17;
|
||||
vd_view[2] = W18;
|
||||
vd_view[3] = W19;
|
||||
};
|
||||
default:
|
||||
throw new std::runtime_error("Unsupported operation in get_crypto_funct");
|
||||
}
|
||||
}
|
||||
template <unsigned VLEN, unsigned EGS, typename elem_type_t>
|
||||
void vector_crypto(uint8_t* V, unsigned funct6, uint64_t eg_len, uint64_t eg_start, vtype_t vtype, unsigned vd, unsigned vs2,
|
||||
unsigned vs1) {
|
||||
auto fn = get_crypto_funct<elem_type_t>(funct6);
|
||||
auto vd_view = get_vreg<VLEN, elem_type_t>(V, vd, EGS);
|
||||
auto vs2_view = get_vreg<VLEN, elem_type_t>(V, vs2, EGS);
|
||||
auto vs1_view = get_vreg<VLEN, elem_type_t>(V, vs1, EGS);
|
||||
for(size_t idx = eg_start; idx < eg_len; idx++) {
|
||||
fn(vd_view, vs2_view, vs1_view);
|
||||
// We cannot use views in case EGW < VLEN, as views can only address the start of a register
|
||||
vd_view.start += EGS * sizeof(elem_type_t);
|
||||
vs2_view.start += EGS * sizeof(elem_type_t);
|
||||
vs1_view.start += EGS * sizeof(elem_type_t);
|
||||
}
|
||||
if(vtype.vta()) {
|
||||
uint64_t vlmax = VLEN * vtype.lmul() / (vtype.sew());
|
||||
auto vd_view = get_vreg<VLEN, elem_type_t>(V, vd, vlmax);
|
||||
for(size_t idx = eg_len * EGS; idx < vlmax; idx++)
|
||||
vd_view[idx] = agnostic_behavior(vd_view[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename dest_elem_t, typename src_elem_t> dest_elem_t brev(src_elem_t vs2) {
|
||||
constexpr dest_elem_t bits = sizeof(src_elem_t) * 8;
|
||||
dest_elem_t result = 0;
|
||||
for(size_t i = 0; i < bits; ++i) {
|
||||
result <<= 1;
|
||||
result |= (vs2 & 1);
|
||||
vs2 >>= 1;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
template <typename dest_elem_t, typename src_elem_t> dest_elem_t brev8(src_elem_t vs2) {
|
||||
constexpr unsigned byte_count = sizeof(src_elem_t);
|
||||
dest_elem_t result = 0;
|
||||
for(size_t i = 0; i < byte_count; ++i) {
|
||||
dest_elem_t byte = (vs2 >> (i * 8)) & 0xFF;
|
||||
byte = ((byte & 0xF0) >> 4) | ((byte & 0x0F) << 4);
|
||||
byte = ((byte & 0xCC) >> 2) | ((byte & 0x33) << 2);
|
||||
byte = ((byte & 0xAA) >> 1) | ((byte & 0x55) << 1);
|
||||
result |= byte << (i * 8);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
} // namespace softvector
|
Reference in New Issue
Block a user