diff options
-rw-r--r-- | target/xtensa/cpu.h | 2 | ||||
-rw-r--r-- | target/xtensa/helper.c | 42 | ||||
-rw-r--r-- | target/xtensa/translate.c | 14 |
3 files changed, 42 insertions, 16 deletions
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 47d80a5..2765665 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -587,8 +587,6 @@ static inline void xtensa_select_static_vectors(CPUXtensaState *env, env->static_vectors = n; } void xtensa_runstall(CPUXtensaState *env, bool runstall); -XtensaOpcodeOps *xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t, - const char *opcode); #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt)) #define XTENSA_OPTION_ALL (~(uint64_t)0) diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c index 321ca42..57709fc 100644 --- a/target/xtensa/helper.c +++ b/target/xtensa/helper.c @@ -30,10 +30,52 @@ #include "exec/exec-all.h" #include "exec/gdbstub.h" #include "exec/helper-proto.h" +#include "qemu/error-report.h" #include "qemu/host-utils.h" static struct XtensaConfigList *xtensa_cores; +static void add_translator_to_hash(GHashTable *translator, + const char *name, + const XtensaOpcodeOps *opcode) +{ + if (!g_hash_table_insert(translator, (void *)name, (void *)opcode)) { + error_report("Multiple definitions of '%s' opcode in a single table", + name); + } +} + +static GHashTable *hash_opcode_translators(const XtensaOpcodeTranslators *t) +{ + unsigned i, j; + GHashTable *translator = g_hash_table_new(g_str_hash, g_str_equal); + + for (i = 0; i < t->num_opcodes; ++i) { + add_translator_to_hash(translator, + (void *)t->opcode[i].name, + (void *)(t->opcode + i)); + } + return translator; +} + +static XtensaOpcodeOps * +xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t, + const char *name) +{ + static GHashTable *translators; + GHashTable *translator; + + if (translators == NULL) { + translators = g_hash_table_new(g_direct_hash, g_direct_equal); + } + translator = g_hash_table_lookup(translators, t); + if (translator == NULL) { + translator = hash_opcode_translators(t); + g_hash_table_insert(translators, (void *)t, translator); + } + return g_hash_table_lookup(translator, name); +} + static void init_libisa(XtensaConfig *config) { unsigned i, j; diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 62283cd..26342aa 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1274,20 +1274,6 @@ void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, env->pc = data[0]; } -static int compare_opcode_ops(const void *a, const void *b) -{ - return strcmp((const char *)a, - ((const XtensaOpcodeOps *)b)->name); -} - -XtensaOpcodeOps * -xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t, - const char *name) -{ - return bsearch(name, t->opcode, t->num_opcodes, - sizeof(XtensaOpcodeOps), compare_opcode_ops); -} - static void translate_abs(DisasContext *dc, const uint32_t arg[], const uint32_t par[]) { |