* [Qemu-devel] [PATCH 01/13] target/xtensa: move xtensa_finalize_config to xtensa_core_class_init
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 02/13] target/xtensa: don't require opcode table sorting Max Filippov
` (11 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
Don't run xtensa_finalize_config at the time of core registration,
instead run it at the CPU class initialization.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/cpu.h | 1 -
target/xtensa/helper.c | 36 +++++++++++++++++++-----------------
target/xtensa/overlay_tool.h | 1 -
3 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index f1861244720e..47d80a59e2f5 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -566,7 +566,6 @@ void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
void xtensa_translate_init(void);
void xtensa_breakpoint_handler(CPUState *cs);
-void xtensa_finalize_config(XtensaConfig *config);
void xtensa_register_core(XtensaConfigList *node);
void xtensa_sim_open_console(Chardev *chr);
void check_interrupts(CPUXtensaState *s);
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index 6cf1dbb8a69b..321ca4295521 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -34,22 +34,6 @@
static struct XtensaConfigList *xtensa_cores;
-static void xtensa_core_class_init(ObjectClass *oc, void *data)
-{
- CPUClass *cc = CPU_CLASS(oc);
- XtensaCPUClass *xcc = XTENSA_CPU_CLASS(oc);
- const XtensaConfig *config = data;
-
- xcc->config = config;
-
- /* Use num_core_regs to see only non-privileged registers in an unmodified
- * gdb. Use num_regs to see all registers. gdb modification is required
- * for that: reset bit 0 in the 'flags' field of the registers definitions
- * in the gdb/xtensa-config.c inside gdb source tree or inside gdb overlay.
- */
- cc->gdb_num_core_regs = config->gdb_regmap.num_regs;
-}
-
static void init_libisa(XtensaConfig *config)
{
unsigned i, j;
@@ -91,7 +75,7 @@ static void init_libisa(XtensaConfig *config)
config->a_regfile = xtensa_regfile_lookup(config->isa, "AR");
}
-void xtensa_finalize_config(XtensaConfig *config)
+static void xtensa_finalize_config(XtensaConfig *config)
{
if (config->isa_internal) {
init_libisa(config);
@@ -112,6 +96,24 @@ void xtensa_finalize_config(XtensaConfig *config)
}
}
+static void xtensa_core_class_init(ObjectClass *oc, void *data)
+{
+ CPUClass *cc = CPU_CLASS(oc);
+ XtensaCPUClass *xcc = XTENSA_CPU_CLASS(oc);
+ XtensaConfig *config = data;
+
+ xtensa_finalize_config(config);
+ xcc->config = config;
+
+ /*
+ * Use num_core_regs to see only non-privileged registers in an unmodified
+ * gdb. Use num_regs to see all registers. gdb modification is required
+ * for that: reset bit 0 in the 'flags' field of the registers definitions
+ * in the gdb/xtensa-config.c inside gdb source tree or inside gdb overlay.
+ */
+ cc->gdb_num_core_regs = config->gdb_regmap.num_regs;
+}
+
void xtensa_register_core(XtensaConfigList *node)
{
TypeInfo type = {
diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h
index 12609a0d0c1e..ea07576bc921 100644
--- a/target/xtensa/overlay_tool.h
+++ b/target/xtensa/overlay_tool.h
@@ -377,7 +377,6 @@
static XtensaConfigList node = { \
.config = &core, \
}; \
- xtensa_finalize_config(&core); \
xtensa_register_core(&node); \
}
#else
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 02/13] target/xtensa: don't require opcode table sorting
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 01/13] target/xtensa: move xtensa_finalize_config to xtensa_core_class_init Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 03/13] target/xtensa: allow multiple names for single opcode Max Filippov
` (10 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
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>
---
target/xtensa/cpu.h | 2 --
target/xtensa/helper.c | 42 ++++++++++++++++++++++++++++++++++++++++++
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 47d80a59e2f5..2765665ceca6 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 321ca4295521..57709fc20caf 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 62283cd1ccc8..26342aaa1f82 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[])
{
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 03/13] target/xtensa: allow multiple names for single opcode
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 01/13] target/xtensa: move xtensa_finalize_config to xtensa_core_class_init Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 02/13] target/xtensa: don't require opcode table sorting Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 04/13] target/xtensa: implement wide branches and loops Max Filippov
` (9 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
There are opcodes that differ only in encoding or possible range of
immediate arguments. Allow multiple names for single opcode translation
table entry to reduce code duplication in that case.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/cpu.h | 4 +-
target/xtensa/helper.c | 16 ++++++--
target/xtensa/translate.c | 100 ++++++++++++++++++++--------------------------
3 files changed, 60 insertions(+), 60 deletions(-)
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 2765665ceca6..db8ee70a0386 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -371,10 +371,12 @@ enum {
XTENSA_OP_CHECK_INTERRUPTS = 0x200,
XTENSA_OP_EXIT_TB_M1 = 0x400,
XTENSA_OP_EXIT_TB_0 = 0x800,
+
+ XTENSA_OP_NAME_ARRAY = 0x8000,
};
typedef struct XtensaOpcodeOps {
- const char *name;
+ const void *name;
XtensaOpcodeOp translate;
XtensaOpcodeBoolTest test_ill;
XtensaOpcodeUintTest test_overflow;
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index 57709fc20caf..7008c6390d20 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -51,9 +51,19 @@ static GHashTable *hash_opcode_translators(const XtensaOpcodeTranslators *t)
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));
+ if (t->opcode[i].op_flags & XTENSA_OP_NAME_ARRAY) {
+ const char * const *name = t->opcode[i].name;
+
+ for (j = 0; name[j]; ++j) {
+ add_translator_to_hash(translator,
+ (void *)name[j],
+ (void *)(t->opcode + i));
+ }
+ } else {
+ add_translator_to_hash(translator,
+ (void *)t->opcode[i].name,
+ (void *)(t->opcode + i));
+ }
}
return translator;
}
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 26342aaa1f82..1b730781ec05 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -2409,17 +2409,17 @@ static const XtensaOpcodeOps core_ops[] = {
.name = "abs",
.translate = translate_abs,
}, {
- .name = "add",
+ .name = (const char * const[]) {
+ "add", "add.n", NULL,
+ },
.translate = translate_add,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "add.n",
- .translate = translate_add,
- }, {
- .name = "addi",
- .translate = translate_addi,
- }, {
- .name = "addi.n",
+ .name = (const char * const[]) {
+ "addi", "addi.n", NULL,
+ },
.translate = translate_addi,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "addmi",
.translate = translate_addi,
@@ -2495,13 +2495,12 @@ static const XtensaOpcodeOps core_ops[] = {
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_EQ},
}, {
- .name = "beqz",
- .translate = translate_bz,
- .par = (const uint32_t[]){TCG_COND_EQ},
- }, {
- .name = "beqz.n",
+ .name = (const char * const[]) {
+ "beqz", "beqz.n", NULL,
+ },
.translate = translate_bz,
.par = (const uint32_t[]){TCG_COND_EQ},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "bf",
.translate = translate_bp,
@@ -2559,13 +2558,12 @@ static const XtensaOpcodeOps core_ops[] = {
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_NE},
}, {
- .name = "bnez",
- .translate = translate_bz,
- .par = (const uint32_t[]){TCG_COND_NE},
- }, {
- .name = "bnez.n",
+ .name = (const char * const[]) {
+ "bnez", "bnez.n", NULL,
+ },
.translate = translate_bz,
.par = (const uint32_t[]){TCG_COND_NE},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "bnone",
.translate = translate_bany,
@@ -2725,11 +2723,10 @@ static const XtensaOpcodeOps core_ops[] = {
.translate = translate_nop,
.op_flags = XTENSA_OP_PRIVILEGED,
}, {
- .name = "ill",
- .op_flags = XTENSA_OP_ILL,
- }, {
- .name = "ill.n",
- .op_flags = XTENSA_OP_ILL,
+ .name = (const char * const[]) {
+ "ill", "ill.n", NULL,
+ },
+ .op_flags = XTENSA_OP_ILL | XTENSA_OP_NAME_ARRAY,
}, {
.name = "ipf",
.translate = translate_nop,
@@ -2763,13 +2760,12 @@ static const XtensaOpcodeOps core_ops[] = {
.translate = translate_l32e,
.op_flags = XTENSA_OP_PRIVILEGED,
}, {
- .name = "l32i",
- .translate = translate_ldst,
- .par = (const uint32_t[]){MO_TEUL, false, false},
- }, {
- .name = "l32i.n",
+ .name = (const char * const[]) {
+ "l32i", "l32i.n", NULL,
+ },
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, false, false},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "l32r",
.translate = translate_l32r,
@@ -2816,11 +2812,11 @@ static const XtensaOpcodeOps core_ops[] = {
.name = "minu",
.translate = translate_umin,
}, {
- .name = "mov",
- .translate = translate_mov,
- }, {
- .name = "mov.n",
+ .name = (const char * const[]) {
+ "mov", "mov.n", NULL,
+ },
.translate = translate_mov,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "moveqz",
.translate = translate_movcond,
@@ -3134,11 +3130,11 @@ static const XtensaOpcodeOps core_ops[] = {
.name = "neg",
.translate = translate_neg,
}, {
- .name = "nop",
- .translate = translate_nop,
- }, {
- .name = "nop.n",
+ .name = (const char * const[]) {
+ "nop", "nop.n", NULL,
+ },
.translate = translate_nop,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "nsa",
.translate = translate_nsa,
@@ -3202,21 +3198,18 @@ static const XtensaOpcodeOps core_ops[] = {
.translate = translate_rer,
.op_flags = XTENSA_OP_PRIVILEGED,
}, {
- .name = "ret",
+ .name = (const char * const[]) {
+ "ret", "ret.n", NULL,
+ },
.translate = translate_ret,
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "ret.n",
- .translate = translate_ret,
- }, {
- .name = "retw",
+ .name = (const char * const[]) {
+ "retw", "retw.n", NULL,
+ },
.translate = translate_retw,
.test_ill = test_ill_retw,
- .op_flags = XTENSA_OP_UNDERFLOW,
- }, {
- .name = "retw.n",
- .translate = translate_retw,
- .test_ill = test_ill_retw,
- .op_flags = XTENSA_OP_UNDERFLOW,
+ .op_flags = XTENSA_OP_UNDERFLOW | XTENSA_OP_NAME_ARRAY,
}, {
.name = "rfdd",
.op_flags = XTENSA_OP_ILL,
@@ -3742,17 +3735,12 @@ static const XtensaOpcodeOps core_ops[] = {
.translate = translate_s32e,
.op_flags = XTENSA_OP_PRIVILEGED,
}, {
- .name = "s32i",
- .translate = translate_ldst,
- .par = (const uint32_t[]){MO_TEUL, false, true},
- }, {
- .name = "s32i.n",
- .translate = translate_ldst,
- .par = (const uint32_t[]){MO_TEUL, false, true},
- }, {
- .name = "s32nb",
+ .name = (const char * const[]) {
+ "s32i", "s32i.n", "s32nb", NULL,
+ },
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, false, true},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "s32ri",
.translate = translate_ldst,
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 04/13] target/xtensa: implement wide branches and loops
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
` (2 preceding siblings ...)
2019-02-14 22:59 ` [Qemu-devel] [PATCH 03/13] target/xtensa: allow multiple names for single opcode Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 05/13] target/xtensa: sort FLIX instruction opcodes Max Filippov
` (8 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
FLIX adds branch and loop instruction variants with 15- and 18-bit wide
target offset. Implement them as additional names for the ordinary
branch/loop opcodes.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/translate.c | 129 ++++++++++++++++++++++++++++++++++++----------
1 file changed, 102 insertions(+), 27 deletions(-)
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 1b730781ec05..e8dddd32b3af 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -2463,40 +2463,64 @@ static const XtensaOpcodeOps core_ops[] = {
.translate = translate_all,
.par = (const uint32_t[]){false, 8},
}, {
- .name = "ball",
+ .name = (const char * const[]) {
+ "ball", "ball.w15", "ball.w18", NULL,
+ },
.translate = translate_ball,
.par = (const uint32_t[]){TCG_COND_EQ},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bany",
+ .name = (const char * const[]) {
+ "bany", "bany.w15", "bany.w18", NULL,
+ },
.translate = translate_bany,
.par = (const uint32_t[]){TCG_COND_NE},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bbc",
+ .name = (const char * const[]) {
+ "bbc", "bbc.w15", "bbc.w18", NULL,
+ },
.translate = translate_bb,
.par = (const uint32_t[]){TCG_COND_EQ},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bbci",
+ .name = (const char * const[]) {
+ "bbci", "bbci.w15", "bbci.w18", NULL,
+ },
.translate = translate_bbi,
.par = (const uint32_t[]){TCG_COND_EQ},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bbs",
+ .name = (const char * const[]) {
+ "bbs", "bbs.w15", "bbs.w18", NULL,
+ },
.translate = translate_bb,
.par = (const uint32_t[]){TCG_COND_NE},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bbsi",
+ .name = (const char * const[]) {
+ "bbsi", "bbsi.w15", "bbsi.w18", NULL,
+ },
.translate = translate_bbi,
.par = (const uint32_t[]){TCG_COND_NE},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "beq",
+ .name = (const char * const[]) {
+ "beq", "beq.w15", "beq.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_EQ},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "beqi",
+ .name = (const char * const[]) {
+ "beqi", "beqi.w15", "beqi.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_EQ},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = (const char * const[]) {
- "beqz", "beqz.n", NULL,
+ "beqz", "beqz.n", "beqz.w15", "beqz.w18", NULL,
},
.translate = translate_bz,
.par = (const uint32_t[]){TCG_COND_EQ},
@@ -2506,68 +2530,110 @@ static const XtensaOpcodeOps core_ops[] = {
.translate = translate_bp,
.par = (const uint32_t[]){TCG_COND_EQ},
}, {
- .name = "bge",
+ .name = (const char * const[]) {
+ "bge", "bge.w15", "bge.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_GE},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bgei",
+ .name = (const char * const[]) {
+ "bgei", "bgei.w15", "bgei.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_GE},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bgeu",
+ .name = (const char * const[]) {
+ "bgeu", "bgeu.w15", "bgeu.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_GEU},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bgeui",
+ .name = (const char * const[]) {
+ "bgeui", "bgeui.w15", "bgeui.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_GEU},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bgez",
+ .name = (const char * const[]) {
+ "bgez", "bgez.w15", "bgez.w18", NULL,
+ },
.translate = translate_bz,
.par = (const uint32_t[]){TCG_COND_GE},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "blt",
+ .name = (const char * const[]) {
+ "blt", "blt.w15", "blt.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_LT},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "blti",
+ .name = (const char * const[]) {
+ "blti", "blti.w15", "blti.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_LT},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bltu",
+ .name = (const char * const[]) {
+ "bltu", "bltu.w15", "bltu.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_LTU},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bltui",
+ .name = (const char * const[]) {
+ "bltui", "bltui.w15", "bltui.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_LTU},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bltz",
+ .name = (const char * const[]) {
+ "bltz", "bltz.w15", "bltz.w18", NULL,
+ },
.translate = translate_bz,
.par = (const uint32_t[]){TCG_COND_LT},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bnall",
+ .name = (const char * const[]) {
+ "bnall", "bnall.w15", "bnall.w18", NULL,
+ },
.translate = translate_ball,
.par = (const uint32_t[]){TCG_COND_NE},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bne",
+ .name = (const char * const[]) {
+ "bne", "bne.w15", "bne.w18", NULL,
+ },
.translate = translate_b,
.par = (const uint32_t[]){TCG_COND_NE},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bnei",
+ .name = (const char * const[]) {
+ "bnei", "bnei.w15", "bnei.w18", NULL,
+ },
.translate = translate_bi,
.par = (const uint32_t[]){TCG_COND_NE},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = (const char * const[]) {
- "bnez", "bnez.n", NULL,
+ "bnez", "bnez.n", "bnez.w15", "bnez.w18", NULL,
},
.translate = translate_bz,
.par = (const uint32_t[]){TCG_COND_NE},
.op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "bnone",
+ .name = (const char * const[]) {
+ "bnone", "bnone.w15", "bnone.w18", NULL,
+ },
.translate = translate_bany,
.par = (const uint32_t[]){TCG_COND_EQ},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "break",
.translate = translate_nop,
@@ -2785,17 +2851,26 @@ static const XtensaOpcodeOps core_ops[] = {
.name = "ldpte",
.op_flags = XTENSA_OP_ILL,
}, {
- .name = "loop",
+ .name = (const char * const[]) {
+ "loop", "loop.w15", NULL,
+ },
.translate = translate_loop,
.par = (const uint32_t[]){TCG_COND_NEVER},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "loopgtz",
+ .name = (const char * const[]) {
+ "loopgtz", "loopgtz.w15", NULL,
+ },
.translate = translate_loop,
.par = (const uint32_t[]){TCG_COND_GT},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
- .name = "loopnez",
+ .name = (const char * const[]) {
+ "loopnez", "loopnez.w15", NULL,
+ },
.translate = translate_loop,
.par = (const uint32_t[]){TCG_COND_NE},
+ .op_flags = XTENSA_OP_NAME_ARRAY,
}, {
.name = "max",
.translate = translate_smax,
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 05/13] target/xtensa: sort FLIX instruction opcodes
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
` (3 preceding siblings ...)
2019-02-14 22:59 ` [Qemu-devel] [PATCH 04/13] target/xtensa: implement wide branches and loops Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 06/13] target/xtensa: add generic instruction post-processing Max Filippov
` (7 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
Opcodes in different slots may read and write same resources (registers,
states). In the absence of resource dependency loops it must be possible
to sort opcodes to avoid interference.
Record resources used by each opcode in the bundle. Build opcode
dependency graph and use topological sort to order its nodes. In case of
success translate opcodes in sort order. In case of failure report and
raise invalid opcode exception.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/cpu.h | 2 +
target/xtensa/translate.c | 226 ++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 220 insertions(+), 8 deletions(-)
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index db8ee70a0386..c59f79e56326 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -373,6 +373,8 @@ enum {
XTENSA_OP_EXIT_TB_0 = 0x800,
XTENSA_OP_NAME_ARRAY = 0x8000,
+
+ XTENSA_OP_CONTROL_FLOW = 0x10000,
};
typedef struct XtensaOpcodeOps {
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index e8dddd32b3af..616ed8f57972 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -846,6 +846,156 @@ static inline unsigned xtensa_op0_insn_len(DisasContext *dc, uint8_t op0)
return xtensa_isa_length_from_chars(dc->config->isa, &op0);
}
+struct opcode_arg_info {
+ uint32_t resource;
+ int index;
+};
+
+struct slot_prop {
+ XtensaOpcodeOps *ops;
+ uint32_t arg[MAX_OPCODE_ARGS];
+ uint32_t raw_arg[MAX_OPCODE_ARGS];
+ struct opcode_arg_info in[MAX_OPCODE_ARGS];
+ struct opcode_arg_info out[MAX_OPCODE_ARGS];
+ unsigned n_in;
+ unsigned n_out;
+ uint32_t op_flags;
+};
+
+enum resource_type {
+ RES_REGFILE,
+ RES_STATE,
+};
+
+static uint32_t encode_resource(enum resource_type r, unsigned g, unsigned n)
+{
+ assert(r < 256 && g < 256 && n < 65536);
+ return (r << 24) | (g << 16) | n;
+}
+
+/*
+ * a depends on b if b must be executed before a,
+ * because a's side effects will destroy b's inputs.
+ */
+static bool op_depends_on(const struct slot_prop *a,
+ const struct slot_prop *b)
+{
+ unsigned i = 0;
+ unsigned j = 0;
+
+ if (a->op_flags & XTENSA_OP_CONTROL_FLOW) {
+ return true;
+ }
+ while (i < a->n_out && j < b->n_in) {
+ if (a->out[i].resource < b->in[j].resource) {
+ ++i;
+ } else if (a->out[i].resource > b->in[j].resource) {
+ ++j;
+ } else {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ * Calculate evaluation order for slot opcodes.
+ * Build opcode order graph and output its nodes in topological sort order.
+ * An edge a -> b in the graph means that opcode a must be followed by
+ * opcode b.
+ */
+static bool tsort(struct slot_prop *slot,
+ struct slot_prop *sorted[],
+ unsigned n)
+{
+ struct tsnode {
+ unsigned n_in_edge;
+ unsigned n_out_edge;
+ unsigned out_edge[MAX_INSN_SLOTS];
+ } node[MAX_INSN_SLOTS];
+
+ unsigned in[MAX_INSN_SLOTS];
+ unsigned i, j;
+ unsigned n_in = 0;
+ unsigned n_out = 0;
+ unsigned n_edge = 0;
+ unsigned in_idx;
+
+ for (i = 0; i < n; ++i) {
+ node[i].n_in_edge = 0;
+ node[i].n_out_edge = 0;
+ }
+
+ for (i = 0; i < n; ++i) {
+ unsigned n_out_edge = 0;
+
+ for (j = 0; j < n; ++j) {
+ if (i != j && op_depends_on(slot + j, slot + i)) {
+ node[i].out_edge[n_out_edge] = j;
+ ++node[j].n_in_edge;
+ ++n_out_edge;
+ ++n_edge;
+ }
+ }
+ node[i].n_out_edge = n_out_edge;
+ }
+
+ for (i = 0; i < n; ++i) {
+ if (!node[i].n_in_edge) {
+ in[n_in] = i;
+ ++n_in;
+ }
+ }
+
+ for (in_idx = 0; in_idx < n_in; ++in_idx) {
+ i = in[in_idx];
+ sorted[n_out] = slot + i;
+ ++n_out;
+ for (j = 0; j < node[i].n_out_edge; ++j) {
+ --n_edge;
+ if (--node[node[i].out_edge[j]].n_in_edge == 0) {
+ in[n_in] = node[i].out_edge[j];
+ ++n_in;
+ }
+ }
+ }
+ return n_edge == 0;
+}
+
+static void opcode_add_resource(struct slot_prop *op,
+ uint32_t resource, char direction,
+ int index)
+{
+ switch (direction) {
+ case 'm':
+ case 'i':
+ assert(op->n_in < ARRAY_SIZE(op->in));
+ op->in[op->n_in].resource = resource;
+ op->in[op->n_in].index = index;
+ ++op->n_in;
+ /* fall through */
+ case 'o':
+ if (direction == 'm' || direction == 'o') {
+ assert(op->n_out < ARRAY_SIZE(op->out));
+ op->out[op->n_out].resource = resource;
+ op->out[op->n_out].index = index;
+ ++op->n_out;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static int resource_compare(const void *a, const void *b)
+{
+ const struct opcode_arg_info *pa = a;
+ const struct opcode_arg_info *pb = b;
+
+ return pa->resource < pb->resource ?
+ -1 : (pa->resource > pb->resource ? 1 : 0);
+}
+
static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
{
xtensa_isa isa = dc->config->isa;
@@ -855,11 +1005,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
int slot, slots;
unsigned i;
uint32_t op_flags = 0;
- struct {
- XtensaOpcodeOps *ops;
- uint32_t arg[MAX_OPCODE_ARGS];
- uint32_t raw_arg[MAX_OPCODE_ARGS];
- } slot_prop[MAX_INSN_SLOTS];
+ struct slot_prop slot_prop[MAX_INSN_SLOTS];
+ struct slot_prop *ordered[MAX_INSN_SLOTS];
uint32_t debug_cause = 0;
uint32_t windowed_register = 0;
uint32_t coprocessor = 0;
@@ -954,6 +1101,68 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
windowed_register |= ops->test_overflow(dc, arg, ops->par);
}
coprocessor |= ops->coprocessor;
+
+ if (slots > 1) {
+ slot_prop[slot].n_in = 0;
+ slot_prop[slot].n_out = 0;
+ slot_prop[slot].op_flags = 0;
+
+ opnds = xtensa_opcode_num_operands(isa, opc);
+
+ for (opnd = vopnd = 0; opnd < opnds; ++opnd) {
+ bool visible = xtensa_operand_is_visible(isa, opc, opnd);
+
+ if (xtensa_operand_is_register(isa, opc, opnd)) {
+ xtensa_regfile rf = xtensa_operand_regfile(isa, opc, opnd);
+ uint32_t v = 0;
+
+ xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
+ dc->slotbuf, &v);
+ xtensa_operand_decode(isa, opc, opnd, &v);
+ opcode_add_resource(slot_prop + slot,
+ encode_resource(RES_REGFILE, rf, v),
+ xtensa_operand_inout(isa, opc, opnd),
+ visible ? vopnd : -1);
+ }
+ if (visible) {
+ ++vopnd;
+ }
+ }
+
+ opnds = xtensa_opcode_num_stateOperands(isa, opc);
+
+ for (opnd = 0; opnd < opnds; ++opnd) {
+ xtensa_state state = xtensa_stateOperand_state(isa, opc, opnd);
+
+ opcode_add_resource(slot_prop + slot,
+ encode_resource(RES_STATE, 0, state),
+ xtensa_stateOperand_inout(isa, opc, opnd),
+ -1);
+ }
+ if (xtensa_opcode_is_branch(isa, opc) ||
+ xtensa_opcode_is_jump(isa, opc) ||
+ xtensa_opcode_is_loop(isa, opc) ||
+ xtensa_opcode_is_call(isa, opc)) {
+ slot_prop[slot].op_flags |= XTENSA_OP_CONTROL_FLOW;
+ }
+
+ qsort(slot_prop[slot].in, slot_prop[slot].n_in,
+ sizeof(slot_prop[slot].in[0]), resource_compare);
+ qsort(slot_prop[slot].out, slot_prop[slot].n_out,
+ sizeof(slot_prop[slot].out[0]), resource_compare);
+ }
+ }
+
+ if (slots > 1) {
+ if (!tsort(slot_prop, ordered, slots)) {
+ qemu_log_mask(LOG_UNIMP,
+ "Circular resource dependencies (pc = %08x)\n",
+ dc->pc);
+ gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
+ return;
+ }
+ } else {
+ ordered[0] = slot_prop + 0;
}
if ((op_flags & XTENSA_OP_PRIVILEGED) &&
@@ -1002,10 +1211,11 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
}
for (slot = 0; slot < slots; ++slot) {
- XtensaOpcodeOps *ops = slot_prop[slot].ops;
+ struct slot_prop *pslot = ordered[slot];
+ XtensaOpcodeOps *ops = pslot->ops;
- dc->raw_arg = slot_prop[slot].raw_arg;
- ops->translate(dc, slot_prop[slot].arg, ops->par);
+ dc->raw_arg = pslot->raw_arg;
+ ops->translate(dc, pslot->arg, ops->par);
}
if (dc->base.is_jmp == DISAS_NEXT) {
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 06/13] target/xtensa: add generic instruction post-processing
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
` (4 preceding siblings ...)
2019-02-14 22:59 ` [Qemu-devel] [PATCH 05/13] target/xtensa: sort FLIX instruction opcodes Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 07/13] target/xtensa: move WINDOW_BASE SR update to postprocessing Max Filippov
` (6 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
Some opcodes may need additional actions at every exit from the
translated instruction or may need to amend TB exit slots available to
jumps generated for the instruction. Add gen_postprocess function and
call it from the gen_jump_slot and from the disas_xtensa_insn.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/cpu.h | 8 ++++++++
target/xtensa/translate.c | 33 +++++++++++++++++++++++++--------
2 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index c59f79e56326..a3bab9c5a254 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -368,9 +368,17 @@ enum {
XTENSA_OP_DIVIDE_BY_ZERO = 0x100,
+ /* Postprocessing flags */
XTENSA_OP_CHECK_INTERRUPTS = 0x200,
XTENSA_OP_EXIT_TB_M1 = 0x400,
XTENSA_OP_EXIT_TB_0 = 0x800,
+ XTENSA_OP_SYNC_REGISTER_WINDOW = 0x1000,
+
+ XTENSA_OP_POSTPROCESS =
+ XTENSA_OP_CHECK_INTERRUPTS |
+ XTENSA_OP_EXIT_TB_M1 |
+ XTENSA_OP_EXIT_TB_0 |
+ XTENSA_OP_SYNC_REGISTER_WINDOW,
XTENSA_OP_NAME_ARRAY = 0x8000,
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 616ed8f57972..149fcd37f9a1 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -71,6 +71,7 @@ struct DisasContext {
unsigned cpenable;
+ uint32_t op_flags;
uint32_t *raw_arg;
xtensa_insnbuf insnbuf;
xtensa_insnbuf slotbuf;
@@ -363,6 +364,8 @@ static bool gen_check_cpenable(DisasContext *dc, uint32_t cp_mask)
return true;
}
+static int gen_postprocess(DisasContext *dc, int slot);
+
static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
{
tcg_gen_mov_i32(cpu_pc, dest);
@@ -372,6 +375,9 @@ static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
if (dc->base.singlestep_enabled) {
gen_exception(dc, EXCP_DEBUG);
} else {
+ if (dc->op_flags & XTENSA_OP_POSTPROCESS) {
+ slot = gen_postprocess(dc, slot);
+ }
if (slot >= 0) {
tcg_gen_goto_tb(slot);
tcg_gen_exit_tb(dc->base.tb, slot);
@@ -846,6 +852,19 @@ static inline unsigned xtensa_op0_insn_len(DisasContext *dc, uint8_t op0)
return xtensa_isa_length_from_chars(dc->config->isa, &op0);
}
+static int gen_postprocess(DisasContext *dc, int slot)
+{
+ uint32_t op_flags = dc->op_flags;
+
+ if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) {
+ gen_check_interrupts(dc);
+ }
+ if (op_flags & XTENSA_OP_EXIT_TB_M1) {
+ slot = -1;
+ }
+ return slot;
+}
+
struct opcode_arg_info {
uint32_t resource;
int index;
@@ -1210,6 +1229,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
}
}
+ dc->op_flags = op_flags;
+
for (slot = 0; slot < slots; ++slot) {
struct slot_prop *pslot = ordered[slot];
XtensaOpcodeOps *ops = pslot->ops;
@@ -1219,21 +1240,17 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
}
if (dc->base.is_jmp == DISAS_NEXT) {
- if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) {
- gen_check_interrupts(dc);
- }
-
+ gen_postprocess(dc, 0);
+ dc->op_flags = 0;
if (op_flags & XTENSA_OP_EXIT_TB_M1) {
/* Change in mmu index, memory mapping or tb->flags; exit tb */
gen_jumpi_check_loop_end(dc, -1);
} else if (op_flags & XTENSA_OP_EXIT_TB_0) {
gen_jumpi_check_loop_end(dc, 0);
+ } else {
+ gen_check_loop_end(dc, 0);
}
}
-
- if (dc->base.is_jmp == DISAS_NEXT) {
- gen_check_loop_end(dc, 0);
- }
dc->pc = dc->base.pc_next;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 07/13] target/xtensa: move WINDOW_BASE SR update to postprocessing
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
` (5 preceding siblings ...)
2019-02-14 22:59 ` [Qemu-devel] [PATCH 06/13] target/xtensa: add generic instruction post-processing Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 08/13] target/xtensa: only rotate window in the retw helper Max Filippov
` (5 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
Opcodes that modify WINDOW_BASE SR don't have dependency on opcodes that
use windowed registers. If such opcodes are combined in a single
instruction they may not be correctly ordered. Instead of adding said
dependency use temporary register to store changed WINDOW_BASE value and
do actual register window rotation as a postprocessing step.
Not all opcodes that change WINDOW_BASE need this: retw, rfwo and rfwu
are also jump opcodes, so they are guaranteed to be translated last and
thus will not affect other opcodes in the same instruction.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/cpu.h | 1 +
target/xtensa/helper.h | 3 +--
target/xtensa/translate.c | 30 ++++++++++++++++++++++--------
target/xtensa/win_helper.c | 14 ++++----------
4 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index a3bab9c5a254..dca4e4b1114b 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -486,6 +486,7 @@ typedef struct CPUXtensaState {
float64 f64;
} fregs[16];
float_status fp_status;
+ uint32_t windowbase_next;
#ifndef CONFIG_USER_ONLY
xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
diff --git a/target/xtensa/helper.h b/target/xtensa/helper.h
index 2a7db35874fe..b6529a8925f3 100644
--- a/target/xtensa/helper.h
+++ b/target/xtensa/helper.h
@@ -3,12 +3,11 @@ DEF_HELPER_3(exception_cause, noreturn, env, i32, i32)
DEF_HELPER_4(exception_cause_vaddr, noreturn, env, i32, i32, i32)
DEF_HELPER_3(debug_exception, noreturn, env, i32, i32)
-DEF_HELPER_2(wsr_windowbase, void, env, i32)
+DEF_HELPER_1(sync_windowbase, void, env)
DEF_HELPER_4(entry, void, env, i32, i32, i32)
DEF_HELPER_2(test_ill_retw, void, env, i32)
DEF_HELPER_2(test_underflow_retw, void, env, i32)
DEF_HELPER_2(retw, i32, env, i32)
-DEF_HELPER_2(rotw, void, env, i32)
DEF_HELPER_3(window_check, noreturn, env, i32, i32)
DEF_HELPER_1(restore_owb, void, env)
DEF_HELPER_2(movsp, void, env, i32)
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 149fcd37f9a1..0213cef1b605 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -82,6 +82,7 @@ static TCGv_i32 cpu_R[16];
static TCGv_i32 cpu_FR[16];
static TCGv_i32 cpu_SR[256];
static TCGv_i32 cpu_UR[256];
+static TCGv_i32 cpu_windowbase_next;
#include "exec/gen-icount.h"
@@ -253,6 +254,11 @@ void xtensa_translate_init(void)
uregnames[i].name);
}
}
+
+ cpu_windowbase_next =
+ tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUXtensaState, windowbase_next),
+ "windowbase_next");
}
static inline bool option_enabled(DisasContext *dc, int opt)
@@ -557,7 +563,7 @@ static void gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s)
#ifndef CONFIG_USER_ONLY
static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
{
- gen_helper_wsr_windowbase(cpu_env, v);
+ tcg_gen_mov_i32(cpu_windowbase_next, v);
}
static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v)
@@ -859,6 +865,9 @@ static int gen_postprocess(DisasContext *dc, int slot)
if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) {
gen_check_interrupts(dc);
}
+ if (op_flags & XTENSA_OP_SYNC_REGISTER_WINDOW) {
+ gen_helper_sync_windowbase(cpu_env);
+ }
if (op_flags & XTENSA_OP_EXIT_TB_M1) {
slot = -1;
}
@@ -2267,9 +2276,7 @@ static void translate_rfw(DisasContext *dc, const uint32_t arg[],
static void translate_rotw(DisasContext *dc, const uint32_t arg[],
const uint32_t par[])
{
- TCGv_i32 tmp = tcg_const_i32(arg[0]);
- gen_helper_rotw(cpu_env, tmp);
- tcg_temp_free(tmp);
+ tcg_gen_addi_i32(cpu_windowbase_next, cpu_SR[WINDOW_BASE], arg[0]);
}
static void translate_rsil(DisasContext *dc, const uint32_t arg[],
@@ -2971,7 +2978,8 @@ static const XtensaOpcodeOps core_ops[] = {
.translate = translate_entry,
.test_ill = test_ill_entry,
.test_overflow = test_overflow_entry,
- .op_flags = XTENSA_OP_EXIT_TB_M1,
+ .op_flags = XTENSA_OP_EXIT_TB_M1 |
+ XTENSA_OP_SYNC_REGISTER_WINDOW,
}, {
.name = "esync",
.translate = translate_nop,
@@ -3553,7 +3561,9 @@ static const XtensaOpcodeOps core_ops[] = {
}, {
.name = "rotw",
.translate = translate_rotw,
- .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
+ .op_flags = XTENSA_OP_PRIVILEGED |
+ XTENSA_OP_EXIT_TB_M1 |
+ XTENSA_OP_SYNC_REGISTER_WINDOW,
}, {
.name = "rsil",
.translate = translate_rsil,
@@ -4621,7 +4631,9 @@ static const XtensaOpcodeOps core_ops[] = {
.translate = translate_wsr,
.test_ill = test_ill_wsr,
.par = (const uint32_t[]){WINDOW_BASE},
- .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
+ .op_flags = XTENSA_OP_PRIVILEGED |
+ XTENSA_OP_EXIT_TB_M1 |
+ XTENSA_OP_SYNC_REGISTER_WINDOW,
}, {
.name = "wsr.windowstart",
.translate = translate_wsr,
@@ -5107,7 +5119,9 @@ static const XtensaOpcodeOps core_ops[] = {
.translate = translate_xsr,
.test_ill = test_ill_xsr,
.par = (const uint32_t[]){WINDOW_BASE},
- .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_EXIT_TB_M1,
+ .op_flags = XTENSA_OP_PRIVILEGED |
+ XTENSA_OP_EXIT_TB_M1 |
+ XTENSA_OP_SYNC_REGISTER_WINDOW,
}, {
.name = "xsr.windowstart",
.translate = translate_xsr,
diff --git a/target/xtensa/win_helper.c b/target/xtensa/win_helper.c
index 7d793d4f9cff..d7a4e2782186 100644
--- a/target/xtensa/win_helper.c
+++ b/target/xtensa/win_helper.c
@@ -96,9 +96,9 @@ void xtensa_rotate_window(CPUXtensaState *env, uint32_t delta)
xtensa_rotate_window_abs(env, env->sregs[WINDOW_BASE] + delta);
}
-void HELPER(wsr_windowbase)(CPUXtensaState *env, uint32_t v)
+void HELPER(sync_windowbase)(CPUXtensaState *env)
{
- xtensa_rotate_window_abs(env, v);
+ xtensa_rotate_window_abs(env, env->windowbase_next);
}
void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
@@ -106,9 +106,8 @@ void HELPER(entry)(CPUXtensaState *env, uint32_t pc, uint32_t s, uint32_t imm)
int callinc = (env->sregs[PS] & PS_CALLINC) >> PS_CALLINC_SHIFT;
env->regs[(callinc << 2) | (s & 3)] = env->regs[s] - imm;
- xtensa_rotate_window(env, callinc);
- env->sregs[WINDOW_START] |=
- windowstart_bit(env->sregs[WINDOW_BASE], env);
+ env->windowbase_next = env->sregs[WINDOW_BASE] + callinc;
+ env->sregs[WINDOW_START] |= windowstart_bit(env->windowbase_next, env);
}
void HELPER(window_check)(CPUXtensaState *env, uint32_t pc, uint32_t w)
@@ -196,11 +195,6 @@ uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
return ret_pc;
}
-void HELPER(rotw)(CPUXtensaState *env, uint32_t imm4)
-{
- xtensa_rotate_window(env, imm4);
-}
-
void xtensa_restore_owb(CPUXtensaState *env)
{
xtensa_rotate_window_abs(env, (env->sregs[PS] & PS_OWB) >> PS_OWB_SHIFT);
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 08/13] target/xtensa: only rotate window in the retw helper
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
` (6 preceding siblings ...)
2019-02-14 22:59 ` [Qemu-devel] [PATCH 07/13] target/xtensa: move WINDOW_BASE SR update to postprocessing Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 09/13] target/xtensa: reorganize register handling in translators Max Filippov
` (4 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
Move return address calculation and WINDOW_START adjustment out of the
retw helper to simplify logic a bit and avoid using registers directly.
Pass a0 as a parameter to the helper.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/helper.h | 2 +-
target/xtensa/translate.c | 9 +++++++--
target/xtensa/win_helper.c | 8 ++------
3 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/target/xtensa/helper.h b/target/xtensa/helper.h
index b6529a8925f3..0b9ec670c86e 100644
--- a/target/xtensa/helper.h
+++ b/target/xtensa/helper.h
@@ -7,7 +7,7 @@ DEF_HELPER_1(sync_windowbase, void, env)
DEF_HELPER_4(entry, void, env, i32, i32, i32)
DEF_HELPER_2(test_ill_retw, void, env, i32)
DEF_HELPER_2(test_underflow_retw, void, env, i32)
-DEF_HELPER_2(retw, i32, env, i32)
+DEF_HELPER_2(retw, void, env, i32)
DEF_HELPER_3(window_check, noreturn, env, i32, i32)
DEF_HELPER_1(restore_owb, void, env)
DEF_HELPER_2(movsp, void, env, i32)
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 0213cef1b605..f991cc360889 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -2226,8 +2226,13 @@ static bool test_ill_retw(DisasContext *dc, const uint32_t arg[],
static void translate_retw(DisasContext *dc, const uint32_t arg[],
const uint32_t par[])
{
- TCGv_i32 tmp = tcg_const_i32(dc->pc);
- gen_helper_retw(tmp, cpu_env, tmp);
+ TCGv_i32 tmp = tcg_const_i32(1);
+ tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]);
+ tcg_gen_andc_i32(cpu_SR[WINDOW_START],
+ cpu_SR[WINDOW_START], tmp);
+ tcg_gen_movi_i32(tmp, dc->pc);
+ tcg_gen_deposit_i32(tmp, tmp, cpu_R[0], 0, 30);
+ gen_helper_retw(cpu_env, cpu_R[0]);
gen_jump(dc, tmp);
tcg_temp_free(tmp);
}
diff --git a/target/xtensa/win_helper.c b/target/xtensa/win_helper.c
index d7a4e2782186..f6f96a64c30e 100644
--- a/target/xtensa/win_helper.c
+++ b/target/xtensa/win_helper.c
@@ -184,15 +184,11 @@ void HELPER(test_underflow_retw)(CPUXtensaState *env, uint32_t pc)
}
}
-uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
+void HELPER(retw)(CPUXtensaState *env, uint32_t a0)
{
- int n = (env->regs[0] >> 30) & 0x3;
- uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
- uint32_t ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);
+ int n = (a0 >> 30) & 0x3;
xtensa_rotate_window(env, -n);
- env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env);
- return ret_pc;
}
void xtensa_restore_owb(CPUXtensaState *env)
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 09/13] target/xtensa: reorganize register handling in translators
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
` (7 preceding siblings ...)
2019-02-14 22:59 ` [Qemu-devel] [PATCH 08/13] target/xtensa: only rotate window in the retw helper Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 10/13] target/xtensa: reorganize access to MAC16 registers Max Filippov
` (3 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
To support circular register dependencies in FLIX bundles opcode inputs
and outputs must be separate and adjustable. Circular dependencies can
be broken by making temporary copies of opcode inputs and substituting
them into the arguments array instead of the original registers.
E.g. the circular register dependency in the following bundle:
{ mov a2, a3 ; mov a3, a2 }
can be resolved by making copy a2' = a2 and substituting it as input
argument of the second opcode:
{ mov a2, a3 ; mov a3, a2' }
Change opcode translator prototype to accept OpcodeArg array as
argument. For each register argument initialize OpcodeArg::{in,out} with
TCGv_* of the respective register. Don't explicitly use cpu_R in the
opcode translators, use OpcodeArg::{in,out} instead.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/cpu.h | 15 +-
target/xtensa/helper.c | 15 +
target/xtensa/translate.c | 700 ++++++++++++++++++++++++----------------------
3 files changed, 386 insertions(+), 344 deletions(-)
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index dca4e4b1114b..bf021f7695e6 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -345,14 +345,21 @@ typedef struct XtensaMemory {
} location[MAX_NMEMORY];
} XtensaMemory;
+typedef struct opcode_arg {
+ uint32_t imm;
+ uint32_t raw_imm;
+ void *in;
+ void *out;
+} OpcodeArg;
+
typedef struct DisasContext DisasContext;
-typedef void (*XtensaOpcodeOp)(DisasContext *dc, const uint32_t arg[],
+typedef void (*XtensaOpcodeOp)(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[]);
typedef bool (*XtensaOpcodeBoolTest)(DisasContext *dc,
- const uint32_t arg[],
+ const OpcodeArg arg[],
const uint32_t par[]);
typedef uint32_t (*XtensaOpcodeUintTest)(DisasContext *dc,
- const uint32_t arg[],
+ const OpcodeArg arg[],
const uint32_t par[]);
enum {
@@ -450,6 +457,7 @@ struct XtensaConfig {
XtensaOpcodeOps **opcode_ops;
const XtensaOpcodeTranslators **opcode_translators;
xtensa_regfile a_regfile;
+ void ***regfile;
uint32_t clock_freq_khz;
@@ -578,6 +586,7 @@ void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
XTENSA_CPU_TYPE_NAME(XTENSA_DEFAULT_CPU_NOMMU_MODEL)
void xtensa_translate_init(void);
+void **xtensa_get_regfile_by_name(const char *name);
void xtensa_breakpoint_handler(CPUState *cs);
void xtensa_register_core(XtensaConfigList *node);
void xtensa_sim_open_console(Chardev *chr);
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index 7008c6390d20..f4867a9b5631 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -91,11 +91,13 @@ static void init_libisa(XtensaConfig *config)
unsigned i, j;
unsigned opcodes;
unsigned formats;
+ unsigned regfiles;
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);
formats = xtensa_isa_num_formats(config->isa);
+ regfiles = xtensa_isa_num_regfiles(config->isa);
config->opcode_ops = g_new(XtensaOpcodeOps *, opcodes);
for (i = 0; i < formats; ++i) {
@@ -125,6 +127,19 @@ static void init_libisa(XtensaConfig *config)
config->opcode_ops[i] = ops;
}
config->a_regfile = xtensa_regfile_lookup(config->isa, "AR");
+
+ config->regfile = g_new(void **, regfiles);
+ for (i = 0; i < regfiles; ++i) {
+ const char *name = xtensa_regfile_name(config->isa, i);
+
+ config->regfile[i] = xtensa_get_regfile_by_name(name);
+#ifdef DEBUG
+ if (config->regfile[i] == NULL) {
+ fprintf(stderr, "regfile '%s' not found for %s\n",
+ name, config->name);
+ }
+#endif
+ }
}
static void xtensa_finalize_config(XtensaConfig *config)
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index f991cc360889..253777468c29 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -72,7 +72,6 @@ struct DisasContext {
unsigned cpenable;
uint32_t op_flags;
- uint32_t *raw_arg;
xtensa_insnbuf insnbuf;
xtensa_insnbuf slotbuf;
};
@@ -84,6 +83,8 @@ static TCGv_i32 cpu_SR[256];
static TCGv_i32 cpu_UR[256];
static TCGv_i32 cpu_windowbase_next;
+static GHashTable *xtensa_regfile_table;
+
#include "exec/gen-icount.h"
typedef struct XtensaReg {
@@ -261,6 +262,18 @@ void xtensa_translate_init(void)
"windowbase_next");
}
+void **xtensa_get_regfile_by_name(const char *name)
+{
+ if (xtensa_regfile_table == NULL) {
+ xtensa_regfile_table = g_hash_table_new(g_str_hash, g_str_equal);
+ g_hash_table_insert(xtensa_regfile_table,
+ (void *)"AR", (void *)cpu_R);
+ g_hash_table_insert(xtensa_regfile_table,
+ (void *)"FR", (void *)cpu_FR);
+ }
+ return (void **)g_hash_table_lookup(xtensa_regfile_table, (void *)name);
+}
+
static inline bool option_enabled(DisasContext *dc, int opt)
{
return xtensa_option_enabled(dc->config, opt);
@@ -844,11 +857,11 @@ static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned)
return m;
}
-static void gen_zero_check(DisasContext *dc, const uint32_t arg[])
+static void gen_zero_check(DisasContext *dc, const OpcodeArg arg[])
{
TCGLabel *label = gen_new_label();
- tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0, label);
+ tcg_gen_brcondi_i32(TCG_COND_NE, arg[2].in, 0, label);
gen_exception_cause(dc, INTEGER_DIVIDE_BY_ZERO_CAUSE);
gen_set_label(label);
}
@@ -881,8 +894,7 @@ struct opcode_arg_info {
struct slot_prop {
XtensaOpcodeOps *ops;
- uint32_t arg[MAX_OPCODE_ARGS];
- uint32_t raw_arg[MAX_OPCODE_ARGS];
+ OpcodeArg arg[MAX_OPCODE_ARGS];
struct opcode_arg_info in[MAX_OPCODE_ARGS];
struct opcode_arg_info out[MAX_OPCODE_ARGS];
unsigned n_in;
@@ -1064,12 +1076,9 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
for (slot = 0; slot < slots; ++slot) {
xtensa_opcode opc;
int opnd, vopnd, opnds;
- uint32_t *raw_arg = slot_prop[slot].raw_arg;
- uint32_t *arg = slot_prop[slot].arg;
+ OpcodeArg *arg = slot_prop[slot].arg;
XtensaOpcodeOps *ops;
- dc->raw_arg = raw_arg;
-
xtensa_format_get_slot(isa, fmt, slot, dc->insnbuf, dc->slotbuf);
opc = xtensa_opcode_decode(isa, fmt, slot, dc->slotbuf);
if (opc == XTENSA_UNDEFINED) {
@@ -1082,15 +1091,21 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
opnds = xtensa_opcode_num_operands(isa, opc);
for (opnd = vopnd = 0; opnd < opnds; ++opnd) {
- if (xtensa_operand_is_register(isa, opc, opnd) &&
- xtensa_operand_regfile(isa, opc, opnd) ==
- dc->config->a_regfile) {
- uint32_t v;
+ void **register_file = NULL;
- xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
- dc->slotbuf, &v);
- xtensa_operand_decode(isa, opc, opnd, &v);
- windowed_register |= 1u << v;
+ if (xtensa_operand_is_register(isa, opc, opnd)) {
+ xtensa_regfile rf = xtensa_operand_regfile(isa, opc, opnd);
+
+ register_file = dc->config->regfile[rf];
+
+ if (rf == dc->config->a_regfile) {
+ uint32_t v;
+
+ xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
+ dc->slotbuf, &v);
+ xtensa_operand_decode(isa, opc, opnd, &v);
+ windowed_register |= 1u << v;
+ }
}
if (xtensa_operand_is_visible(isa, opc, opnd)) {
uint32_t v;
@@ -1098,11 +1113,15 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
xtensa_operand_get_field(isa, opc, opnd, fmt, slot,
dc->slotbuf, &v);
xtensa_operand_decode(isa, opc, opnd, &v);
- raw_arg[vopnd] = v;
+ arg[vopnd].raw_imm = v;
if (xtensa_operand_is_PCrelative(isa, opc, opnd)) {
xtensa_operand_undo_reloc(isa, opc, opnd, &v, dc->pc);
}
- arg[vopnd] = v;
+ arg[vopnd].imm = v;
+ if (register_file) {
+ arg[vopnd].in = register_file[v];
+ arg[vopnd].out = register_file[v];
+ }
++vopnd;
}
}
@@ -1244,7 +1263,6 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
struct slot_prop *pslot = ordered[slot];
XtensaOpcodeOps *ops = pslot->ops;
- dc->raw_arg = pslot->raw_arg;
ops->translate(dc, pslot->arg, ops->par);
}
@@ -1510,91 +1528,91 @@ void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb,
env->pc = data[0];
}
-static void translate_abs(DisasContext *dc, const uint32_t arg[],
+static void translate_abs(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 zero = tcg_const_i32(0);
TCGv_i32 neg = tcg_temp_new_i32();
- tcg_gen_neg_i32(neg, cpu_R[arg[1]]);
- tcg_gen_movcond_i32(TCG_COND_GE, cpu_R[arg[0]],
- cpu_R[arg[1]], zero, cpu_R[arg[1]], neg);
+ tcg_gen_neg_i32(neg, arg[1].in);
+ tcg_gen_movcond_i32(TCG_COND_GE, arg[0].out,
+ arg[1].in, zero, arg[1].in, neg);
tcg_temp_free(neg);
tcg_temp_free(zero);
}
-static void translate_add(DisasContext *dc, const uint32_t arg[],
+static void translate_add(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_add_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_add_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_addi(DisasContext *dc, const uint32_t arg[],
+static void translate_addi(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_addi_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+ tcg_gen_addi_i32(arg[0].out, arg[1].in, arg[2].imm);
}
-static void translate_addx(DisasContext *dc, const uint32_t arg[],
+static void translate_addx(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]);
- tcg_gen_add_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]);
+ tcg_gen_shli_i32(tmp, arg[1].in, par[0]);
+ tcg_gen_add_i32(arg[0].out, tmp, arg[2].in);
tcg_temp_free(tmp);
}
-static void translate_all(DisasContext *dc, const uint32_t arg[],
+static void translate_all(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
uint32_t shift = par[1];
- TCGv_i32 mask = tcg_const_i32(((1 << shift) - 1) << arg[1]);
+ TCGv_i32 mask = tcg_const_i32(((1 << shift) - 1) << arg[1].imm);
TCGv_i32 tmp = tcg_temp_new_i32();
tcg_gen_and_i32(tmp, cpu_SR[BR], mask);
if (par[0]) {
- tcg_gen_addi_i32(tmp, tmp, 1 << arg[1]);
+ tcg_gen_addi_i32(tmp, tmp, 1 << arg[1].imm);
} else {
tcg_gen_add_i32(tmp, tmp, mask);
}
- tcg_gen_shri_i32(tmp, tmp, arg[1] + shift);
+ tcg_gen_shri_i32(tmp, tmp, arg[1].imm + shift);
tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR],
- tmp, arg[0], 1);
+ tmp, arg[0].imm, 1);
tcg_temp_free(mask);
tcg_temp_free(tmp);
}
-static void translate_and(DisasContext *dc, const uint32_t arg[],
+static void translate_and(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_and_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_and_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_ball(DisasContext *dc, const uint32_t arg[],
+static void translate_ball(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]);
- gen_brcond(dc, par[0], tmp, cpu_R[arg[1]], arg[2]);
+ tcg_gen_and_i32(tmp, arg[0].in, arg[1].in);
+ gen_brcond(dc, par[0], tmp, arg[1].in, arg[2].imm);
tcg_temp_free(tmp);
}
-static void translate_bany(DisasContext *dc, const uint32_t arg[],
+static void translate_bany(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_and_i32(tmp, cpu_R[arg[0]], cpu_R[arg[1]]);
- gen_brcondi(dc, par[0], tmp, 0, arg[2]);
+ tcg_gen_and_i32(tmp, arg[0].in, arg[1].in);
+ gen_brcondi(dc, par[0], tmp, 0, arg[2].imm);
tcg_temp_free(tmp);
}
-static void translate_b(DisasContext *dc, const uint32_t arg[],
+static void translate_b(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_brcond(dc, par[0], cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+ gen_brcond(dc, par[0], arg[0].in, arg[1].in, arg[2].imm);
}
-static void translate_bb(DisasContext *dc, const uint32_t arg[],
+static void translate_bb(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifdef TARGET_WORDS_BIGENDIAN
@@ -1603,41 +1621,41 @@ static void translate_bb(DisasContext *dc, const uint32_t arg[],
TCGv_i32 bit = tcg_const_i32(0x00000001u);
#endif
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cpu_R[arg[1]], 0x1f);
+ tcg_gen_andi_i32(tmp, arg[1].in, 0x1f);
#ifdef TARGET_WORDS_BIGENDIAN
tcg_gen_shr_i32(bit, bit, tmp);
#else
tcg_gen_shl_i32(bit, bit, tmp);
#endif
- tcg_gen_and_i32(tmp, cpu_R[arg[0]], bit);
- gen_brcondi(dc, par[0], tmp, 0, arg[2]);
+ tcg_gen_and_i32(tmp, arg[0].in, bit);
+ gen_brcondi(dc, par[0], tmp, 0, arg[2].imm);
tcg_temp_free(tmp);
tcg_temp_free(bit);
}
-static void translate_bbi(DisasContext *dc, const uint32_t arg[],
+static void translate_bbi(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
#ifdef TARGET_WORDS_BIGENDIAN
- tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x80000000u >> arg[1]);
+ tcg_gen_andi_i32(tmp, arg[0].in, 0x80000000u >> arg[1].imm);
#else
- tcg_gen_andi_i32(tmp, cpu_R[arg[0]], 0x00000001u << arg[1]);
+ tcg_gen_andi_i32(tmp, arg[0].in, 0x00000001u << arg[1].imm);
#endif
- gen_brcondi(dc, par[0], tmp, 0, arg[2]);
+ gen_brcondi(dc, par[0], tmp, 0, arg[2].imm);
tcg_temp_free(tmp);
}
-static void translate_bi(DisasContext *dc, const uint32_t arg[],
+static void translate_bi(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_brcondi(dc, par[0], cpu_R[arg[0]], arg[1], arg[2]);
+ gen_brcondi(dc, par[0], arg[0].in, arg[1].imm, arg[2].imm);
}
-static void translate_bz(DisasContext *dc, const uint32_t arg[],
+static void translate_bz(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_brcondi(dc, par[0], cpu_R[arg[0]], 0, arg[1]);
+ gen_brcondi(dc, par[0], arg[0].in, 0, arg[1].imm);
}
enum {
@@ -1648,7 +1666,7 @@ enum {
BOOLEAN_XOR,
};
-static void translate_boolean(DisasContext *dc, const uint32_t arg[],
+static void translate_boolean(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
static void (* const op[])(TCGv_i32, TCGv_i32, TCGv_i32) = {
@@ -1662,110 +1680,110 @@ static void translate_boolean(DisasContext *dc, const uint32_t arg[],
TCGv_i32 tmp1 = tcg_temp_new_i32();
TCGv_i32 tmp2 = tcg_temp_new_i32();
- tcg_gen_shri_i32(tmp1, cpu_SR[BR], arg[1]);
- tcg_gen_shri_i32(tmp2, cpu_SR[BR], arg[2]);
+ tcg_gen_shri_i32(tmp1, cpu_SR[BR], arg[1].imm);
+ tcg_gen_shri_i32(tmp2, cpu_SR[BR], arg[2].imm);
op[par[0]](tmp1, tmp1, tmp2);
- tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], tmp1, arg[0], 1);
+ tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], tmp1, arg[0].imm, 1);
tcg_temp_free(tmp1);
tcg_temp_free(tmp2);
}
-static void translate_bp(DisasContext *dc, const uint32_t arg[],
+static void translate_bp(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[0]);
- gen_brcondi(dc, par[0], tmp, 0, arg[1]);
+ tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[0].imm);
+ gen_brcondi(dc, par[0], tmp, 0, arg[1].imm);
tcg_temp_free(tmp);
}
-static void translate_call0(DisasContext *dc, const uint32_t arg[],
+static void translate_call0(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
tcg_gen_movi_i32(cpu_R[0], dc->base.pc_next);
- gen_jumpi(dc, arg[0], 0);
+ gen_jumpi(dc, arg[0].imm, 0);
}
-static void translate_callw(DisasContext *dc, const uint32_t arg[],
+static void translate_callw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- TCGv_i32 tmp = tcg_const_i32(arg[0]);
- gen_callw_slot(dc, par[0], tmp, adjust_jump_slot(dc, arg[0], 0));
+ TCGv_i32 tmp = tcg_const_i32(arg[0].imm);
+ gen_callw_slot(dc, par[0], tmp, adjust_jump_slot(dc, arg[0].imm, 0));
tcg_temp_free(tmp);
}
-static void translate_callx0(DisasContext *dc, const uint32_t arg[],
+static void translate_callx0(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_mov_i32(tmp, cpu_R[arg[0]]);
+ tcg_gen_mov_i32(tmp, arg[0].in);
tcg_gen_movi_i32(cpu_R[0], dc->base.pc_next);
gen_jump(dc, tmp);
tcg_temp_free(tmp);
}
-static void translate_callxw(DisasContext *dc, const uint32_t arg[],
+static void translate_callxw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_mov_i32(tmp, cpu_R[arg[0]]);
+ tcg_gen_mov_i32(tmp, arg[0].in);
gen_callw_slot(dc, par[0], tmp, -1);
tcg_temp_free(tmp);
}
-static void translate_clamps(DisasContext *dc, const uint32_t arg[],
+static void translate_clamps(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- TCGv_i32 tmp1 = tcg_const_i32(-1u << arg[2]);
- TCGv_i32 tmp2 = tcg_const_i32((1 << arg[2]) - 1);
+ TCGv_i32 tmp1 = tcg_const_i32(-1u << arg[2].imm);
+ TCGv_i32 tmp2 = tcg_const_i32((1 << arg[2].imm) - 1);
- tcg_gen_smax_i32(tmp1, tmp1, cpu_R[arg[1]]);
- tcg_gen_smin_i32(cpu_R[arg[0]], tmp1, tmp2);
+ tcg_gen_smax_i32(tmp1, tmp1, arg[1].in);
+ tcg_gen_smin_i32(arg[0].out, tmp1, tmp2);
tcg_temp_free(tmp1);
tcg_temp_free(tmp2);
}
-static void translate_clrb_expstate(DisasContext *dc, const uint32_t arg[],
+static void translate_clrb_expstate(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
/* TODO: GPIO32 may be a part of coprocessor */
- tcg_gen_andi_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], ~(1u << arg[0]));
+ tcg_gen_andi_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], ~(1u << arg[0].imm));
}
-static void translate_const16(DisasContext *dc, const uint32_t arg[],
+static void translate_const16(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- TCGv_i32 c = tcg_const_i32(arg[1]);
+ TCGv_i32 c = tcg_const_i32(arg[1].imm);
- tcg_gen_deposit_i32(cpu_R[arg[0]], c, cpu_R[arg[0]], 16, 16);
+ tcg_gen_deposit_i32(arg[0].out, c, arg[0].in, 16, 16);
tcg_temp_free(c);
}
-static void translate_dcache(DisasContext *dc, const uint32_t arg[],
+static void translate_dcache(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
TCGv_i32 res = tcg_temp_new_i32();
- tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]);
+ tcg_gen_addi_i32(addr, arg[0].in, arg[1].imm);
tcg_gen_qemu_ld8u(res, addr, dc->cring);
tcg_temp_free(addr);
tcg_temp_free(res);
}
-static void translate_depbits(DisasContext *dc, const uint32_t arg[],
+static void translate_depbits(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_deposit_i32(cpu_R[arg[1]], cpu_R[arg[1]], cpu_R[arg[0]],
- arg[2], arg[3]);
+ tcg_gen_deposit_i32(arg[1].out, arg[1].in, arg[0].in,
+ arg[2].imm, arg[3].imm);
}
-static bool test_ill_entry(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_entry(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- if (arg[0] > 3 || !dc->cwoe) {
+ if (arg[0].imm > 3 || !dc->cwoe) {
qemu_log_mask(LOG_GUEST_ERROR,
"Illegal entry instruction(pc = %08x)\n", dc->pc);
return true;
@@ -1774,88 +1792,88 @@ static bool test_ill_entry(DisasContext *dc, const uint32_t arg[],
}
}
-static uint32_t test_overflow_entry(DisasContext *dc, const uint32_t arg[],
+static uint32_t test_overflow_entry(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
return 1 << (dc->callinc * 4);
}
-static void translate_entry(DisasContext *dc, const uint32_t arg[],
+static void translate_entry(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 pc = tcg_const_i32(dc->pc);
- TCGv_i32 s = tcg_const_i32(arg[0]);
- TCGv_i32 imm = tcg_const_i32(arg[1]);
+ TCGv_i32 s = tcg_const_i32(arg[0].imm);
+ TCGv_i32 imm = tcg_const_i32(arg[1].imm);
gen_helper_entry(cpu_env, pc, s, imm);
tcg_temp_free(imm);
tcg_temp_free(s);
tcg_temp_free(pc);
}
-static void translate_extui(DisasContext *dc, const uint32_t arg[],
+static void translate_extui(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- int maskimm = (1 << arg[3]) - 1;
+ int maskimm = (1 << arg[3].imm) - 1;
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shri_i32(tmp, cpu_R[arg[1]], arg[2]);
- tcg_gen_andi_i32(cpu_R[arg[0]], tmp, maskimm);
+ tcg_gen_shri_i32(tmp, arg[1].in, arg[2].imm);
+ tcg_gen_andi_i32(arg[0].out, tmp, maskimm);
tcg_temp_free(tmp);
}
-static void translate_icache(DisasContext *dc, const uint32_t arg[],
+static void translate_icache(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
TCGv_i32 addr = tcg_temp_new_i32();
tcg_gen_movi_i32(cpu_pc, dc->pc);
- tcg_gen_addi_i32(addr, cpu_R[arg[0]], arg[1]);
+ tcg_gen_addi_i32(addr, arg[0].in, arg[1].imm);
gen_helper_itlb_hit_test(cpu_env, addr);
tcg_temp_free(addr);
#endif
}
-static void translate_itlb(DisasContext *dc, const uint32_t arg[],
+static void translate_itlb(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
TCGv_i32 dtlb = tcg_const_i32(par[0]);
- gen_helper_itlb(cpu_env, cpu_R[arg[0]], dtlb);
+ gen_helper_itlb(cpu_env, arg[0].in, dtlb);
tcg_temp_free(dtlb);
#endif
}
-static void translate_j(DisasContext *dc, const uint32_t arg[],
+static void translate_j(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_jumpi(dc, arg[0], 0);
+ gen_jumpi(dc, arg[0].imm, 0);
}
-static void translate_jx(DisasContext *dc, const uint32_t arg[],
+static void translate_jx(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_jump(dc, cpu_R[arg[0]]);
+ gen_jump(dc, arg[0].in);
}
-static void translate_l32e(DisasContext *dc, const uint32_t arg[],
+static void translate_l32e(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
- tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+ tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
gen_load_store_alignment(dc, 2, addr, false);
- tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL);
+ tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->ring, MO_TEUL);
tcg_temp_free(addr);
}
-static void translate_ldst(DisasContext *dc, const uint32_t arg[],
+static void translate_ldst(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
- tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+ tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
if (par[0] & MO_SIZE) {
gen_load_store_alignment(dc, par[0] & MO_SIZE, addr, par[1]);
}
@@ -1863,9 +1881,9 @@ static void translate_ldst(DisasContext *dc, const uint32_t arg[],
if (par[1]) {
tcg_gen_mb(TCG_BAR_STRL | TCG_MO_ALL);
}
- tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->cring, par[0]);
+ tcg_gen_qemu_st_tl(arg[0].in, addr, dc->cring, par[0]);
} else {
- tcg_gen_qemu_ld_tl(cpu_R[arg[0]], addr, dc->cring, par[0]);
+ tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->cring, par[0]);
if (par[1]) {
tcg_gen_mb(TCG_BAR_LDAQ | TCG_MO_ALL);
}
@@ -1873,33 +1891,33 @@ static void translate_ldst(DisasContext *dc, const uint32_t arg[],
tcg_temp_free(addr);
}
-static void translate_l32r(DisasContext *dc, const uint32_t arg[],
+static void translate_l32r(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp;
if (dc->base.tb->flags & XTENSA_TBFLAG_LITBASE) {
- tmp = tcg_const_i32(dc->raw_arg[1] - 1);
+ tmp = tcg_const_i32(arg[1].raw_imm - 1);
tcg_gen_add_i32(tmp, cpu_SR[LITBASE], tmp);
} else {
- tmp = tcg_const_i32(arg[1]);
+ tmp = tcg_const_i32(arg[1].imm);
}
- tcg_gen_qemu_ld32u(cpu_R[arg[0]], tmp, dc->cring);
+ tcg_gen_qemu_ld32u(arg[0].out, tmp, dc->cring);
tcg_temp_free(tmp);
}
-static void translate_loop(DisasContext *dc, const uint32_t arg[],
+static void translate_loop(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- uint32_t lend = arg[1];
+ uint32_t lend = arg[1].imm;
- tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[arg[0]], 1);
+ tcg_gen_subi_i32(cpu_SR[LCOUNT], arg[0].in, 1);
tcg_gen_movi_i32(cpu_SR[LBEG], dc->base.pc_next);
tcg_gen_movi_i32(cpu_SR[LEND], lend);
if (par[0] != TCG_COND_NEVER) {
TCGLabel *label = gen_new_label();
- tcg_gen_brcondi_i32(par[0], cpu_R[arg[0]], 0, label);
+ tcg_gen_brcondi_i32(par[0], arg[0].in, 0, label);
gen_jumpi(dc, lend, 1);
gen_set_label(label);
}
@@ -1935,7 +1953,7 @@ enum {
MAC16_DX = 0x2,
};
-static void translate_mac16(DisasContext *dc, const uint32_t arg[],
+static void translate_mac16(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
int op = par[0];
@@ -1948,18 +1966,18 @@ static void translate_mac16(DisasContext *dc, const uint32_t arg[],
TCGv_i32 mem32 = tcg_temp_new_i32();
if (ld_offset) {
- tcg_gen_addi_i32(vaddr, cpu_R[arg[1]], ld_offset);
+ tcg_gen_addi_i32(vaddr, arg[1].in, ld_offset);
gen_load_store_alignment(dc, 2, vaddr, false);
tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring);
}
if (op != MAC16_NONE) {
TCGv_i32 m1 = gen_mac16_m(is_m1_sr ?
- cpu_SR[MR + arg[off]] :
- cpu_R[arg[off]],
+ cpu_SR[MR + arg[off].imm] :
+ arg[off].in,
half & MAC16_HX, op == MAC16_UMUL);
TCGv_i32 m2 = gen_mac16_m(is_m2_sr ?
- cpu_SR[MR + arg[off + 1]] :
- cpu_R[arg[off + 1]],
+ cpu_SR[MR + arg[off + 1].imm] :
+ arg[off + 1].in,
half & MAC16_XH, op == MAC16_UMUL);
if (op == MAC16_MUL || op == MAC16_UMUL) {
@@ -1993,221 +2011,221 @@ static void translate_mac16(DisasContext *dc, const uint32_t arg[],
tcg_temp_free(m2);
}
if (ld_offset) {
- tcg_gen_mov_i32(cpu_R[arg[1]], vaddr);
- tcg_gen_mov_i32(cpu_SR[MR + arg[0]], mem32);
+ tcg_gen_mov_i32(arg[1].out, vaddr);
+ tcg_gen_mov_i32(cpu_SR[MR + arg[0].imm], mem32);
}
tcg_temp_free(vaddr);
tcg_temp_free(mem32);
}
-static void translate_memw(DisasContext *dc, const uint32_t arg[],
+static void translate_memw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
}
-static void translate_smin(DisasContext *dc, const uint32_t arg[],
+static void translate_smin(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_smin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_smin_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_umin(DisasContext *dc, const uint32_t arg[],
+static void translate_umin(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_umin_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_umin_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_smax(DisasContext *dc, const uint32_t arg[],
+static void translate_smax(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_smax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_smax_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_umax(DisasContext *dc, const uint32_t arg[],
+static void translate_umax(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_umax_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_umax_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_mov(DisasContext *dc, const uint32_t arg[],
+static void translate_mov(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_mov_i32(arg[0].out, arg[1].in);
}
-static void translate_movcond(DisasContext *dc, const uint32_t arg[],
+static void translate_movcond(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 zero = tcg_const_i32(0);
- tcg_gen_movcond_i32(par[0], cpu_R[arg[0]],
- cpu_R[arg[2]], zero, cpu_R[arg[1]], cpu_R[arg[0]]);
+ tcg_gen_movcond_i32(par[0], arg[0].out,
+ arg[2].in, zero, arg[1].in, arg[0].in);
tcg_temp_free(zero);
}
-static void translate_movi(DisasContext *dc, const uint32_t arg[],
+static void translate_movi(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_movi_i32(cpu_R[arg[0]], arg[1]);
+ tcg_gen_movi_i32(arg[0].out, arg[1].imm);
}
-static void translate_movp(DisasContext *dc, const uint32_t arg[],
+static void translate_movp(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 zero = tcg_const_i32(0);
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]);
+ tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2].imm);
tcg_gen_movcond_i32(par[0],
- cpu_R[arg[0]], tmp, zero,
- cpu_R[arg[1]], cpu_R[arg[0]]);
+ arg[0].out, tmp, zero,
+ arg[1].in, arg[0].in);
tcg_temp_free(tmp);
tcg_temp_free(zero);
}
-static void translate_movsp(DisasContext *dc, const uint32_t arg[],
+static void translate_movsp(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_mov_i32(arg[0].out, arg[1].in);
}
-static void translate_mul16(DisasContext *dc, const uint32_t arg[],
+static void translate_mul16(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 v1 = tcg_temp_new_i32();
TCGv_i32 v2 = tcg_temp_new_i32();
if (par[0]) {
- tcg_gen_ext16s_i32(v1, cpu_R[arg[1]]);
- tcg_gen_ext16s_i32(v2, cpu_R[arg[2]]);
+ tcg_gen_ext16s_i32(v1, arg[1].in);
+ tcg_gen_ext16s_i32(v2, arg[2].in);
} else {
- tcg_gen_ext16u_i32(v1, cpu_R[arg[1]]);
- tcg_gen_ext16u_i32(v2, cpu_R[arg[2]]);
+ tcg_gen_ext16u_i32(v1, arg[1].in);
+ tcg_gen_ext16u_i32(v2, arg[2].in);
}
- tcg_gen_mul_i32(cpu_R[arg[0]], v1, v2);
+ tcg_gen_mul_i32(arg[0].out, v1, v2);
tcg_temp_free(v2);
tcg_temp_free(v1);
}
-static void translate_mull(DisasContext *dc, const uint32_t arg[],
+static void translate_mull(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mul_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_mul_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_mulh(DisasContext *dc, const uint32_t arg[],
+static void translate_mulh(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 lo = tcg_temp_new();
if (par[0]) {
- tcg_gen_muls2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_muls2_i32(lo, arg[0].out, arg[1].in, arg[2].in);
} else {
- tcg_gen_mulu2_i32(lo, cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_mulu2_i32(lo, arg[0].out, arg[1].in, arg[2].in);
}
tcg_temp_free(lo);
}
-static void translate_neg(DisasContext *dc, const uint32_t arg[],
+static void translate_neg(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_neg_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_neg_i32(arg[0].out, arg[1].in);
}
-static void translate_nop(DisasContext *dc, const uint32_t arg[],
+static void translate_nop(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
}
-static void translate_nsa(DisasContext *dc, const uint32_t arg[],
+static void translate_nsa(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_clrsb_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_clrsb_i32(arg[0].out, arg[1].in);
}
-static void translate_nsau(DisasContext *dc, const uint32_t arg[],
+static void translate_nsau(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_clzi_i32(cpu_R[arg[0]], cpu_R[arg[1]], 32);
+ tcg_gen_clzi_i32(arg[0].out, arg[1].in, 32);
}
-static void translate_or(DisasContext *dc, const uint32_t arg[],
+static void translate_or(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_or_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_or_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_ptlb(DisasContext *dc, const uint32_t arg[],
+static void translate_ptlb(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
TCGv_i32 dtlb = tcg_const_i32(par[0]);
tcg_gen_movi_i32(cpu_pc, dc->pc);
- gen_helper_ptlb(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb);
+ gen_helper_ptlb(arg[0].out, cpu_env, arg[1].in, dtlb);
tcg_temp_free(dtlb);
#endif
}
-static void translate_quos(DisasContext *dc, const uint32_t arg[],
+static void translate_quos(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGLabel *label1 = gen_new_label();
TCGLabel *label2 = gen_new_label();
- tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[1]], 0x80000000,
+ tcg_gen_brcondi_i32(TCG_COND_NE, arg[1].in, 0x80000000,
label1);
- tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[arg[2]], 0xffffffff,
+ tcg_gen_brcondi_i32(TCG_COND_NE, arg[2].in, 0xffffffff,
label1);
- tcg_gen_movi_i32(cpu_R[arg[0]],
+ tcg_gen_movi_i32(arg[0].out,
par[0] ? 0x80000000 : 0);
tcg_gen_br(label2);
gen_set_label(label1);
if (par[0]) {
- tcg_gen_div_i32(cpu_R[arg[0]],
- cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_div_i32(arg[0].out,
+ arg[1].in, arg[2].in);
} else {
- tcg_gen_rem_i32(cpu_R[arg[0]],
- cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_rem_i32(arg[0].out,
+ arg[1].in, arg[2].in);
}
gen_set_label(label2);
}
-static void translate_quou(DisasContext *dc, const uint32_t arg[],
+static void translate_quou(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_divu_i32(cpu_R[arg[0]],
- cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_divu_i32(arg[0].out,
+ arg[1].in, arg[2].in);
}
-static void translate_read_impwire(DisasContext *dc, const uint32_t arg[],
+static void translate_read_impwire(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
/* TODO: GPIO32 may be a part of coprocessor */
- tcg_gen_movi_i32(cpu_R[arg[0]], 0);
+ tcg_gen_movi_i32(arg[0].out, 0);
}
-static void translate_remu(DisasContext *dc, const uint32_t arg[],
+static void translate_remu(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_remu_i32(cpu_R[arg[0]],
- cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_remu_i32(arg[0].out,
+ arg[1].in, arg[2].in);
}
-static void translate_rer(DisasContext *dc, const uint32_t arg[],
+static void translate_rer(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_rer(cpu_R[arg[0]], cpu_env, cpu_R[arg[1]]);
+ gen_helper_rer(arg[0].out, cpu_env, arg[1].in);
}
-static void translate_ret(DisasContext *dc, const uint32_t arg[],
+static void translate_ret(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
gen_jump(dc, cpu_R[0]);
}
-static bool test_ill_retw(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_retw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (!dc->cwoe) {
@@ -2223,7 +2241,7 @@ static bool test_ill_retw(DisasContext *dc, const uint32_t arg[],
}
}
-static void translate_retw(DisasContext *dc, const uint32_t arg[],
+static void translate_retw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_const_i32(1);
@@ -2237,27 +2255,27 @@ static void translate_retw(DisasContext *dc, const uint32_t arg[],
tcg_temp_free(tmp);
}
-static void translate_rfde(DisasContext *dc, const uint32_t arg[],
+static void translate_rfde(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
gen_jump(dc, cpu_SR[dc->config->ndepc ? DEPC : EPC1]);
}
-static void translate_rfe(DisasContext *dc, const uint32_t arg[],
+static void translate_rfe(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
gen_jump(dc, cpu_SR[EPC1]);
}
-static void translate_rfi(DisasContext *dc, const uint32_t arg[],
+static void translate_rfi(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + arg[0] - 2]);
- gen_jump(dc, cpu_SR[EPC1 + arg[0] - 1]);
+ tcg_gen_mov_i32(cpu_SR[PS], cpu_SR[EPS2 + arg[0].imm - 2]);
+ gen_jump(dc, cpu_SR[EPC1 + arg[0].imm - 1]);
}
-static void translate_rfw(DisasContext *dc, const uint32_t arg[],
+static void translate_rfw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_const_i32(1);
@@ -2278,33 +2296,33 @@ static void translate_rfw(DisasContext *dc, const uint32_t arg[],
gen_jump(dc, cpu_SR[EPC1]);
}
-static void translate_rotw(DisasContext *dc, const uint32_t arg[],
+static void translate_rotw(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_addi_i32(cpu_windowbase_next, cpu_SR[WINDOW_BASE], arg[0]);
+ tcg_gen_addi_i32(cpu_windowbase_next, cpu_SR[WINDOW_BASE], arg[0].imm);
}
-static void translate_rsil(DisasContext *dc, const uint32_t arg[],
+static void translate_rsil(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_R[arg[0]], cpu_SR[PS]);
+ tcg_gen_mov_i32(arg[0].out, cpu_SR[PS]);
tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL);
- tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1]);
+ tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], arg[1].imm);
}
-static bool test_ill_rsr(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_rsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
return !check_sr(dc, par[0], SR_R);
}
-static void translate_rsr(DisasContext *dc, const uint32_t arg[],
+static void translate_rsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_rsr(dc, cpu_R[arg[0]], par[0]);
+ gen_rsr(dc, arg[0].out, par[0]);
}
-static void translate_rtlb(DisasContext *dc, const uint32_t arg[],
+static void translate_rtlb(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
@@ -2315,26 +2333,26 @@ static void translate_rtlb(DisasContext *dc, const uint32_t arg[],
};
TCGv_i32 dtlb = tcg_const_i32(par[0]);
- helper[par[1]](cpu_R[arg[0]], cpu_env, cpu_R[arg[1]], dtlb);
+ helper[par[1]](arg[0].out, cpu_env, arg[1].in, dtlb);
tcg_temp_free(dtlb);
#endif
}
-static void translate_rur(DisasContext *dc, const uint32_t arg[],
+static void translate_rur(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (uregnames[par[0]].name) {
- tcg_gen_mov_i32(cpu_R[arg[0]], cpu_UR[par[0]]);
+ tcg_gen_mov_i32(arg[0].out, cpu_UR[par[0]]);
} else {
qemu_log_mask(LOG_UNIMP, "RUR %d not implemented\n", par[0]);
}
}
-static void translate_setb_expstate(DisasContext *dc, const uint32_t arg[],
+static void translate_setb_expstate(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
/* TODO: GPIO32 may be a part of coprocessor */
- tcg_gen_ori_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], 1u << arg[0]);
+ tcg_gen_ori_i32(cpu_UR[EXPSTATE], cpu_UR[EXPSTATE], 1u << arg[0].imm);
}
#ifdef CONFIG_USER_ONLY
@@ -2351,59 +2369,59 @@ static void gen_check_atomctl(DisasContext *dc, TCGv_i32 addr)
}
#endif
-static void translate_s32c1i(DisasContext *dc, const uint32_t arg[],
+static void translate_s32c1i(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_local_new_i32();
TCGv_i32 addr = tcg_temp_local_new_i32();
- tcg_gen_mov_i32(tmp, cpu_R[arg[0]]);
- tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+ tcg_gen_mov_i32(tmp, arg[0].in);
+ tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
gen_load_store_alignment(dc, 2, addr, true);
gen_check_atomctl(dc, addr);
- tcg_gen_atomic_cmpxchg_i32(cpu_R[arg[0]], addr, cpu_SR[SCOMPARE1],
+ tcg_gen_atomic_cmpxchg_i32(arg[0].out, addr, cpu_SR[SCOMPARE1],
tmp, dc->cring, MO_TEUL);
tcg_temp_free(addr);
tcg_temp_free(tmp);
}
-static void translate_s32e(DisasContext *dc, const uint32_t arg[],
+static void translate_s32e(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
- tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+ tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
gen_load_store_alignment(dc, 2, addr, false);
- tcg_gen_qemu_st_tl(cpu_R[arg[0]], addr, dc->ring, MO_TEUL);
+ tcg_gen_qemu_st_tl(arg[0].in, addr, dc->ring, MO_TEUL);
tcg_temp_free(addr);
}
-static void translate_salt(DisasContext *dc, const uint32_t arg[],
+static void translate_salt(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
tcg_gen_setcond_i32(par[0],
- cpu_R[arg[0]],
- cpu_R[arg[1]], cpu_R[arg[2]]);
+ arg[0].out,
+ arg[1].in, arg[2].in);
}
-static void translate_sext(DisasContext *dc, const uint32_t arg[],
+static void translate_sext(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- int shift = 31 - arg[2];
+ int shift = 31 - arg[2].imm;
if (shift == 24) {
- tcg_gen_ext8s_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_ext8s_i32(arg[0].out, arg[1].in);
} else if (shift == 16) {
- tcg_gen_ext16s_i32(cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_ext16s_i32(arg[0].out, arg[1].in);
} else {
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shli_i32(tmp, cpu_R[arg[1]], shift);
- tcg_gen_sari_i32(cpu_R[arg[0]], tmp, shift);
+ tcg_gen_shli_i32(tmp, arg[1].in, shift);
+ tcg_gen_sari_i32(arg[0].out, tmp, shift);
tcg_temp_free(tmp);
}
}
-static bool test_ill_simcall(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_simcall(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifdef CONFIG_USER_ONLY
@@ -2417,7 +2435,7 @@ static bool test_ill_simcall(DisasContext *dc, const uint32_t arg[],
return ill;
}
-static void translate_simcall(DisasContext *dc, const uint32_t arg[],
+static void translate_simcall(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
@@ -2433,73 +2451,73 @@ static void translate_simcall(DisasContext *dc, const uint32_t arg[],
TCGv_i64 tmp = tcg_temp_new_i64(); \
tcg_gen_extu_i32_i64(tmp, reg); \
tcg_gen_##cmd##_i64(v, v, tmp); \
- tcg_gen_extrl_i64_i32(cpu_R[arg[0]], v); \
+ tcg_gen_extrl_i64_i32(arg[0].out, v); \
tcg_temp_free_i64(v); \
tcg_temp_free_i64(tmp); \
} while (0)
#define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR])
-static void translate_sll(DisasContext *dc, const uint32_t arg[],
+static void translate_sll(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (dc->sar_m32_5bit) {
- tcg_gen_shl_i32(cpu_R[arg[0]], cpu_R[arg[1]], dc->sar_m32);
+ tcg_gen_shl_i32(arg[0].out, arg[1].in, dc->sar_m32);
} else {
TCGv_i64 v = tcg_temp_new_i64();
TCGv_i32 s = tcg_const_i32(32);
tcg_gen_sub_i32(s, s, cpu_SR[SAR]);
tcg_gen_andi_i32(s, s, 0x3f);
- tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]);
+ tcg_gen_extu_i32_i64(v, arg[1].in);
gen_shift_reg(shl, s);
tcg_temp_free(s);
}
}
-static void translate_slli(DisasContext *dc, const uint32_t arg[],
+static void translate_slli(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- if (arg[2] == 32) {
+ if (arg[2].imm == 32) {
qemu_log_mask(LOG_GUEST_ERROR, "slli a%d, a%d, 32 is undefined\n",
- arg[0], arg[1]);
+ arg[0].imm, arg[1].imm);
}
- tcg_gen_shli_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2] & 0x1f);
+ tcg_gen_shli_i32(arg[0].out, arg[1].in, arg[2].imm & 0x1f);
}
-static void translate_sra(DisasContext *dc, const uint32_t arg[],
+static void translate_sra(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (dc->sar_m32_5bit) {
- tcg_gen_sar_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]);
+ tcg_gen_sar_i32(arg[0].out, arg[1].in, cpu_SR[SAR]);
} else {
TCGv_i64 v = tcg_temp_new_i64();
- tcg_gen_ext_i32_i64(v, cpu_R[arg[1]]);
+ tcg_gen_ext_i32_i64(v, arg[1].in);
gen_shift(sar);
}
}
-static void translate_srai(DisasContext *dc, const uint32_t arg[],
+static void translate_srai(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_sari_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+ tcg_gen_sari_i32(arg[0].out, arg[1].in, arg[2].imm);
}
-static void translate_src(DisasContext *dc, const uint32_t arg[],
+static void translate_src(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i64 v = tcg_temp_new_i64();
- tcg_gen_concat_i32_i64(v, cpu_R[arg[2]], cpu_R[arg[1]]);
+ tcg_gen_concat_i32_i64(v, arg[2].in, arg[1].in);
gen_shift(shr);
}
-static void translate_srl(DisasContext *dc, const uint32_t arg[],
+static void translate_srl(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (dc->sar_m32_5bit) {
- tcg_gen_shr_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_SR[SAR]);
+ tcg_gen_shr_i32(arg[0].out, arg[1].in, cpu_SR[SAR]);
} else {
TCGv_i64 v = tcg_temp_new_i64();
- tcg_gen_extu_i32_i64(v, cpu_R[arg[1]]);
+ tcg_gen_extu_i32_i64(v, arg[1].in);
gen_shift(shr);
}
}
@@ -2507,138 +2525,138 @@ static void translate_srl(DisasContext *dc, const uint32_t arg[],
#undef gen_shift
#undef gen_shift_reg
-static void translate_srli(DisasContext *dc, const uint32_t arg[],
+static void translate_srli(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_shri_i32(cpu_R[arg[0]], cpu_R[arg[1]], arg[2]);
+ tcg_gen_shri_i32(arg[0].out, arg[1].in, arg[2].imm);
}
-static void translate_ssa8b(DisasContext *dc, const uint32_t arg[],
+static void translate_ssa8b(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3);
+ tcg_gen_shli_i32(tmp, arg[0].in, 3);
gen_left_shift_sar(dc, tmp);
tcg_temp_free(tmp);
}
-static void translate_ssa8l(DisasContext *dc, const uint32_t arg[],
+static void translate_ssa8l(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shli_i32(tmp, cpu_R[arg[0]], 3);
+ tcg_gen_shli_i32(tmp, arg[0].in, 3);
gen_right_shift_sar(dc, tmp);
tcg_temp_free(tmp);
}
-static void translate_ssai(DisasContext *dc, const uint32_t arg[],
+static void translate_ssai(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- TCGv_i32 tmp = tcg_const_i32(arg[0]);
+ TCGv_i32 tmp = tcg_const_i32(arg[0].imm);
gen_right_shift_sar(dc, tmp);
tcg_temp_free(tmp);
}
-static void translate_ssl(DisasContext *dc, const uint32_t arg[],
+static void translate_ssl(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_left_shift_sar(dc, cpu_R[arg[0]]);
+ gen_left_shift_sar(dc, arg[0].in);
}
-static void translate_ssr(DisasContext *dc, const uint32_t arg[],
+static void translate_ssr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_right_shift_sar(dc, cpu_R[arg[0]]);
+ gen_right_shift_sar(dc, arg[0].in);
}
-static void translate_sub(DisasContext *dc, const uint32_t arg[],
+static void translate_sub(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_sub_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_sub_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static void translate_subx(DisasContext *dc, const uint32_t arg[],
+static void translate_subx(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_shli_i32(tmp, cpu_R[arg[1]], par[0]);
- tcg_gen_sub_i32(cpu_R[arg[0]], tmp, cpu_R[arg[2]]);
+ tcg_gen_shli_i32(tmp, arg[1].in, par[0]);
+ tcg_gen_sub_i32(arg[0].out, tmp, arg[2].in);
tcg_temp_free(tmp);
}
-static void translate_waiti(DisasContext *dc, const uint32_t arg[],
+static void translate_waiti(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
- gen_waiti(dc, arg[0]);
+ gen_waiti(dc, arg[0].imm);
#endif
}
-static void translate_wtlb(DisasContext *dc, const uint32_t arg[],
+static void translate_wtlb(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
#ifndef CONFIG_USER_ONLY
TCGv_i32 dtlb = tcg_const_i32(par[0]);
- gen_helper_wtlb(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]], dtlb);
+ gen_helper_wtlb(cpu_env, arg[0].in, arg[1].in, dtlb);
tcg_temp_free(dtlb);
#endif
}
-static void translate_wer(DisasContext *dc, const uint32_t arg[],
+static void translate_wer(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_wer(cpu_env, cpu_R[arg[0]], cpu_R[arg[1]]);
+ gen_helper_wer(cpu_env, arg[0].in, arg[1].in);
}
-static void translate_wrmsk_expstate(DisasContext *dc, const uint32_t arg[],
+static void translate_wrmsk_expstate(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
/* TODO: GPIO32 may be a part of coprocessor */
- tcg_gen_and_i32(cpu_UR[EXPSTATE], cpu_R[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_and_i32(cpu_UR[EXPSTATE], arg[0].in, arg[1].in);
}
-static bool test_ill_wsr(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_wsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
return !check_sr(dc, par[0], SR_W);
}
-static void translate_wsr(DisasContext *dc, const uint32_t arg[],
+static void translate_wsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_wsr(dc, par[0], cpu_R[arg[0]]);
+ gen_wsr(dc, par[0], arg[0].in);
}
-static void translate_wur(DisasContext *dc, const uint32_t arg[],
+static void translate_wur(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
if (uregnames[par[0]].name) {
- gen_wur(par[0], cpu_R[arg[0]]);
+ gen_wur(par[0], arg[0].in);
} else {
qemu_log_mask(LOG_UNIMP, "WUR %d not implemented\n", par[0]);
}
}
-static void translate_xor(DisasContext *dc, const uint32_t arg[],
+static void translate_xor(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_xor_i32(cpu_R[arg[0]], cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_xor_i32(arg[0].out, arg[1].in, arg[2].in);
}
-static bool test_ill_xsr(DisasContext *dc, const uint32_t arg[],
+static bool test_ill_xsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
return !check_sr(dc, par[0], SR_X);
}
-static void translate_xsr(DisasContext *dc, const uint32_t arg[],
+static void translate_xsr(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_mov_i32(tmp, cpu_R[arg[0]]);
- gen_rsr(dc, cpu_R[arg[0]], par[0]);
+ tcg_gen_mov_i32(tmp, arg[0].in);
+ gen_rsr(dc, arg[0].out, par[0]);
gen_wsr(dc, par[0], tmp);
tcg_temp_free(tmp);
}
@@ -5142,17 +5160,17 @@ const XtensaOpcodeTranslators xtensa_core_opcodes = {
};
-static void translate_abs_s(DisasContext *dc, const uint32_t arg[],
+static void translate_abs_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_abs_s(cpu_FR[arg[0]], cpu_FR[arg[1]]);
+ gen_helper_abs_s(arg[0].out, arg[1].in);
}
-static void translate_add_s(DisasContext *dc, const uint32_t arg[],
+static void translate_add_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_add_s(cpu_FR[arg[0]], cpu_env,
- cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ gen_helper_add_s(arg[0].out, cpu_env,
+ arg[1].in, arg[2].in);
}
enum {
@@ -5165,7 +5183,7 @@ enum {
COMPARE_ULE,
};
-static void translate_compare_s(DisasContext *dc, const uint32_t arg[],
+static void translate_compare_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
static void (* const helper[])(TCGv_env env, TCGv_i32 bit,
@@ -5178,153 +5196,153 @@ static void translate_compare_s(DisasContext *dc, const uint32_t arg[],
[COMPARE_OLE] = gen_helper_ole_s,
[COMPARE_ULE] = gen_helper_ule_s,
};
- TCGv_i32 bit = tcg_const_i32(1 << arg[0]);
+ TCGv_i32 bit = tcg_const_i32(1 << arg[0].imm);
- helper[par[0]](cpu_env, bit, cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ helper[par[0]](cpu_env, bit, arg[1].in, arg[2].in);
tcg_temp_free(bit);
}
-static void translate_float_s(DisasContext *dc, const uint32_t arg[],
+static void translate_float_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- TCGv_i32 scale = tcg_const_i32(-arg[2]);
+ TCGv_i32 scale = tcg_const_i32(-arg[2].imm);
if (par[0]) {
- gen_helper_uitof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale);
+ gen_helper_uitof(arg[0].out, cpu_env, arg[1].in, scale);
} else {
- gen_helper_itof(cpu_FR[arg[0]], cpu_env, cpu_R[arg[1]], scale);
+ gen_helper_itof(arg[0].out, cpu_env, arg[1].in, scale);
}
tcg_temp_free(scale);
}
-static void translate_ftoi_s(DisasContext *dc, const uint32_t arg[],
+static void translate_ftoi_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 rounding_mode = tcg_const_i32(par[0]);
- TCGv_i32 scale = tcg_const_i32(arg[2]);
+ TCGv_i32 scale = tcg_const_i32(arg[2].imm);
if (par[1]) {
- gen_helper_ftoui(cpu_R[arg[0]], cpu_FR[arg[1]],
+ gen_helper_ftoui(arg[0].out, arg[1].in,
rounding_mode, scale);
} else {
- gen_helper_ftoi(cpu_R[arg[0]], cpu_FR[arg[1]],
+ gen_helper_ftoi(arg[0].out, arg[1].in,
rounding_mode, scale);
}
tcg_temp_free(rounding_mode);
tcg_temp_free(scale);
}
-static void translate_ldsti(DisasContext *dc, const uint32_t arg[],
+static void translate_ldsti(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
- tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
+ tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
gen_load_store_alignment(dc, 2, addr, false);
if (par[0]) {
- tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring);
+ tcg_gen_qemu_st32(arg[0].in, addr, dc->cring);
} else {
- tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring);
+ tcg_gen_qemu_ld32u(arg[0].out, addr, dc->cring);
}
if (par[1]) {
- tcg_gen_mov_i32(cpu_R[arg[1]], addr);
+ tcg_gen_mov_i32(arg[1].out, addr);
}
tcg_temp_free(addr);
}
-static void translate_ldstx(DisasContext *dc, const uint32_t arg[],
+static void translate_ldstx(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 addr = tcg_temp_new_i32();
- tcg_gen_add_i32(addr, cpu_R[arg[1]], cpu_R[arg[2]]);
+ tcg_gen_add_i32(addr, arg[1].in, arg[2].in);
gen_load_store_alignment(dc, 2, addr, false);
if (par[0]) {
- tcg_gen_qemu_st32(cpu_FR[arg[0]], addr, dc->cring);
+ tcg_gen_qemu_st32(arg[0].in, addr, dc->cring);
} else {
- tcg_gen_qemu_ld32u(cpu_FR[arg[0]], addr, dc->cring);
+ tcg_gen_qemu_ld32u(arg[0].out, addr, dc->cring);
}
if (par[1]) {
- tcg_gen_mov_i32(cpu_R[arg[1]], addr);
+ tcg_gen_mov_i32(arg[1].out, addr);
}
tcg_temp_free(addr);
}
-static void translate_madd_s(DisasContext *dc, const uint32_t arg[],
+static void translate_madd_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_madd_s(cpu_FR[arg[0]], cpu_env,
- cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ gen_helper_madd_s(arg[0].out, cpu_env,
+ arg[0].in, arg[1].in, arg[2].in);
}
-static void translate_mov_s(DisasContext *dc, const uint32_t arg[],
+static void translate_mov_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_FR[arg[1]]);
+ tcg_gen_mov_i32(arg[0].out, arg[1].in);
}
-static void translate_movcond_s(DisasContext *dc, const uint32_t arg[],
+static void translate_movcond_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 zero = tcg_const_i32(0);
- tcg_gen_movcond_i32(par[0], cpu_FR[arg[0]],
- cpu_R[arg[2]], zero,
- cpu_FR[arg[1]], cpu_FR[arg[0]]);
+ tcg_gen_movcond_i32(par[0], arg[0].out,
+ arg[2].in, zero,
+ arg[1].in, arg[0].in);
tcg_temp_free(zero);
}
-static void translate_movp_s(DisasContext *dc, const uint32_t arg[],
+static void translate_movp_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
TCGv_i32 zero = tcg_const_i32(0);
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2]);
+ tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2].imm);
tcg_gen_movcond_i32(par[0],
- cpu_FR[arg[0]], tmp, zero,
- cpu_FR[arg[1]], cpu_FR[arg[0]]);
+ arg[0].out, tmp, zero,
+ arg[1].in, arg[0].in);
tcg_temp_free(tmp);
tcg_temp_free(zero);
}
-static void translate_mul_s(DisasContext *dc, const uint32_t arg[],
+static void translate_mul_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_mul_s(cpu_FR[arg[0]], cpu_env,
- cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ gen_helper_mul_s(arg[0].out, cpu_env,
+ arg[1].in, arg[2].in);
}
-static void translate_msub_s(DisasContext *dc, const uint32_t arg[],
+static void translate_msub_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_msub_s(cpu_FR[arg[0]], cpu_env,
- cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ gen_helper_msub_s(arg[0].out, cpu_env,
+ arg[0].in, arg[1].in, arg[2].in);
}
-static void translate_neg_s(DisasContext *dc, const uint32_t arg[],
+static void translate_neg_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_neg_s(cpu_FR[arg[0]], cpu_FR[arg[1]]);
+ gen_helper_neg_s(arg[0].out, arg[1].in);
}
-static void translate_rfr_s(DisasContext *dc, const uint32_t arg[],
+static void translate_rfr_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_R[arg[0]], cpu_FR[arg[1]]);
+ tcg_gen_mov_i32(arg[0].out, arg[1].in);
}
-static void translate_sub_s(DisasContext *dc, const uint32_t arg[],
+static void translate_sub_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- gen_helper_sub_s(cpu_FR[arg[0]], cpu_env,
- cpu_FR[arg[1]], cpu_FR[arg[2]]);
+ gen_helper_sub_s(arg[0].out, cpu_env,
+ arg[1].in, arg[2].in);
}
-static void translate_wfr_s(DisasContext *dc, const uint32_t arg[],
+static void translate_wfr_s(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
- tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_R[arg[1]]);
+ tcg_gen_mov_i32(arg[0].out, arg[1].in);
}
static const XtensaOpcodeOps fpu2000_ops[] = {
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 10/13] target/xtensa: reorganize access to MAC16 registers
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
` (8 preceding siblings ...)
2019-02-14 22:59 ` [Qemu-devel] [PATCH 09/13] target/xtensa: reorganize register handling in translators Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 11/13] target/xtensa: reorganize access to boolean registers Max Filippov
` (2 subsequent siblings)
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
libisa represents MAC16 registers m0..m3 as an MR register file. Add
this register file and reference its registers directly from the
translate_mac16. Drop translator parameter that indicates whether opcode
argument is in ar or in mr.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/translate.c | 186 +++++++++++++++++++++++-----------------------
1 file changed, 92 insertions(+), 94 deletions(-)
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 253777468c29..065e3d01427b 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -79,6 +79,7 @@ struct DisasContext {
static TCGv_i32 cpu_pc;
static TCGv_i32 cpu_R[16];
static TCGv_i32 cpu_FR[16];
+static TCGv_i32 cpu_MR[4];
static TCGv_i32 cpu_SR[256];
static TCGv_i32 cpu_UR[256];
static TCGv_i32 cpu_windowbase_next;
@@ -223,6 +224,9 @@ void xtensa_translate_init(void)
"f8", "f9", "f10", "f11",
"f12", "f13", "f14", "f15",
};
+ static const char * const mregnames[] = {
+ "m0", "m1", "m2", "m3",
+ };
int i;
cpu_pc = tcg_global_mem_new_i32(cpu_env,
@@ -230,14 +234,22 @@ void xtensa_translate_init(void)
for (i = 0; i < 16; i++) {
cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
- offsetof(CPUXtensaState, regs[i]),
- regnames[i]);
+ offsetof(CPUXtensaState, regs[i]),
+ regnames[i]);
}
for (i = 0; i < 16; i++) {
cpu_FR[i] = tcg_global_mem_new_i32(cpu_env,
- offsetof(CPUXtensaState, fregs[i].f32[FP_F32_LOW]),
- fregnames[i]);
+ offsetof(CPUXtensaState,
+ fregs[i].f32[FP_F32_LOW]),
+ fregnames[i]);
+ }
+
+ for (i = 0; i < 4; i++) {
+ cpu_MR[i] = tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUXtensaState,
+ sregs[MR + i]),
+ mregnames[i]);
}
for (i = 0; i < 256; ++i) {
@@ -269,6 +281,8 @@ void **xtensa_get_regfile_by_name(const char *name)
g_hash_table_insert(xtensa_regfile_table,
(void *)"AR", (void *)cpu_R);
g_hash_table_insert(xtensa_regfile_table,
+ (void *)"MR", (void *)cpu_MR);
+ g_hash_table_insert(xtensa_regfile_table,
(void *)"FR", (void *)cpu_FR);
}
return (void **)g_hash_table_lookup(xtensa_regfile_table, (void *)name);
@@ -1943,24 +1957,12 @@ enum {
MAC16_XH = 0x2,
};
-enum {
- MAC16_AA,
- MAC16_AD,
- MAC16_DA,
- MAC16_DD,
-
- MAC16_XD = 0x1,
- MAC16_DX = 0x2,
-};
-
static void translate_mac16(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[])
{
int op = par[0];
- bool is_m1_sr = par[1] & MAC16_DX;
- bool is_m2_sr = par[1] & MAC16_XD;
- unsigned half = par[2];
- uint32_t ld_offset = par[3];
+ unsigned half = par[1];
+ uint32_t ld_offset = par[2];
unsigned off = ld_offset ? 2 : 0;
TCGv_i32 vaddr = tcg_temp_new_i32();
TCGv_i32 mem32 = tcg_temp_new_i32();
@@ -1971,13 +1973,9 @@ static void translate_mac16(DisasContext *dc, const OpcodeArg arg[],
tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring);
}
if (op != MAC16_NONE) {
- TCGv_i32 m1 = gen_mac16_m(is_m1_sr ?
- cpu_SR[MR + arg[off].imm] :
- arg[off].in,
+ TCGv_i32 m1 = gen_mac16_m(arg[off].in,
half & MAC16_HX, op == MAC16_UMUL);
- TCGv_i32 m2 = gen_mac16_m(is_m2_sr ?
- cpu_SR[MR + arg[off + 1].imm] :
- arg[off + 1].in,
+ TCGv_i32 m2 = gen_mac16_m(arg[off + 1].in,
half & MAC16_XH, op == MAC16_UMUL);
if (op == MAC16_MUL || op == MAC16_UMUL) {
@@ -3100,11 +3098,11 @@ static const XtensaOpcodeOps core_ops[] = {
}, {
.name = "lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_NONE, 0, 0, -4},
+ .par = (const uint32_t[]){MAC16_NONE, 0, -4},
}, {
.name = "ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_NONE, 0, 0, 4},
+ .par = (const uint32_t[]){MAC16_NONE, 0, 4},
}, {
.name = "ldpte",
.op_flags = XTENSA_OP_ILL,
@@ -3187,67 +3185,67 @@ static const XtensaOpcodeOps core_ops[] = {
}, {
.name = "mul.aa.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
}, {
.name = "mul.aa.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
}, {
.name = "mul.aa.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
}, {
.name = "mul.aa.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AA, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
}, {
.name = "mul.ad.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
}, {
.name = "mul.ad.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
}, {
.name = "mul.ad.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
}, {
.name = "mul.ad.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_AD, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
}, {
.name = "mul.da.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
}, {
.name = "mul.da.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
}, {
.name = "mul.da.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
}, {
.name = "mul.da.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DA, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
}, {
.name = "mul.dd.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HH, 0},
}, {
.name = "mul.dd.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_HL, 0},
}, {
.name = "mul.dd.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LH, 0},
}, {
.name = "mul.dd.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MUL, MAC16_DD, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MUL, MAC16_LL, 0},
}, {
.name = "mul16s",
.translate = translate_mul16,
@@ -3259,198 +3257,198 @@ static const XtensaOpcodeOps core_ops[] = {
}, {
.name = "mula.aa.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
}, {
.name = "mula.aa.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
}, {
.name = "mula.aa.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
}, {
.name = "mula.aa.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AA, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
}, {
.name = "mula.ad.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
}, {
.name = "mula.ad.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
}, {
.name = "mula.ad.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
}, {
.name = "mula.ad.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_AD, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
}, {
.name = "mula.da.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
}, {
.name = "mula.da.hh.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, -4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, -4},
}, {
.name = "mula.da.hh.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HH, 4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 4},
}, {
.name = "mula.da.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
}, {
.name = "mula.da.hl.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, -4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, -4},
}, {
.name = "mula.da.hl.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_HL, 4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 4},
}, {
.name = "mula.da.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
}, {
.name = "mula.da.lh.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, -4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, -4},
}, {
.name = "mula.da.lh.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LH, 4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 4},
}, {
.name = "mula.da.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
}, {
.name = "mula.da.ll.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, -4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, -4},
}, {
.name = "mula.da.ll.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DA, MAC16_LL, 4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 4},
}, {
.name = "mula.dd.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 0},
}, {
.name = "mula.dd.hh.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, -4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, -4},
}, {
.name = "mula.dd.hh.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HH, 4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HH, 4},
}, {
.name = "mula.dd.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 0},
}, {
.name = "mula.dd.hl.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, -4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, -4},
}, {
.name = "mula.dd.hl.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_HL, 4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_HL, 4},
}, {
.name = "mula.dd.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 0},
}, {
.name = "mula.dd.lh.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, -4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, -4},
}, {
.name = "mula.dd.lh.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LH, 4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LH, 4},
}, {
.name = "mula.dd.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 0},
}, {
.name = "mula.dd.ll.lddec",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, -4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, -4},
}, {
.name = "mula.dd.ll.ldinc",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULA, MAC16_DD, MAC16_LL, 4},
+ .par = (const uint32_t[]){MAC16_MULA, MAC16_LL, 4},
}, {
.name = "mull",
.translate = translate_mull,
}, {
.name = "muls.aa.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
}, {
.name = "muls.aa.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
}, {
.name = "muls.aa.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
}, {
.name = "muls.aa.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AA, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
}, {
.name = "muls.ad.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
}, {
.name = "muls.ad.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
}, {
.name = "muls.ad.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
}, {
.name = "muls.ad.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_AD, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
}, {
.name = "muls.da.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
}, {
.name = "muls.da.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
}, {
.name = "muls.da.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
}, {
.name = "muls.da.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DA, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
}, {
.name = "muls.dd.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HH, 0},
}, {
.name = "muls.dd.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_HL, 0},
}, {
.name = "muls.dd.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LH, 0},
}, {
.name = "muls.dd.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_MULS, MAC16_DD, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_MULS, MAC16_LL, 0},
}, {
.name = "mulsh",
.translate = translate_mulh,
@@ -4160,19 +4158,19 @@ static const XtensaOpcodeOps core_ops[] = {
}, {
.name = "umul.aa.hh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_HH, 0},
+ .par = (const uint32_t[]){MAC16_UMUL, MAC16_HH, 0},
}, {
.name = "umul.aa.hl",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_HL, 0},
+ .par = (const uint32_t[]){MAC16_UMUL, MAC16_HL, 0},
}, {
.name = "umul.aa.lh",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_LH, 0},
+ .par = (const uint32_t[]){MAC16_UMUL, MAC16_LH, 0},
}, {
.name = "umul.aa.ll",
.translate = translate_mac16,
- .par = (const uint32_t[]){MAC16_UMUL, MAC16_AA, MAC16_LL, 0},
+ .par = (const uint32_t[]){MAC16_UMUL, MAC16_LL, 0},
}, {
.name = "waiti",
.translate = translate_waiti,
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 11/13] target/xtensa: reorganize access to boolean registers
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
` (9 preceding siblings ...)
2019-02-14 22:59 ` [Qemu-devel] [PATCH 10/13] target/xtensa: reorganize access to MAC16 registers Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 22:59 ` [Qemu-devel] [PATCH 12/13] target/xtensa: break circular register dependencies Max Filippov
2019-02-14 23:00 ` [Qemu-devel] [PATCH 13/13] target/xtensa: prioritize load/store in FLIX bundles Max Filippov
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
libisa represents boolean registers b0..b16 as a BR register file and as
BR4 and BR8 register groups. Add these register files and use
OpcodeArg::{in,out} parameters to access boolean registers in
translators.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/translate.c | 50 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 42 insertions(+), 8 deletions(-)
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 065e3d01427b..276b435ce81e 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -80,6 +80,9 @@ static TCGv_i32 cpu_pc;
static TCGv_i32 cpu_R[16];
static TCGv_i32 cpu_FR[16];
static TCGv_i32 cpu_MR[4];
+static TCGv_i32 cpu_BR[16];
+static TCGv_i32 cpu_BR4[4];
+static TCGv_i32 cpu_BR8[2];
static TCGv_i32 cpu_SR[256];
static TCGv_i32 cpu_UR[256];
static TCGv_i32 cpu_windowbase_next;
@@ -227,6 +230,12 @@ void xtensa_translate_init(void)
static const char * const mregnames[] = {
"m0", "m1", "m2", "m3",
};
+ static const char * const bregnames[] = {
+ "b0", "b1", "b2", "b3",
+ "b4", "b5", "b6", "b7",
+ "b8", "b9", "b10", "b11",
+ "b12", "b13", "b14", "b15",
+ };
int i;
cpu_pc = tcg_global_mem_new_i32(cpu_env,
@@ -252,6 +261,25 @@ void xtensa_translate_init(void)
mregnames[i]);
}
+ for (i = 0; i < 16; i++) {
+ cpu_BR[i] = tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUXtensaState,
+ sregs[BR]),
+ bregnames[i]);
+ if (i % 4 == 0) {
+ cpu_BR4[i / 4] = tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUXtensaState,
+ sregs[BR]),
+ bregnames[i]);
+ }
+ if (i % 8 == 0) {
+ cpu_BR8[i / 8] = tcg_global_mem_new_i32(cpu_env,
+ offsetof(CPUXtensaState,
+ sregs[BR]),
+ bregnames[i]);
+ }
+ }
+
for (i = 0; i < 256; ++i) {
if (sregnames[i].name) {
cpu_SR[i] = tcg_global_mem_new_i32(cpu_env,
@@ -284,6 +312,12 @@ void **xtensa_get_regfile_by_name(const char *name)
(void *)"MR", (void *)cpu_MR);
g_hash_table_insert(xtensa_regfile_table,
(void *)"FR", (void *)cpu_FR);
+ g_hash_table_insert(xtensa_regfile_table,
+ (void *)"BR", (void *)cpu_BR);
+ g_hash_table_insert(xtensa_regfile_table,
+ (void *)"BR4", (void *)cpu_BR4);
+ g_hash_table_insert(xtensa_regfile_table,
+ (void *)"BR8", (void *)cpu_BR8);
}
return (void **)g_hash_table_lookup(xtensa_regfile_table, (void *)name);
}
@@ -1583,14 +1617,14 @@ static void translate_all(DisasContext *dc, const OpcodeArg arg[],
TCGv_i32 mask = tcg_const_i32(((1 << shift) - 1) << arg[1].imm);
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_and_i32(tmp, cpu_SR[BR], mask);
+ tcg_gen_and_i32(tmp, arg[1].in, mask);
if (par[0]) {
tcg_gen_addi_i32(tmp, tmp, 1 << arg[1].imm);
} else {
tcg_gen_add_i32(tmp, tmp, mask);
}
tcg_gen_shri_i32(tmp, tmp, arg[1].imm + shift);
- tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR],
+ tcg_gen_deposit_i32(arg[0].out, arg[0].out,
tmp, arg[0].imm, 1);
tcg_temp_free(mask);
tcg_temp_free(tmp);
@@ -1694,10 +1728,10 @@ static void translate_boolean(DisasContext *dc, const OpcodeArg arg[],
TCGv_i32 tmp1 = tcg_temp_new_i32();
TCGv_i32 tmp2 = tcg_temp_new_i32();
- tcg_gen_shri_i32(tmp1, cpu_SR[BR], arg[1].imm);
- tcg_gen_shri_i32(tmp2, cpu_SR[BR], arg[2].imm);
+ tcg_gen_shri_i32(tmp1, arg[1].in, arg[1].imm);
+ tcg_gen_shri_i32(tmp2, arg[2].in, arg[2].imm);
op[par[0]](tmp1, tmp1, tmp2);
- tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], tmp1, arg[0].imm, 1);
+ tcg_gen_deposit_i32(arg[0].out, arg[0].out, tmp1, arg[0].imm, 1);
tcg_temp_free(tmp1);
tcg_temp_free(tmp2);
}
@@ -1707,7 +1741,7 @@ static void translate_bp(DisasContext *dc, const OpcodeArg arg[],
{
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[0].imm);
+ tcg_gen_andi_i32(tmp, arg[0].in, 1 << arg[0].imm);
gen_brcondi(dc, par[0], tmp, 0, arg[1].imm);
tcg_temp_free(tmp);
}
@@ -2074,7 +2108,7 @@ static void translate_movp(DisasContext *dc, const OpcodeArg arg[],
TCGv_i32 zero = tcg_const_i32(0);
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2].imm);
+ tcg_gen_andi_i32(tmp, arg[2].in, 1 << arg[2].imm);
tcg_gen_movcond_i32(par[0],
arg[0].out, tmp, zero,
arg[1].in, arg[0].in);
@@ -5296,7 +5330,7 @@ static void translate_movp_s(DisasContext *dc, const OpcodeArg arg[],
TCGv_i32 zero = tcg_const_i32(0);
TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << arg[2].imm);
+ tcg_gen_andi_i32(tmp, arg[2].in, 1 << arg[2].imm);
tcg_gen_movcond_i32(par[0],
arg[0].out, tmp, zero,
arg[1].in, arg[0].in);
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 12/13] target/xtensa: break circular register dependencies
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
` (10 preceding siblings ...)
2019-02-14 22:59 ` [Qemu-devel] [PATCH 11/13] target/xtensa: reorganize access to boolean registers Max Filippov
@ 2019-02-14 22:59 ` Max Filippov
2019-02-14 23:00 ` [Qemu-devel] [PATCH 13/13] target/xtensa: prioritize load/store in FLIX bundles Max Filippov
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 22:59 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
Currently topologic opcode sorting stops at the first detected
dependency loop. Introduce struct opcode_arg_copy that describes
temporary register copy. Scan remaining opcodes searching for
dependencies that can be broken, break them by introducing temporary
register copies and record them in an array. In case of success
create local temporaries and initialize them with current register
values. Share single temporary copy between all register users. Delete
temporaries after translation.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/translate.c | 127 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 123 insertions(+), 4 deletions(-)
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 276b435ce81e..8bc272d05b4b 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -935,6 +935,12 @@ static int gen_postprocess(DisasContext *dc, int slot)
return slot;
}
+struct opcode_arg_copy {
+ uint32_t resource;
+ void *temp;
+ OpcodeArg *arg;
+};
+
struct opcode_arg_info {
uint32_t resource;
int index;
@@ -961,6 +967,11 @@ static uint32_t encode_resource(enum resource_type r, unsigned g, unsigned n)
return (r << 24) | (g << 16) | n;
}
+static enum resource_type get_resource_type(uint32_t resource)
+{
+ return resource >> 24;
+}
+
/*
* a depends on b if b must be executed before a,
* because a's side effects will destroy b's inputs.
@@ -987,6 +998,49 @@ static bool op_depends_on(const struct slot_prop *a,
}
/*
+ * Try to break a dependency on b, append temporary register copy records
+ * to the end of copy and update n_copy in case of success.
+ * This is not always possible: e.g. control flow must always be the last,
+ * load/store must be first and state dependencies are not supported yet.
+ */
+static bool break_dependency(struct slot_prop *a,
+ struct slot_prop *b,
+ struct opcode_arg_copy *copy,
+ unsigned *n_copy)
+{
+ unsigned i = 0;
+ unsigned j = 0;
+ unsigned n = *n_copy;
+ bool rv = false;
+
+ if (a->op_flags & XTENSA_OP_CONTROL_FLOW) {
+ return false;
+ }
+ while (i < a->n_out && j < b->n_in) {
+ if (a->out[i].resource < b->in[j].resource) {
+ ++i;
+ } else if (a->out[i].resource > b->in[j].resource) {
+ ++j;
+ } else {
+ int index = b->in[j].index;
+
+ if (get_resource_type(a->out[i].resource) != RES_REGFILE ||
+ index < 0) {
+ return false;
+ }
+ copy[n].resource = b->in[j].resource;
+ copy[n].arg = b->arg + index;
+ ++n;
+ ++i;
+ ++j;
+ rv = true;
+ }
+ }
+ *n_copy = n;
+ return rv;
+}
+
+/*
* Calculate evaluation order for slot opcodes.
* Build opcode order graph and output its nodes in topological sort order.
* An edge a -> b in the graph means that opcode a must be followed by
@@ -994,7 +1048,9 @@ static bool op_depends_on(const struct slot_prop *a,
*/
static bool tsort(struct slot_prop *slot,
struct slot_prop *sorted[],
- unsigned n)
+ unsigned n,
+ struct opcode_arg_copy *copy,
+ unsigned *n_copy)
{
struct tsnode {
unsigned n_in_edge;
@@ -1007,7 +1063,8 @@ static bool tsort(struct slot_prop *slot,
unsigned n_in = 0;
unsigned n_out = 0;
unsigned n_edge = 0;
- unsigned in_idx;
+ unsigned in_idx = 0;
+ unsigned node_idx = 0;
for (i = 0; i < n; ++i) {
node[i].n_in_edge = 0;
@@ -1035,7 +1092,8 @@ static bool tsort(struct slot_prop *slot,
}
}
- for (in_idx = 0; in_idx < n_in; ++in_idx) {
+again:
+ for (; in_idx < n_in; ++in_idx) {
i = in[in_idx];
sorted[n_out] = slot + i;
++n_out;
@@ -1047,6 +1105,29 @@ static bool tsort(struct slot_prop *slot,
}
}
}
+ if (n_edge) {
+ for (; node_idx < n; ++node_idx) {
+ struct tsnode *cnode = node + node_idx;
+
+ if (cnode->n_in_edge) {
+ for (j = 0; j < cnode->n_out_edge; ++j) {
+ unsigned k = cnode->out_edge[j];
+
+ if (break_dependency(slot + k, slot + node_idx,
+ copy, n_copy) &&
+ --node[k].n_in_edge == 0) {
+ in[n_in] = k;
+ ++n_in;
+ --n_edge;
+ cnode->out_edge[j] =
+ cnode->out_edge[cnode->n_out_edge - 1];
+ --cnode->n_out_edge;
+ goto again;
+ }
+ }
+ }
+ }
+ }
return n_edge == 0;
}
@@ -1084,6 +1165,15 @@ static int resource_compare(const void *a, const void *b)
-1 : (pa->resource > pb->resource ? 1 : 0);
}
+static int arg_copy_compare(const void *a, const void *b)
+{
+ const struct opcode_arg_copy *pa = a;
+ const struct opcode_arg_copy *pb = b;
+
+ return pa->resource < pb->resource ?
+ -1 : (pa->resource > pb->resource ? 1 : 0);
+}
+
static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
{
xtensa_isa isa = dc->config->isa;
@@ -1095,6 +1185,8 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
uint32_t op_flags = 0;
struct slot_prop slot_prop[MAX_INSN_SLOTS];
struct slot_prop *ordered[MAX_INSN_SLOTS];
+ struct opcode_arg_copy arg_copy[MAX_INSN_SLOTS * MAX_OPCODE_ARGS];
+ unsigned n_arg_copy = 0;
uint32_t debug_cause = 0;
uint32_t windowed_register = 0;
uint32_t coprocessor = 0;
@@ -1249,7 +1341,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
}
if (slots > 1) {
- if (!tsort(slot_prop, ordered, slots)) {
+ if (!tsort(slot_prop, ordered, slots, arg_copy, &n_arg_copy)) {
qemu_log_mask(LOG_UNIMP,
"Circular resource dependencies (pc = %08x)\n",
dc->pc);
@@ -1297,6 +1389,29 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
return;
}
+ if (n_arg_copy) {
+ uint32_t resource;
+ void *temp;
+ unsigned j;
+
+ qsort(arg_copy, n_arg_copy, sizeof(*arg_copy), arg_copy_compare);
+ for (i = j = 0; i < n_arg_copy; ++i) {
+ if (i == 0 || arg_copy[i].resource != resource) {
+ resource = arg_copy[i].resource;
+ temp = tcg_temp_local_new();
+ tcg_gen_mov_i32(temp, arg_copy[i].arg->in);
+ arg_copy[i].temp = temp;
+
+ if (i != j) {
+ arg_copy[j] = arg_copy[i];
+ }
+ ++j;
+ }
+ arg_copy[i].arg->in = temp;
+ }
+ n_arg_copy = j;
+ }
+
if (op_flags & XTENSA_OP_DIVIDE_BY_ZERO) {
for (slot = 0; slot < slots; ++slot) {
if (slot_prop[slot].ops->op_flags & XTENSA_OP_DIVIDE_BY_ZERO) {
@@ -1314,6 +1429,10 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
ops->translate(dc, pslot->arg, ops->par);
}
+ for (i = 0; i < n_arg_copy; ++i) {
+ tcg_temp_free(arg_copy[i].temp);
+ }
+
if (dc->base.is_jmp == DISAS_NEXT) {
gen_postprocess(dc, 0);
dc->op_flags = 0;
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 13/13] target/xtensa: prioritize load/store in FLIX bundles
2019-02-14 22:59 [Qemu-devel] [PATCH 00/13] target/xtensa: add FLIX support Max Filippov
` (11 preceding siblings ...)
2019-02-14 22:59 ` [Qemu-devel] [PATCH 12/13] target/xtensa: break circular register dependencies Max Filippov
@ 2019-02-14 23:00 ` Max Filippov
12 siblings, 0 replies; 14+ messages in thread
From: Max Filippov @ 2019-02-14 23:00 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson, Max Filippov
Load/store opcodes may raise MMU exceptions. Normally exceptions should
be checked in priority order before any actual operations, but since MMU
exceptions are tightly coupled with actual memory access, there's
currently no way to do it.
Approximate this behavior by executing all load, then all store, and
then all other opcodes in the FLIX bundles. Use opcode dependency
mechanism to express ordering. Mark load/store opcodes with
XTENSA_OP_{LOAD,STORE} flags. Newer libisa has classifier functions that
can tell whether opcode is a load or store, but this information is not
available in the existing overlays.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
target/xtensa/cpu.h | 4 ++++
target/xtensa/translate.c | 37 ++++++++++++++++++++++++++++++++-----
2 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index bf021f7695e6..a01a94e2a683 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -390,6 +390,10 @@ enum {
XTENSA_OP_NAME_ARRAY = 0x8000,
XTENSA_OP_CONTROL_FLOW = 0x10000,
+ XTENSA_OP_STORE = 0x20000,
+ XTENSA_OP_LOAD = 0x40000,
+ XTENSA_OP_LOAD_STORE =
+ XTENSA_OP_LOAD | XTENSA_OP_STORE,
};
typedef struct XtensaOpcodeOps {
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 8bc272d05b4b..2fd64f8d995d 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -985,6 +985,10 @@ static bool op_depends_on(const struct slot_prop *a,
if (a->op_flags & XTENSA_OP_CONTROL_FLOW) {
return true;
}
+ if ((a->op_flags & XTENSA_OP_LOAD_STORE) <
+ (b->op_flags & XTENSA_OP_LOAD_STORE)) {
+ return true;
+ }
while (i < a->n_out && j < b->n_in) {
if (a->out[i].resource < b->in[j].resource) {
++i;
@@ -1016,6 +1020,10 @@ static bool break_dependency(struct slot_prop *a,
if (a->op_flags & XTENSA_OP_CONTROL_FLOW) {
return false;
}
+ if ((a->op_flags & XTENSA_OP_LOAD_STORE) <
+ (b->op_flags & XTENSA_OP_LOAD_STORE)) {
+ return false;
+ }
while (i < a->n_out && j < b->n_in) {
if (a->out[i].resource < b->in[j].resource) {
++i;
@@ -1292,7 +1300,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
if (slots > 1) {
slot_prop[slot].n_in = 0;
slot_prop[slot].n_out = 0;
- slot_prop[slot].op_flags = 0;
+ slot_prop[slot].op_flags = ops->op_flags & XTENSA_OP_LOAD_STORE;
opnds = xtensa_opcode_num_operands(isa, opc);
@@ -3222,40 +3230,47 @@ static const XtensaOpcodeOps core_ops[] = {
.name = "l16si",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TESW, false, false},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l16ui",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUW, false, false},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l32ai",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, true, false},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l32e",
.translate = translate_l32e,
- .op_flags = XTENSA_OP_PRIVILEGED,
+ .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_LOAD,
}, {
.name = (const char * const[]) {
"l32i", "l32i.n", NULL,
},
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, false, false},
- .op_flags = XTENSA_OP_NAME_ARRAY,
+ .op_flags = XTENSA_OP_NAME_ARRAY | XTENSA_OP_LOAD,
}, {
.name = "l32r",
.translate = translate_l32r,
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "l8ui",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_UB, false, false},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "lddec",
.translate = translate_mac16,
.par = (const uint32_t[]){MAC16_NONE, 0, -4},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "ldinc",
.translate = translate_mac16,
.par = (const uint32_t[]){MAC16_NONE, 0, 4},
+ .op_flags = XTENSA_OP_LOAD,
}, {
.name = "ldpte",
.op_flags = XTENSA_OP_ILL,
@@ -4213,28 +4228,32 @@ static const XtensaOpcodeOps core_ops[] = {
.name = "s16i",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUW, false, true},
+ .op_flags = XTENSA_OP_STORE,
}, {
.name = "s32c1i",
.translate = translate_s32c1i,
+ .op_flags = XTENSA_OP_LOAD | XTENSA_OP_STORE,
}, {
.name = "s32e",
.translate = translate_s32e,
- .op_flags = XTENSA_OP_PRIVILEGED,
+ .op_flags = XTENSA_OP_PRIVILEGED | XTENSA_OP_STORE,
}, {
.name = (const char * const[]) {
"s32i", "s32i.n", "s32nb", NULL,
},
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, false, true},
- .op_flags = XTENSA_OP_NAME_ARRAY,
+ .op_flags = XTENSA_OP_NAME_ARRAY | XTENSA_OP_STORE,
}, {
.name = "s32ri",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_TEUL, true, true},
+ .op_flags = XTENSA_OP_STORE,
}, {
.name = "s8i",
.translate = translate_ldst,
.par = (const uint32_t[]){MO_UB, false, true},
+ .op_flags = XTENSA_OP_STORE,
}, {
.name = "salt",
.translate = translate_salt,
@@ -5524,21 +5543,25 @@ static const XtensaOpcodeOps fpu2000_ops[] = {
.name = "lsi",
.translate = translate_ldsti,
.par = (const uint32_t[]){false, false},
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "lsiu",
.translate = translate_ldsti,
.par = (const uint32_t[]){false, true},
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "lsx",
.translate = translate_ldstx,
.par = (const uint32_t[]){false, false},
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "lsxu",
.translate = translate_ldstx,
.par = (const uint32_t[]){false, true},
+ .op_flags = XTENSA_OP_LOAD,
.coprocessor = 0x1,
}, {
.name = "madd.s",
@@ -5618,21 +5641,25 @@ static const XtensaOpcodeOps fpu2000_ops[] = {
.name = "ssi",
.translate = translate_ldsti,
.par = (const uint32_t[]){true, false},
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "ssiu",
.translate = translate_ldsti,
.par = (const uint32_t[]){true, true},
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "ssx",
.translate = translate_ldstx,
.par = (const uint32_t[]){true, false},
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "ssxu",
.translate = translate_ldstx,
.par = (const uint32_t[]){true, true},
+ .op_flags = XTENSA_OP_STORE,
.coprocessor = 0x1,
}, {
.name = "sub.s",
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread