aboutsummaryrefslogtreecommitdiff
path: root/target/xtensa/helper.c
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2019-02-09 23:21:44 -0800
committerMax Filippov <jcmvbkbc@gmail.com>2019-02-18 21:29:08 -0800
commit759039737504c3f11098f7240c6048c6279e2215 (patch)
treebdedf02668294fdfc0d1bd5f5aa9894ee2f6d3bd /target/xtensa/helper.c
parent0e7c887919e44f25491a4eb86403e947d9d54937 (diff)
downloadqemu-759039737504c3f11098f7240c6048c6279e2215.zip
qemu-759039737504c3f11098f7240c6048c6279e2215.tar.gz
qemu-759039737504c3f11098f7240c6048c6279e2215.tar.bz2
target/xtensa: don't require opcode table sorting
Requirement for alphabetical opcode sorting in opcode tables is awkward and does not allow sharing implementation between multiple opcodes. Use hash tables to find opcodes by name. Move implementation from the translate.c to the helper.c to its only user and remove declaration from the cpu.h Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'target/xtensa/helper.c')
-rw-r--r--target/xtensa/helper.c42
1 files changed, 42 insertions, 0 deletions
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;