factors decoder into separate component
This commit is contained in:
parent
cb5375258a
commit
f096b15dbd
|
@ -36,7 +36,8 @@ FILE(GLOB GEN_SOURCES
|
|||
|
||||
set(LIB_SOURCES
|
||||
src/iss/plugin/instruction_count.cpp
|
||||
src/iss/arch/tgc_c.cpp
|
||||
src/iss/arch/tgc_c.cpp
|
||||
src/iss/arch/tgc_c_decoder.cpp
|
||||
src/vm/interp/vm_tgc_c.cpp
|
||||
src/vm/fp_functions.cpp
|
||||
${GEN_SOURCES}
|
||||
|
|
|
@ -69,6 +69,7 @@ def getCString(def val){
|
|||
#include <array>
|
||||
#include <iss/arch/traits.h>
|
||||
#include <iss/arch_if.h>
|
||||
#include <iss/arch/instruction_decoder.h>
|
||||
#include <iss/vm_if.h>
|
||||
|
||||
namespace iss {
|
||||
|
@ -120,6 +121,8 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
|
|||
${instr.instruction.name} = ${index},<%}%>
|
||||
MAX_OPCODE
|
||||
};
|
||||
|
||||
static std::unique_ptr<instruction_decoder<${coreDef.name.toLowerCase()}>> get_decoder();
|
||||
};
|
||||
|
||||
struct ${coreDef.name.toLowerCase()}: public arch_if {
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
#include "${coreDef.name.toLowerCase()}.h"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
|
||||
namespace iss {
|
||||
namespace arch {
|
||||
namespace {
|
||||
// according to
|
||||
// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation
|
||||
#ifdef __GCC__
|
||||
constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); }
|
||||
#elif __cplusplus < 201402L
|
||||
constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); }
|
||||
constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; }
|
||||
#else
|
||||
constexpr size_t bit_count(uint32_t u) {
|
||||
size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
|
||||
return ((uCount + (uCount >> 3)) & 030707070707) % 63;
|
||||
}
|
||||
#endif
|
||||
|
||||
using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e;
|
||||
|
||||
/****************************************************************************
|
||||
* start opcode definitions
|
||||
****************************************************************************/
|
||||
struct instruction_desriptor {
|
||||
size_t length;
|
||||
uint32_t value;
|
||||
uint32_t mask;
|
||||
opcode_e op;
|
||||
};
|
||||
|
||||
const std::array<instruction_desriptor, ${instructions.size}> instr_descr = {{
|
||||
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, opcode_e::${instr.instruction.name}},<%}%>
|
||||
}};
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
struct instruction_decoder<${coreDef.name.toLowerCase()}> {
|
||||
using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e;
|
||||
using code_word_t=traits<${coreDef.name.toLowerCase()}>::code_word_t;
|
||||
|
||||
struct instruction_pattern {
|
||||
uint32_t value;
|
||||
uint32_t mask;
|
||||
opcode_e id;
|
||||
};
|
||||
|
||||
std::array<std::vector<instruction_pattern>, 4> qlut;
|
||||
|
||||
template<typename T>
|
||||
unsigned decode_instruction(T);
|
||||
|
||||
instruction_decoder() {
|
||||
for (auto instr : instr_descr) {
|
||||
auto quadrant = instr.value & 0x3;
|
||||
qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op});
|
||||
}
|
||||
for(auto& lut: qlut){
|
||||
std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){
|
||||
return bit_count(a.mask) > bit_count(b.mask);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
unsigned instruction_decoder<${coreDef.name.toLowerCase()}>::decode_instruction<traits<${coreDef.name.toLowerCase()}>::code_word_t>(traits<${coreDef.name.toLowerCase()}>::code_word_t instr){
|
||||
auto res = std::find_if(std::begin(qlut[instr&0x3]), std::end(qlut[instr&0x3]), [instr](instruction_pattern const& e){
|
||||
return !((instr&e.mask) ^ e.value );
|
||||
});
|
||||
return static_cast<unsigned>(res!=std::end(qlut[instr&0x3])? res->id : opcode_e::MAX_OPCODE);
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<instruction_decoder<${coreDef.name.toLowerCase()}>> traits<${coreDef.name.toLowerCase()}>::get_decoder(){
|
||||
return std::make_unique<instruction_decoder<${coreDef.name.toLowerCase()}>>();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -12,5 +12,6 @@
|
|||
${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %>
|
||||
- ${it.instruction.name}:
|
||||
encoding: ${it.encoding}
|
||||
mask: ${it.mask}<%}}%>
|
||||
mask: ${it.mask}<%if(it.attributes.size) {%>
|
||||
attributes: ${it.attributes}<%}}}%>
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ public:
|
|||
using addr_t = typename super::addr_t;
|
||||
using reg_t = typename traits::reg_t;
|
||||
using mem_type_e = typename traits::mem_type_e;
|
||||
using opcode_e = typename traits::opcode_e;
|
||||
|
||||
vm_impl();
|
||||
|
||||
|
@ -94,7 +95,6 @@ protected:
|
|||
|
||||
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
|
||||
|
||||
typename arch::traits<ARCH>::opcode_e decode_inst_id(code_word_t instr);
|
||||
virt_addr_t execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit) override;
|
||||
|
||||
// some compile time constants
|
||||
|
@ -111,13 +111,7 @@ protected:
|
|||
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
|
||||
std::array<compile_func, LUT_SIZE> lut_11;
|
||||
|
||||
struct instruction_pattern {
|
||||
uint32_t value;
|
||||
uint32_t mask;
|
||||
typename arch::traits<ARCH>::opcode_e id;
|
||||
};
|
||||
|
||||
std::array<std::vector<instruction_pattern>, 4> qlut;
|
||||
std::unique_ptr<instruction_decoder<ARCH>> decoder;
|
||||
|
||||
inline void raise(uint16_t trap_id, uint16_t cause){
|
||||
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
|
||||
|
@ -139,42 +133,7 @@ protected:
|
|||
|
||||
template<typename T>
|
||||
T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;}
|
||||
inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint8_t>(space, addr);
|
||||
if(this->core.trap_state) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline uint16_t readSpace2(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint16_t>(space, addr);
|
||||
if(this->core.trap_state) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline uint32_t readSpace4(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint32_t>(space, addr);
|
||||
if(this->core.trap_state) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline uint64_t readSpace8(typename super::mem_type_e space, uint64_t addr){
|
||||
auto ret = super::template read_mem<uint64_t>(space, addr);
|
||||
if(this->core.trap_state) throw 0;
|
||||
return ret;
|
||||
}
|
||||
inline void writeSpace1(typename super::mem_type_e space, uint64_t addr, uint8_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->core.trap_state) throw 0;
|
||||
}
|
||||
inline void writeSpace2(typename super::mem_type_e space, uint64_t addr, uint16_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->core.trap_state) throw 0;
|
||||
}
|
||||
inline void writeSpace4(typename super::mem_type_e space, uint64_t addr, uint32_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->core.trap_state) throw 0;
|
||||
}
|
||||
inline void writeSpace8(typename super::mem_type_e space, uint64_t addr, uint64_t data){
|
||||
super::write_mem(space, addr, data);
|
||||
if(this->core.trap_state) throw 0;
|
||||
}
|
||||
|
||||
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
|
||||
inline S sext(U from) {
|
||||
auto mask = (1ULL<<W) - 1;
|
||||
|
@ -194,20 +153,6 @@ protected:
|
|||
${it}<%}%>
|
||||
<%}%>
|
||||
private:
|
||||
/****************************************************************************
|
||||
* start opcode definitions
|
||||
****************************************************************************/
|
||||
struct InstructionDesriptor {
|
||||
size_t length;
|
||||
uint32_t value;
|
||||
uint32_t mask;
|
||||
typename arch::traits<ARCH>::opcode_e op;
|
||||
};
|
||||
|
||||
const std::array<InstructionDesriptor, ${instructions.size}> instr_descr = {{
|
||||
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, arch::traits<ARCH>::opcode_e::${instr.instruction.name}},<%}%>
|
||||
}};
|
||||
|
||||
//static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK;
|
||||
iss::status fetch_ins(virt_addr_t pc, uint8_t * data){
|
||||
|
@ -247,16 +192,7 @@ constexpr size_t bit_count(uint32_t u) {
|
|||
template <typename ARCH>
|
||||
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||
: vm_base<ARCH>(core, core_id, cluster_id) {
|
||||
unsigned id=0;
|
||||
for (auto instr : instr_descr) {
|
||||
auto quadrant = instr.value & 0x3;
|
||||
qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op});
|
||||
}
|
||||
for(auto& lut: qlut){
|
||||
std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){
|
||||
return bit_count(a.mask) > bit_count(b.mask);
|
||||
});
|
||||
}
|
||||
decoder = traits::get_decoder();
|
||||
}
|
||||
|
||||
inline bool is_count_limit_enabled(finish_cond_e cond){
|
||||
|
@ -267,19 +203,11 @@ inline bool is_jump_to_self_enabled(finish_cond_e cond){
|
|||
return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF;
|
||||
}
|
||||
|
||||
template <typename ARCH>
|
||||
typename arch::traits<ARCH>::opcode_e vm_impl<ARCH>::decode_inst_id(code_word_t instr){
|
||||
for(auto& e: qlut[instr&0x3]){
|
||||
if(!((instr&e.mask) ^ e.value )) return e.id;
|
||||
}
|
||||
return arch::traits<ARCH>::opcode_e::MAX_OPCODE;
|
||||
}
|
||||
|
||||
template <typename ARCH>
|
||||
typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){
|
||||
auto pc=start;
|
||||
auto* PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]);
|
||||
auto* NEXT_PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]);
|
||||
auto* PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+traits::reg_byte_offsets[traits::PC]);
|
||||
auto* NEXT_PC = reinterpret_cast<uint32_t*>(this->regs_base_ptr+traits::reg_byte_offsets[traits::NEXT_PC]);
|
||||
auto& trap_state = this->core.trap_state;
|
||||
auto& icount = this->core.icount;
|
||||
auto& cycle = this->core.cycle;
|
||||
|
@ -296,11 +224,11 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||
} else {
|
||||
if (is_jump_to_self_enabled(cond) &&
|
||||
(instr == 0x0000006f || (instr&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||
auto inst_id = decode_inst_id(instr);
|
||||
auto inst_id = static_cast<opcode_e>(decoder->decode_instruction(instr));
|
||||
// pre execution stuff
|
||||
if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, static_cast<unsigned>(inst_id));
|
||||
switch(inst_id){<%instructions.eachWithIndex{instr, idx -> %>
|
||||
case arch::traits<ARCH>::opcode_e::${instr.name}: {
|
||||
case opcode_e::${instr.name}: {
|
||||
<%instr.fields.eachLine{%>${it}
|
||||
<%}%>if(this->disass_enabled){
|
||||
/* generate console output when executing the command */<%instr.disass.eachLine{%>
|
||||
|
@ -308,8 +236,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
|
|||
}
|
||||
// used registers<%instr.usedVariables.each{ k,v->
|
||||
if(v.isArray) {%>
|
||||
auto* ${k} = reinterpret_cast<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}0]);<% }else{ %>
|
||||
auto* ${k} = reinterpret_cast<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}]);
|
||||
auto* ${k} = reinterpret_cast<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+traits::reg_byte_offsets[traits::${k}0]);<% }else{ %>
|
||||
auto* ${k} = reinterpret_cast<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+traits::reg_byte_offsets[traits::${k}]);
|
||||
<%}}%>// calculate next pc value
|
||||
*NEXT_PC = *PC + ${instr.length/8};
|
||||
// execute instruction<%instr.behavior.eachLine{%>
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <array>
|
||||
#include <iss/arch/traits.h>
|
||||
#include <iss/arch_if.h>
|
||||
#include <iss/arch/instruction_decoder.h>
|
||||
#include <iss/vm_if.h>
|
||||
|
||||
namespace iss {
|
||||
|
@ -176,6 +177,8 @@ template <> struct traits<tgc_c> {
|
|||
DII = 89,
|
||||
MAX_OPCODE
|
||||
};
|
||||
|
||||
static std::unique_ptr<instruction_decoder<tgc_c>> get_decoder();
|
||||
};
|
||||
|
||||
struct tgc_c: public arch_if {
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
#include "tgc_c.h"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
|
||||
namespace iss {
|
||||
namespace arch {
|
||||
namespace {
|
||||
// according to
|
||||
// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation
|
||||
#ifdef __GCC__
|
||||
constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); }
|
||||
#elif __cplusplus < 201402L
|
||||
constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); }
|
||||
constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; }
|
||||
#else
|
||||
constexpr size_t bit_count(uint32_t u) {
|
||||
size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
|
||||
return ((uCount + (uCount >> 3)) & 030707070707) % 63;
|
||||
}
|
||||
#endif
|
||||
|
||||
using opcode_e = traits<tgc_c>::opcode_e;
|
||||
|
||||
/****************************************************************************
|
||||
* start opcode definitions
|
||||
****************************************************************************/
|
||||
struct instruction_desriptor {
|
||||
size_t length;
|
||||
uint32_t value;
|
||||
uint32_t mask;
|
||||
opcode_e op;
|
||||
};
|
||||
|
||||
const std::array<instruction_desriptor, 90> instr_descr = {{
|
||||
/* entries are: size, valid value, valid mask, function ptr */
|
||||
{32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, opcode_e::LUI},
|
||||
{32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, opcode_e::AUIPC},
|
||||
{32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, opcode_e::JAL},
|
||||
{32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, opcode_e::JALR},
|
||||
{32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, opcode_e::BEQ},
|
||||
{32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, opcode_e::BNE},
|
||||
{32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, opcode_e::BLT},
|
||||
{32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, opcode_e::BGE},
|
||||
{32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, opcode_e::BLTU},
|
||||
{32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, opcode_e::BGEU},
|
||||
{32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, opcode_e::LB},
|
||||
{32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, opcode_e::LH},
|
||||
{32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, opcode_e::LW},
|
||||
{32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, opcode_e::LBU},
|
||||
{32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, opcode_e::LHU},
|
||||
{32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, opcode_e::SB},
|
||||
{32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, opcode_e::SH},
|
||||
{32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, opcode_e::SW},
|
||||
{32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, opcode_e::ADDI},
|
||||
{32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, opcode_e::SLTI},
|
||||
{32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, opcode_e::SLTIU},
|
||||
{32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, opcode_e::XORI},
|
||||
{32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, opcode_e::ORI},
|
||||
{32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, opcode_e::ANDI},
|
||||
{32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, opcode_e::SLLI},
|
||||
{32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, opcode_e::SRLI},
|
||||
{32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, opcode_e::SRAI},
|
||||
{32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::ADD},
|
||||
{32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::SUB},
|
||||
{32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, opcode_e::SLL},
|
||||
{32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, opcode_e::SLT},
|
||||
{32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, opcode_e::SLTU},
|
||||
{32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, opcode_e::XOR},
|
||||
{32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::SRL},
|
||||
{32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::SRA},
|
||||
{32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, opcode_e::OR},
|
||||
{32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, opcode_e::AND},
|
||||
{32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, opcode_e::FENCE},
|
||||
{32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, opcode_e::ECALL},
|
||||
{32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, opcode_e::EBREAK},
|
||||
{32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::URET},
|
||||
{32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::SRET},
|
||||
{32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::MRET},
|
||||
{32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, opcode_e::WFI},
|
||||
{32, 0b01111011001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::DRET},
|
||||
{32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRW},
|
||||
{32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRS},
|
||||
{32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRC},
|
||||
{32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRWI},
|
||||
{32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRSI},
|
||||
{32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRCI},
|
||||
{32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, opcode_e::FENCE_I},
|
||||
{32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::MUL},
|
||||
{32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, opcode_e::MULH},
|
||||
{32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, opcode_e::MULHSU},
|
||||
{32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, opcode_e::MULHU},
|
||||
{32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, opcode_e::DIV},
|
||||
{32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::DIVU},
|
||||
{32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, opcode_e::REM},
|
||||
{32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, opcode_e::REMU},
|
||||
{16, 0b0000000000000000, 0b1110000000000011, opcode_e::CADDI4SPN},
|
||||
{16, 0b0100000000000000, 0b1110000000000011, opcode_e::CLW},
|
||||
{16, 0b1100000000000000, 0b1110000000000011, opcode_e::CSW},
|
||||
{16, 0b0000000000000001, 0b1110000000000011, opcode_e::CADDI},
|
||||
{16, 0b0000000000000001, 0b1110111110000011, opcode_e::CNOP},
|
||||
{16, 0b0010000000000001, 0b1110000000000011, opcode_e::CJAL},
|
||||
{16, 0b0100000000000001, 0b1110000000000011, opcode_e::CLI},
|
||||
{16, 0b0110000000000001, 0b1110000000000011, opcode_e::CLUI},
|
||||
{16, 0b0110000100000001, 0b1110111110000011, opcode_e::CADDI16SP},
|
||||
{16, 0b0110000000000001, 0b1111000001111111, opcode_e::__reserved_clui},
|
||||
{16, 0b1000000000000001, 0b1111110000000011, opcode_e::CSRLI},
|
||||
{16, 0b1000010000000001, 0b1111110000000011, opcode_e::CSRAI},
|
||||
{16, 0b1000100000000001, 0b1110110000000011, opcode_e::CANDI},
|
||||
{16, 0b1000110000000001, 0b1111110001100011, opcode_e::CSUB},
|
||||
{16, 0b1000110000100001, 0b1111110001100011, opcode_e::CXOR},
|
||||
{16, 0b1000110001000001, 0b1111110001100011, opcode_e::COR},
|
||||
{16, 0b1000110001100001, 0b1111110001100011, opcode_e::CAND},
|
||||
{16, 0b1010000000000001, 0b1110000000000011, opcode_e::CJ},
|
||||
{16, 0b1100000000000001, 0b1110000000000011, opcode_e::CBEQZ},
|
||||
{16, 0b1110000000000001, 0b1110000000000011, opcode_e::CBNEZ},
|
||||
{16, 0b0000000000000010, 0b1111000000000011, opcode_e::CSLLI},
|
||||
{16, 0b0100000000000010, 0b1110000000000011, opcode_e::CLWSP},
|
||||
{16, 0b1000000000000010, 0b1111000000000011, opcode_e::CMV},
|
||||
{16, 0b1000000000000010, 0b1111000001111111, opcode_e::CJR},
|
||||
{16, 0b1000000000000010, 0b1111111111111111, opcode_e::__reserved_cmv},
|
||||
{16, 0b1001000000000010, 0b1111000000000011, opcode_e::CADD},
|
||||
{16, 0b1001000000000010, 0b1111000001111111, opcode_e::CJALR},
|
||||
{16, 0b1001000000000010, 0b1111111111111111, opcode_e::CEBREAK},
|
||||
{16, 0b1100000000000010, 0b1110000000000011, opcode_e::CSWSP},
|
||||
{16, 0b0000000000000000, 0b1111111111111111, opcode_e::DII},
|
||||
}};
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
struct instruction_decoder<tgc_c> {
|
||||
using opcode_e = traits<tgc_c>::opcode_e;
|
||||
using code_word_t=traits<tgc_c>::code_word_t;
|
||||
|
||||
struct instruction_pattern {
|
||||
uint32_t value;
|
||||
uint32_t mask;
|
||||
opcode_e id;
|
||||
};
|
||||
|
||||
std::array<std::vector<instruction_pattern>, 4> qlut;
|
||||
|
||||
template<typename T>
|
||||
unsigned decode_instruction(T);
|
||||
|
||||
instruction_decoder() {
|
||||
for (auto instr : instr_descr) {
|
||||
auto quadrant = instr.value & 0x3;
|
||||
qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op});
|
||||
}
|
||||
for(auto& lut: qlut){
|
||||
std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){
|
||||
return bit_count(a.mask) > bit_count(b.mask);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
unsigned instruction_decoder<tgc_c>::decode_instruction<traits<tgc_c>::code_word_t>(traits<tgc_c>::code_word_t instr){
|
||||
auto res = std::find_if(std::begin(qlut[instr&0x3]), std::end(qlut[instr&0x3]), [instr](instruction_pattern const& e){
|
||||
return !((instr&e.mask) ^ e.value );
|
||||
});
|
||||
return static_cast<unsigned>(res!=std::end(qlut[instr&0x3])? res->id : opcode_e::MAX_OPCODE);
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<instruction_decoder<tgc_c>> traits<tgc_c>::get_decoder(){
|
||||
return std::make_unique<instruction_decoder<tgc_c>>();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue