@@ -62,13 +62,8 @@ processor_t::processor_t(const char* isa_str, const char* priv_str,
6262 VU.vlenb = isa.get_vlen () / 8 ;
6363 VU.vstart_alu = 0 ;
6464
65- register_base_instructions ();
6665 mmu = new mmu_t (sim, cfg->endianness , this , cfg->cache_blocksz );
6766
68- disassembler = new disassembler_t (&isa);
69- for (auto e : isa.get_extensions ())
70- register_extension (find_extension (e.c_str ())());
71-
7267 set_pmp_granularity (cfg->pmpgranularity );
7368 set_pmp_num (cfg->pmpregions );
7469
@@ -81,6 +76,12 @@ processor_t::processor_t(const char* isa_str, const char* priv_str,
8176 set_impl (IMPL_MMU_VMID, true );
8277
8378 reset ();
79+
80+ register_base_instructions ();
81+
82+ disassembler = new disassembler_t (&isa);
83+ for (auto e : isa.get_extensions ())
84+ register_extension (find_extension (e.c_str ())());
8485}
8586
8687processor_t ::~processor_t ()
@@ -663,47 +664,48 @@ reg_t processor_t::throw_instruction_address_misaligned(reg_t pc)
663664
664665insn_func_t processor_t::decode_insn (insn_t insn)
665666{
666- if (!extension_enabled (EXT_ZCA) && insn_length (insn.bits ()) % 4 )
667- return &::illegal_instruction;
668-
669- // look up opcode in hash table
670- size_t idx = insn.bits () % OPCODE_CACHE_SIZE;
671- auto [hit, desc] = opcode_cache[idx].lookup (insn.bits ());
667+ const auto & pool = opcode_map[insn.bits () % std::size (opcode_map)];
672668
673- bool rve = extension_enabled (' E' );
674-
675- if (unlikely (!hit)) {
676- // fall back to linear search
677- auto matching = [insn_bits = insn.bits ()](const insn_desc_t &d) {
678- return (insn_bits & d.mask ) == d.match ;
679- };
680- auto p = std::find_if (custom_instructions.begin (),
681- custom_instructions.end (), matching);
682- if (p == custom_instructions.end ()) {
683- p = std::find_if (instructions.begin (), instructions.end (), matching);
684- assert (p != instructions.end ());
669+ for (auto p = pool.begin (); ; ++p) {
670+ if ((insn.bits () & p->mask ) == p->match ) {
671+ return p->func ;
685672 }
686- desc = &*p;
687- opcode_cache[idx].replace (insn.bits (), desc);
688673 }
689-
690- return desc->func (xlen, rve, log_commits_enabled);
691674}
692675
693- void processor_t::register_insn (insn_desc_t desc, bool is_custom ) {
676+ void processor_t::register_insn (insn_desc_t desc, std::vector< insn_desc_t >& pool ) {
694677 assert (desc.fast_rv32i && desc.fast_rv64i && desc.fast_rv32e && desc.fast_rv64e &&
695678 desc.logged_rv32i && desc.logged_rv64i && desc.logged_rv32e && desc.logged_rv64e );
696679
697- if (is_custom)
698- custom_instructions.push_back (desc);
699- else
700- instructions.push_back (desc);
680+ pool.push_back (desc);
701681}
702682
703683void processor_t::build_opcode_map ()
704684{
705- for (size_t i = 0 ; i < OPCODE_CACHE_SIZE; i++)
706- opcode_cache[i].reset ();
685+ bool rve = extension_enabled (' E' );
686+ bool zca = extension_enabled (EXT_ZCA);
687+ const size_t N = std::size (opcode_map);
688+
689+ auto build_one = [&](const insn_desc_t & desc) {
690+ auto func = desc.func (xlen, rve, log_commits_enabled);
691+ if (!zca && insn_length (desc.match ) % 4 )
692+ func = &::illegal_instruction;
693+
694+ auto stride = std::min (N, size_t (1 ) << ctz (~desc.mask ));
695+ for (size_t i = desc.match & (stride - 1 ); i < N; i += stride) {
696+ if ((desc.match % N) == (i & desc.mask ))
697+ opcode_map[i].push_back ({desc.match , desc.mask , func});
698+ }
699+ };
700+
701+ for (auto & p : opcode_map)
702+ p.clear ();
703+
704+ for (auto & d : custom_instructions)
705+ build_one (d);
706+
707+ for (auto & d : instructions)
708+ build_one (d);
707709}
708710
709711void processor_t::register_extension (extension_t *x) {
0 commit comments