@@ -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 ()
@@ -146,6 +147,7 @@ void processor_t::enable_log_commits()
146147{
147148 log_commits_enabled = true ;
148149 mmu->flush_tlb (); // the TLB caches this setting
150+ build_opcode_map ();
149151}
150152
151153void processor_t::reset ()
@@ -662,47 +664,48 @@ reg_t processor_t::throw_instruction_address_misaligned(reg_t pc)
662664
663665insn_func_t processor_t::decode_insn (insn_t insn)
664666{
665- if (!extension_enabled (EXT_ZCA) && insn_length (insn.bits ()) % 4 )
666- return &::illegal_instruction;
667-
668- // look up opcode in hash table
669- size_t idx = insn.bits () % OPCODE_CACHE_SIZE;
670- auto [hit, desc] = opcode_cache[idx].lookup (insn.bits ());
667+ const auto & pool = opcode_map[insn.bits () % std::size (opcode_map)];
671668
672- bool rve = extension_enabled (' E' );
673-
674- if (unlikely (!hit)) {
675- // fall back to linear search
676- auto matching = [insn_bits = insn.bits ()](const insn_desc_t &d) {
677- return (insn_bits & d.mask ) == d.match ;
678- };
679- auto p = std::find_if (custom_instructions.begin (),
680- custom_instructions.end (), matching);
681- if (p == custom_instructions.end ()) {
682- p = std::find_if (instructions.begin (), instructions.end (), matching);
683- assert (p != instructions.end ());
669+ for (auto p = pool.begin (); ; ++p) {
670+ if ((insn.bits () & p->mask ) == p->match ) {
671+ return p->func ;
684672 }
685- desc = &*p;
686- opcode_cache[idx].replace (insn.bits (), desc);
687673 }
688-
689- return desc->func (xlen, rve, log_commits_enabled);
690674}
691675
692- 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 ) {
693677 assert (desc.fast_rv32i && desc.fast_rv64i && desc.fast_rv32e && desc.fast_rv64e &&
694678 desc.logged_rv32i && desc.logged_rv64i && desc.logged_rv32e && desc.logged_rv64e );
695679
696- if (is_custom)
697- custom_instructions.push_back (desc);
698- else
699- instructions.push_back (desc);
680+ pool.push_back (desc);
700681}
701682
702683void processor_t::build_opcode_map ()
703684{
704- for (size_t i = 0 ; i < OPCODE_CACHE_SIZE; i++)
705- 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);
706709}
707710
708711void processor_t::register_extension (extension_t *x) {
0 commit comments