#include "${coreDef.name.toLowerCase()}.h" #include #include #include #include namespace iss { namespace arch { namespace { // according to // https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation #ifdef __GCC__ constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); } #elif __cplusplus < 201402L constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); } constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; } #else constexpr size_t bit_count(uint32_t u) { size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); return ((uCount + (uCount >> 3)) & 030707070707) % 63; } #endif using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e; /**************************************************************************** * start opcode definitions ****************************************************************************/ struct instruction_desriptor { size_t length; uint32_t value; uint32_t mask; opcode_e op; }; const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %> {${instr.length}, ${instr.encoding}, ${instr.mask}, opcode_e::${instr.instruction.name}},<%}%> }}; } template<> struct instruction_decoder<${coreDef.name.toLowerCase()}> { using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e; using code_word_t=traits<${coreDef.name.toLowerCase()}>::code_word_t; struct instruction_pattern { uint32_t value; uint32_t mask; opcode_e id; }; std::array, 4> qlut; template unsigned decode_instruction(T); instruction_decoder() { for (auto instr : instr_descr) { auto quadrant = instr.value & 0x3; qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op}); } for(auto& lut: qlut){ std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){ return bit_count(a.mask) < bit_count(b.mask); }); } } }; template<> unsigned instruction_decoder<${coreDef.name.toLowerCase()}>::decode_instruction::code_word_t>(traits<${coreDef.name.toLowerCase()}>::code_word_t instr){ auto res = std::find_if(std::begin(qlut[instr&0x3]), std::end(qlut[instr&0x3]), [instr](instruction_pattern const& e){ return !((instr&e.mask) ^ e.value ); }); return static_cast(res!=std::end(qlut[instr&0x3])? res->id : opcode_e::MAX_OPCODE); } std::unique_ptr> traits<${coreDef.name.toLowerCase()}>::get_decoder(){ return std::make_unique>(); } } }