87 lines
3.0 KiB
Plaintext
87 lines
3.0 KiB
Plaintext
|
#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()}>>();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|