summaryrefslogtreecommitdiff
path: root/target/xtensa/helper.c
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2017-11-03 19:44:46 -0700
committerMax Filippov <jcmvbkbc@gmail.com>2018-01-09 09:55:38 -0800
commit33071f6888913ef2c6600e827bf63bbb86e249a8 (patch)
tree9ad73974941e506cc138f6489d3de6b36529504c /target/xtensa/helper.c
parent502d0f361b690df7d5b19ed8869d7f465fd51ed1 (diff)
downloadqemu-33071f6888913ef2c6600e827bf63bbb86e249a8.zip
target/xtensa: use libisa for instruction decoding
Replace manual opcode analysis with libisa-based code. This makes it possible to support variable-encoding instructions of the core ISA, like const16, and will allow to support advanced Xtensa features, like FLIX and TIE. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'target/xtensa/helper.c')
-rw-r--r--target/xtensa/helper.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index 216f1988aa..5009fecedc 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -52,10 +52,47 @@ static void xtensa_core_class_init(ObjectClass *oc, void *data)
cc->gdb_num_core_regs = config->gdb_regmap.num_regs;
}
+static void init_libisa(XtensaConfig *config)
+{
+ unsigned i, j;
+ unsigned opcodes;
+
+ config->isa = xtensa_isa_init(config->isa_internal, NULL, NULL);
+ assert(xtensa_isa_maxlength(config->isa) <= MAX_INSN_LENGTH);
+ opcodes = xtensa_isa_num_opcodes(config->isa);
+ config->opcode_ops = g_new(XtensaOpcodeOps *, opcodes);
+
+ for (i = 0; i < opcodes; ++i) {
+ const char *opc_name = xtensa_opcode_name(config->isa, i);
+ XtensaOpcodeOps *ops = NULL;
+
+ assert(xtensa_opcode_num_operands(config->isa, i) <= MAX_OPCODE_ARGS);
+ if (!config->opcode_translators) {
+ ops = xtensa_find_opcode_ops(&xtensa_core_opcodes, opc_name);
+ } else {
+ for (j = 0; !ops && config->opcode_translators[j]; ++j) {
+ ops = xtensa_find_opcode_ops(config->opcode_translators[j],
+ opc_name);
+ }
+ }
+#ifdef DEBUG
+ if (ops == NULL) {
+ fprintf(stderr,
+ "opcode translator not found for %s's opcode '%s'\n",
+ config->name, opc_name);
+ }
+#endif
+ config->opcode_ops[i] = ops;
+ }
+}
+
void xtensa_finalize_config(XtensaConfig *config)
{
unsigned i, n = 0;
+ if (config->isa_internal) {
+ init_libisa(config);
+ }
if (config->gdb_regmap.num_regs) {
return;
}