@@ -1037,6 +1037,24 @@ reg_t illegal_instruction(processor_t UNUSED *p, insn_t insn, reg_t UNUSED pc)
10371037 throw trap_illegal_instruction (insn.bits () & 0xffffffffULL );
10381038}
10391039
1040+ static insn_desc_t
1041+ propagate_instruction_in_vector (std::vector<insn_desc_t > &instructions,
1042+ std::vector<insn_desc_t >::iterator it) {
1043+ assert (it != instructions.end ());
1044+ insn_desc_t desc = *it;
1045+ if (it->mask != 0 && it != instructions.begin () &&
1046+ std::next (it) != instructions.end ()) {
1047+ if (it->match != std::prev (it)->match &&
1048+ it->match != std::next (it)->match ) {
1049+ // move to front of opcode list to reduce miss penalty
1050+ while (--it >= instructions.begin ())
1051+ *std::next (it) = *it;
1052+ instructions[0 ] = desc;
1053+ }
1054+ }
1055+ return desc;
1056+ }
1057+
10401058insn_func_t processor_t::decode_insn (insn_t insn)
10411059{
10421060 // look up opcode in hash table
@@ -1047,34 +1065,33 @@ insn_func_t processor_t::decode_insn(insn_t insn)
10471065
10481066 if (unlikely (insn.bits () != desc.match )) {
10491067 // fall back to linear search
1050- int cnt = 0 ;
1051- insn_desc_t * p = &instructions[0 ];
1052- while ((insn.bits () & p->mask ) != p->match )
1053- p++, cnt++;
1054- desc = *p;
1055-
1056- if (p->mask != 0 && p > &instructions[0 ]) {
1057- if (p->match != (p - 1 )->match && p->match != (p + 1 )->match ) {
1058- // move to front of opcode list to reduce miss penalty
1059- while (--p >= &instructions[0 ])
1060- *(p + 1 ) = *p;
1061- instructions[0 ] = desc;
1062- }
1068+ auto matching = [insn_bits = insn.bits ()](const insn_desc_t &d) {
1069+ return (insn_bits & d.mask ) == d.match ;
1070+ };
1071+ auto p = std::find_if (custom_instructions.begin (),
1072+ custom_instructions.end (), matching);
1073+ if (p != custom_instructions.end ()) {
1074+ desc = propagate_instruction_in_vector (custom_instructions, p);
1075+ } else {
1076+ p = std::find_if (instructions.begin (), instructions.end (), matching);
1077+ assert (p != instructions.end ());
1078+ desc = propagate_instruction_in_vector (instructions, p);
10631079 }
1064-
10651080 opcode_cache[idx] = desc;
10661081 opcode_cache[idx].match = insn.bits ();
10671082 }
10681083
10691084 return desc.func (xlen, rve, log_commits_enabled);
10701085}
10711086
1072- void processor_t::register_insn (insn_desc_t desc)
1073- {
1087+ void processor_t::register_insn (insn_desc_t desc, bool is_custom) {
10741088 assert (desc.fast_rv32i && desc.fast_rv64i && desc.fast_rv32e && desc.fast_rv64e &&
10751089 desc.logged_rv32i && desc.logged_rv64i && desc.logged_rv32e && desc.logged_rv64e );
10761090
1077- instructions.push_back (desc);
1091+ if (is_custom)
1092+ custom_instructions.push_back (desc);
1093+ else
1094+ instructions.push_back (desc);
10781095}
10791096
10801097void processor_t::build_opcode_map ()
@@ -1086,16 +1103,17 @@ void processor_t::build_opcode_map()
10861103 return lhs.match > rhs.match ;
10871104 }
10881105 };
1106+
10891107 std::sort (instructions.begin (), instructions.end (), cmp ());
1108+ std::sort (custom_instructions.begin (), custom_instructions.end (), cmp ());
10901109
10911110 for (size_t i = 0 ; i < OPCODE_CACHE_SIZE; i++)
10921111 opcode_cache[i] = insn_desc_t::illegal ();
10931112}
10941113
1095- void processor_t::register_extension (extension_t * x)
1096- {
1114+ void processor_t::register_extension (extension_t *x) {
10971115 for (auto insn : x->get_instructions ())
1098- register_insn (insn);
1116+ register_custom_insn (insn);
10991117 build_opcode_map ();
11001118
11011119 for (auto disasm_insn : x->get_disasms ())
@@ -1131,7 +1149,7 @@ void processor_t::register_base_instructions()
11311149 extern reg_t logged_rv32e_##name (processor_t *, insn_t , reg_t ); \
11321150 extern reg_t logged_rv64e_##name (processor_t *, insn_t , reg_t ); \
11331151 if (name##_supported) { \
1134- register_insn ((insn_desc_t ) { \
1152+ register_base_insn ((insn_desc_t ) { \
11351153 name##_match, \
11361154 name##_mask, \
11371155 fast_rv32i_##name, \
@@ -1144,10 +1162,8 @@ void processor_t::register_base_instructions()
11441162 logged_rv64e_##name}); \
11451163 }
11461164 #include " insn_list.h"
1147- #undef DEFINE_INSN
1148-
11491165 // terminate instruction list with a catch-all
1150- register_insn (insn_desc_t::illegal ());
1166+ register_base_insn (insn_desc_t::illegal ());
11511167
11521168 build_opcode_map ();
11531169}
0 commit comments