* [PATCH v3 01/15] target/cris: Add DisasContextBase to DisasContext
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 02/15] target/cris: Remove DISAS_SWI Richard Henderson
` (13 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
Migrate the is_jmp, tb and singlestep_enabled fields
from DisasContext into the base.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 49 +++++++++++++++++----------------
target/cris/translate_v10.c.inc | 4 +--
2 files changed, 27 insertions(+), 26 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 6dd5a267a6..bed7a7ed10 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -85,6 +85,8 @@ static TCGv env_pc;
/* This is the state at translation time. */
typedef struct DisasContext {
+ DisasContextBase base;
+
CRISCPU *cpu;
target_ulong pc, ppc;
@@ -121,7 +123,6 @@ typedef struct DisasContext {
int clear_locked_irq; /* Clear the irq lockout. */
int cpustate_changed;
unsigned int tb_flags; /* tb dependent flags. */
- int is_jmp;
#define JMP_NOJMP 0
#define JMP_DIRECT 1
@@ -131,9 +132,6 @@ typedef struct DisasContext {
uint32_t jmp_pc;
int delayed_branch;
-
- TranslationBlock *tb;
- int singlestep_enabled;
} DisasContext;
static void gen_BUG(DisasContext *dc, const char *file, int line)
@@ -531,7 +529,7 @@ static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
{
#ifndef CONFIG_USER_ONLY
- return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
+ return (dc->base.pc_first & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
(dc->ppc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
#else
return true;
@@ -543,7 +541,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
if (use_goto_tb(dc, dest)) {
tcg_gen_goto_tb(n);
tcg_gen_movi_tl(env_pc, dest);
- tcg_gen_exit_tb(dc->tb, n);
+ tcg_gen_exit_tb(dc->base.tb, n);
} else {
tcg_gen_movi_tl(env_pc, dest);
tcg_gen_exit_tb(NULL, 0);
@@ -2037,14 +2035,14 @@ static int dec_setclrf(CPUCRISState *env, DisasContext *dc)
/* Break the TB if any of the SPI flag changes. */
if (flags & (P_FLAG | S_FLAG)) {
tcg_gen_movi_tl(env_pc, dc->pc + 2);
- dc->is_jmp = DISAS_UPDATE;
+ dc->base.is_jmp = DISAS_UPDATE;
dc->cpustate_changed = 1;
}
/* For the I flag, only act on posedge. */
if ((flags & I_FLAG)) {
tcg_gen_movi_tl(env_pc, dc->pc + 2);
- dc->is_jmp = DISAS_UPDATE;
+ dc->base.is_jmp = DISAS_UPDATE;
dc->cpustate_changed = 1;
}
@@ -2886,14 +2884,14 @@ static int dec_rfe_etc(CPUCRISState *env, DisasContext *dc)
LOG_DIS("rfe\n");
cris_evaluate_flags(dc);
gen_helper_rfe(cpu_env);
- dc->is_jmp = DISAS_UPDATE;
+ dc->base.is_jmp = DISAS_UPDATE;
break;
case 5:
/* rfn. */
LOG_DIS("rfn\n");
cris_evaluate_flags(dc);
gen_helper_rfn(cpu_env);
- dc->is_jmp = DISAS_UPDATE;
+ dc->base.is_jmp = DISAS_UPDATE;
break;
case 6:
LOG_DIS("break %d\n", dc->op1);
@@ -2904,7 +2902,7 @@ static int dec_rfe_etc(CPUCRISState *env, DisasContext *dc)
/* Breaks start at 16 in the exception vector. */
t_gen_movi_env_TN(trap_vector, dc->op1 + 16);
t_gen_raise_exception(EXCP_BREAK);
- dc->is_jmp = DISAS_UPDATE;
+ dc->base.is_jmp = DISAS_UPDATE;
break;
default:
printf("op2=%x\n", dc->op2);
@@ -3146,13 +3144,16 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
* delayslot, like in real hw.
*/
pc_start = tb->pc & ~1;
- dc->cpu = env_archcpu(env);
- dc->tb = tb;
- dc->is_jmp = DISAS_NEXT;
+ dc->base.tb = tb;
+ dc->base.pc_first = pc_start;
+ dc->base.pc_next = pc_start;
+ dc->base.is_jmp = DISAS_NEXT;
+ dc->base.singlestep_enabled = cs->singlestep_enabled;
+
+ dc->cpu = env_archcpu(env);
dc->ppc = pc_start;
dc->pc = pc_start;
- dc->singlestep_enabled = cs->singlestep_enabled;
dc->flags_uptodate = 1;
dc->flagx_known = 1;
dc->flags_x = tb->flags & X_FLAG;
@@ -3189,7 +3190,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
cris_evaluate_flags(dc);
tcg_gen_movi_tl(env_pc, dc->pc);
t_gen_raise_exception(EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
+ dc->base.is_jmp = DISAS_UPDATE;
/* The address covered by the breakpoint must be included in
[tb->pc, tb->pc + tb->size) in order to for it to be
properly cleared -- thus we increment the PC here so that
@@ -3242,18 +3243,18 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
gen_goto_tb(dc, 1, dc->jmp_pc);
gen_set_label(l1);
gen_goto_tb(dc, 0, dc->pc);
- dc->is_jmp = DISAS_TB_JUMP;
+ dc->base.is_jmp = DISAS_TB_JUMP;
dc->jmp = JMP_NOJMP;
} else if (dc->jmp == JMP_DIRECT) {
cris_evaluate_flags(dc);
gen_goto_tb(dc, 0, dc->jmp_pc);
- dc->is_jmp = DISAS_TB_JUMP;
+ dc->base.is_jmp = DISAS_TB_JUMP;
dc->jmp = JMP_NOJMP;
} else {
TCGv c = tcg_const_tl(dc->pc);
t_gen_cc_jmp(env_btarget, c);
tcg_temp_free(c);
- dc->is_jmp = DISAS_JUMP;
+ dc->base.is_jmp = DISAS_JUMP;
}
break;
}
@@ -3264,7 +3265,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
if (!(tb->pc & 1) && cs->singlestep_enabled) {
break;
}
- } while (!dc->is_jmp && !dc->cpustate_changed
+ } while (!dc->base.is_jmp && !dc->cpustate_changed
&& !tcg_op_buf_full()
&& !singlestep
&& (dc->pc - page_start < TARGET_PAGE_SIZE)
@@ -3277,10 +3278,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
npc = dc->pc;
/* Force an update if the per-tb cpu state has changed. */
- if (dc->is_jmp == DISAS_NEXT
+ if (dc->base.is_jmp == DISAS_NEXT
&& (dc->cpustate_changed || !dc->flagx_known
|| (dc->flags_x != (tb->flags & X_FLAG)))) {
- dc->is_jmp = DISAS_UPDATE;
+ dc->base.is_jmp = DISAS_UPDATE;
tcg_gen_movi_tl(env_pc, npc);
}
/* Broken branch+delayslot sequence. */
@@ -3293,12 +3294,12 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
cris_evaluate_flags(dc);
if (unlikely(cs->singlestep_enabled)) {
- if (dc->is_jmp == DISAS_NEXT) {
+ if (dc->base.is_jmp == DISAS_NEXT) {
tcg_gen_movi_tl(env_pc, npc);
}
t_gen_raise_exception(EXCP_DEBUG);
} else {
- switch (dc->is_jmp) {
+ switch (dc->base.is_jmp) {
case DISAS_NEXT:
gen_goto_tb(dc, 1, npc);
break;
diff --git a/target/cris/translate_v10.c.inc b/target/cris/translate_v10.c.inc
index f7cd67be37..dd44a7eb97 100644
--- a/target/cris/translate_v10.c.inc
+++ b/target/cris/translate_v10.c.inc
@@ -1169,7 +1169,7 @@ static unsigned int dec10_ind(CPUCRISState *env, DisasContext *dc)
t_gen_mov_env_TN(trap_vector, c);
tcg_temp_free(c);
t_gen_raise_exception(EXCP_BREAK);
- dc->is_jmp = DISAS_UPDATE;
+ dc->base.is_jmp = DISAS_UPDATE;
return insn_len;
}
LOG_DIS("%d: jump.%d %d r%d r%d\n", __LINE__, size,
@@ -1277,7 +1277,7 @@ static unsigned int crisv10_decoder(CPUCRISState *env, DisasContext *dc)
if (dc->clear_prefix && dc->tb_flags & PFIX_FLAG) {
dc->tb_flags &= ~PFIX_FLAG;
tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~PFIX_FLAG);
- if (dc->tb_flags != dc->tb->flags) {
+ if (dc->tb_flags != dc->base.tb->flags) {
dc->cpustate_changed = 1;
}
}
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 02/15] target/cris: Remove DISAS_SWI
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
2021-06-22 15:48 ` [PATCH v3 01/15] target/cris: Add DisasContextBase to DisasContext Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 03/15] target/cris: Replace DISAS_TB_JUMP with DISAS_NORETURN Richard Henderson
` (12 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
This value is unused.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index bed7a7ed10..8c1bad9564 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -56,7 +56,6 @@
#define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */
#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
-#define DISAS_SWI DISAS_TARGET_3
/* Used by the decoder. */
#define EXTRACT_FIELD(src, start, end) \
@@ -3310,7 +3309,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
to find the next TB */
tcg_gen_exit_tb(NULL, 0);
break;
- case DISAS_SWI:
case DISAS_TB_JUMP:
/* nothing more to generate */
break;
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 03/15] target/cris: Replace DISAS_TB_JUMP with DISAS_NORETURN
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
2021-06-22 15:48 ` [PATCH v3 01/15] target/cris: Add DisasContextBase to DisasContext Richard Henderson
2021-06-22 15:48 ` [PATCH v3 02/15] target/cris: Remove DISAS_SWI Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 04/15] target/cris: Mark exceptions as DISAS_NORETURN Richard Henderson
` (11 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
The only semantic of DISAS_TB_JUMP is that we've done goto_tb,
which is the same as DISAS_NORETURN -- we've exited the tb.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 8c1bad9564..e086ff9131 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -55,7 +55,6 @@
/* is_jmp field values */
#define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */
-#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
/* Used by the decoder. */
#define EXTRACT_FIELD(src, start, end) \
@@ -3242,12 +3241,12 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
gen_goto_tb(dc, 1, dc->jmp_pc);
gen_set_label(l1);
gen_goto_tb(dc, 0, dc->pc);
- dc->base.is_jmp = DISAS_TB_JUMP;
+ dc->base.is_jmp = DISAS_NORETURN;
dc->jmp = JMP_NOJMP;
} else if (dc->jmp == JMP_DIRECT) {
cris_evaluate_flags(dc);
gen_goto_tb(dc, 0, dc->jmp_pc);
- dc->base.is_jmp = DISAS_TB_JUMP;
+ dc->base.is_jmp = DISAS_NORETURN;
dc->jmp = JMP_NOJMP;
} else {
TCGv c = tcg_const_tl(dc->pc);
@@ -3309,7 +3308,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
to find the next TB */
tcg_gen_exit_tb(NULL, 0);
break;
- case DISAS_TB_JUMP:
+ case DISAS_NORETURN:
/* nothing more to generate */
break;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 04/15] target/cris: Mark exceptions as DISAS_NORETURN
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (2 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 03/15] target/cris: Replace DISAS_TB_JUMP with DISAS_NORETURN Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 05/15] target/cris: Fix use_goto_tb Richard Henderson
` (10 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
After we've raised the exception, we have left the TB.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 5 +++--
target/cris/translate_v10.c.inc | 3 ++-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index e086ff9131..24dbae6d58 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -2873,6 +2873,7 @@ static int dec_rfe_etc(CPUCRISState *env, DisasContext *dc)
-offsetof(CRISCPU, env) + offsetof(CPUState, halted));
tcg_gen_movi_tl(env_pc, dc->pc + 2);
t_gen_raise_exception(EXCP_HLT);
+ dc->base.is_jmp = DISAS_NORETURN;
return 2;
}
@@ -2900,7 +2901,7 @@ static int dec_rfe_etc(CPUCRISState *env, DisasContext *dc)
/* Breaks start at 16 in the exception vector. */
t_gen_movi_env_TN(trap_vector, dc->op1 + 16);
t_gen_raise_exception(EXCP_BREAK);
- dc->base.is_jmp = DISAS_UPDATE;
+ dc->base.is_jmp = DISAS_NORETURN;
break;
default:
printf("op2=%x\n", dc->op2);
@@ -3188,7 +3189,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
cris_evaluate_flags(dc);
tcg_gen_movi_tl(env_pc, dc->pc);
t_gen_raise_exception(EXCP_DEBUG);
- dc->base.is_jmp = DISAS_UPDATE;
+ dc->base.is_jmp = DISAS_NORETURN;
/* The address covered by the breakpoint must be included in
[tb->pc, tb->pc + tb->size) in order to for it to be
properly cleared -- thus we increment the PC here so that
diff --git a/target/cris/translate_v10.c.inc b/target/cris/translate_v10.c.inc
index dd44a7eb97..0ba2aca96f 100644
--- a/target/cris/translate_v10.c.inc
+++ b/target/cris/translate_v10.c.inc
@@ -61,6 +61,7 @@ static inline void cris_illegal_insn(DisasContext *dc)
{
qemu_log_mask(LOG_GUEST_ERROR, "illegal insn at pc=%x\n", dc->pc);
t_gen_raise_exception(EXCP_BREAK);
+ dc->base.is_jmp = DISAS_NORETURN;
}
static void gen_store_v10_conditional(DisasContext *dc, TCGv addr, TCGv val,
@@ -1169,7 +1170,7 @@ static unsigned int dec10_ind(CPUCRISState *env, DisasContext *dc)
t_gen_mov_env_TN(trap_vector, c);
tcg_temp_free(c);
t_gen_raise_exception(EXCP_BREAK);
- dc->base.is_jmp = DISAS_UPDATE;
+ dc->base.is_jmp = DISAS_NORETURN;
return insn_len;
}
LOG_DIS("%d: jump.%d %d r%d r%d\n", __LINE__, size,
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 05/15] target/cris: Fix use_goto_tb
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (3 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 04/15] target/cris: Mark exceptions as DISAS_NORETURN Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 06/15] target/cris: Convert to TranslatorOps Richard Henderson
` (9 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
Do not skip the page check for user-only -- mmap/mprotect can
still change page mappings. Only check dc->base.pc_first, not
dc->ppc -- the start page is the only one that's relevant.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 24dbae6d58..9e1f2f9239 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -524,14 +524,9 @@ static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
gen_set_label(l1);
}
-static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
+static bool use_goto_tb(DisasContext *dc, target_ulong dest)
{
-#ifndef CONFIG_USER_ONLY
- return (dc->base.pc_first & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
- (dc->ppc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
-#else
- return true;
-#endif
+ return ((dest ^ dc->base.pc_first) & TARGET_PAGE_MASK) == 0;
}
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 06/15] target/cris: Convert to TranslatorOps
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (4 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 05/15] target/cris: Fix use_goto_tb Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 07/15] target/cris: Mark helper_raise_exception noreturn Richard Henderson
` (8 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 317 ++++++++++++++++++++++------------------
1 file changed, 174 insertions(+), 143 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 9e1f2f9239..eabede5251 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -3114,17 +3114,12 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
*
*/
-/* generate intermediate code for basic block 'tb'. */
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
+static void cris_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
{
+ DisasContext *dc = container_of(dcbase, DisasContext, base);
CPUCRISState *env = cs->env_ptr;
+ uint32_t tb_flags = dc->base.tb->flags;
uint32_t pc_start;
- unsigned int insn_len;
- struct DisasContext ctx;
- struct DisasContext *dc = &ctx;
- uint32_t page_start;
- target_ulong npc;
- int num_insns;
if (env->pregs[PR_VR] == 32) {
dc->decoder = crisv32_decoder;
@@ -3134,150 +3129,174 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
dc->clear_locked_irq = 1;
}
- /* Odd PC indicates that branch is rexecuting due to exception in the
+ /*
+ * Odd PC indicates that branch is rexecuting due to exception in the
* delayslot, like in real hw.
*/
- pc_start = tb->pc & ~1;
-
- dc->base.tb = tb;
+ pc_start = dc->base.pc_first & ~1;
dc->base.pc_first = pc_start;
dc->base.pc_next = pc_start;
- dc->base.is_jmp = DISAS_NEXT;
- dc->base.singlestep_enabled = cs->singlestep_enabled;
dc->cpu = env_archcpu(env);
dc->ppc = pc_start;
dc->pc = pc_start;
dc->flags_uptodate = 1;
dc->flagx_known = 1;
- dc->flags_x = tb->flags & X_FLAG;
+ dc->flags_x = tb_flags & X_FLAG;
dc->cc_x_uptodate = 0;
dc->cc_mask = 0;
dc->update_cc = 0;
dc->clear_prefix = 0;
+ dc->cpustate_changed = 0;
cris_update_cc_op(dc, CC_OP_FLAGS, 4);
dc->cc_size_uptodate = -1;
/* Decode TB flags. */
- dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG \
- | X_FLAG | PFIX_FLAG);
- dc->delayed_branch = !!(tb->flags & 7);
+ dc->tb_flags = tb_flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG | PFIX_FLAG);
+ dc->delayed_branch = !!(tb_flags & 7);
if (dc->delayed_branch) {
dc->jmp = JMP_INDIRECT;
} else {
dc->jmp = JMP_NOJMP;
}
+}
- dc->cpustate_changed = 0;
+static void cris_tr_tb_start(DisasContextBase *db, CPUState *cpu)
+{
+}
- page_start = pc_start & TARGET_PAGE_MASK;
- num_insns = 0;
+static void cris_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+ DisasContext *dc = container_of(dcbase, DisasContext, base);
- gen_tb_start(tb);
- do {
- tcg_gen_insn_start(dc->delayed_branch == 1
- ? dc->ppc | 1 : dc->pc);
- num_insns++;
+ tcg_gen_insn_start(dc->delayed_branch == 1 ? dc->ppc | 1 : dc->pc);
+}
- if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+static bool cris_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
+ const CPUBreakpoint *bp)
+{
+ DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+ cris_evaluate_flags(dc);
+ tcg_gen_movi_tl(env_pc, dc->pc);
+ t_gen_raise_exception(EXCP_DEBUG);
+ dc->base.is_jmp = DISAS_NORETURN;
+ /*
+ * The address covered by the breakpoint must be included in
+ * [tb->pc, tb->pc + tb->size) in order to for it to be
+ * properly cleared -- thus we increment the PC here so that
+ * the logic setting tb->size below does the right thing.
+ */
+ dc->pc += 2;
+ return true;
+}
+
+static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
+{
+ DisasContext *dc = container_of(dcbase, DisasContext, base);
+ CPUCRISState *env = cs->env_ptr;
+ unsigned int insn_len;
+
+ /* Pretty disas. */
+ LOG_DIS("%8.8x:\t", dc->pc);
+
+ dc->clear_x = 1;
+
+ insn_len = dc->decoder(env, dc);
+ dc->ppc = dc->pc;
+ dc->pc += insn_len;
+ dc->base.pc_next += insn_len;
+
+ if (dc->base.is_jmp == DISAS_NORETURN) {
+ return;
+ }
+
+ if (dc->clear_x) {
+ cris_clear_x_flag(dc);
+ }
+
+ /*
+ * Check for delayed branches here. If we do it before
+ * actually generating any host code, the simulator will just
+ * loop doing nothing for on this program location.
+ */
+ if (dc->delayed_branch && --dc->delayed_branch == 0) {
+ if (dc->base.tb->flags & 7) {
+ t_gen_movi_env_TN(dslot, 0);
+ }
+
+ if (dc->cpustate_changed
+ || !dc->flagx_known
+ || (dc->flags_x != (dc->base.tb->flags & X_FLAG))) {
+ cris_store_direct_jmp(dc);
+ }
+
+ if (dc->clear_locked_irq) {
+ dc->clear_locked_irq = 0;
+ t_gen_movi_env_TN(locked_irq, 0);
+ }
+
+ if (dc->jmp == JMP_DIRECT_CC) {
+ TCGLabel *l1 = gen_new_label();
cris_evaluate_flags(dc);
- tcg_gen_movi_tl(env_pc, dc->pc);
- t_gen_raise_exception(EXCP_DEBUG);
+
+ /* Conditional jmp. */
+ tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
+ gen_goto_tb(dc, 1, dc->jmp_pc);
+ gen_set_label(l1);
+ gen_goto_tb(dc, 0, dc->pc);
dc->base.is_jmp = DISAS_NORETURN;
- /* The address covered by the breakpoint must be included in
- [tb->pc, tb->pc + tb->size) in order to for it to be
- properly cleared -- thus we increment the PC here so that
- the logic setting tb->size below does the right thing. */
- dc->pc += 2;
- break;
+ dc->jmp = JMP_NOJMP;
+ } else if (dc->jmp == JMP_DIRECT) {
+ cris_evaluate_flags(dc);
+ gen_goto_tb(dc, 0, dc->jmp_pc);
+ dc->base.is_jmp = DISAS_NORETURN;
+ dc->jmp = JMP_NOJMP;
+ } else {
+ TCGv c = tcg_const_tl(dc->pc);
+ t_gen_cc_jmp(env_btarget, c);
+ tcg_temp_free(c);
+ dc->base.is_jmp = DISAS_JUMP;
}
+ }
- /* Pretty disas. */
- LOG_DIS("%8.8x:\t", dc->pc);
+ /* Force an update if the per-tb cpu state has changed. */
+ if (dc->base.is_jmp == DISAS_NEXT
+ && (dc->cpustate_changed
+ || !dc->flagx_known
+ || (dc->flags_x != (dc->base.tb->flags & X_FLAG)))) {
+ dc->base.is_jmp = DISAS_UPDATE;
+ tcg_gen_movi_tl(env_pc, dc->pc);
+ }
- if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
- gen_io_start();
- }
- dc->clear_x = 1;
+ /*
+ * FIXME: Only the first insn in the TB should cross a page boundary.
+ * If we can detect the length of the next insn easily, we should.
+ * In the meantime, simply stop when we do cross.
+ */
+ if (dc->base.is_jmp == DISAS_NEXT
+ && ((dc->pc ^ dc->base.pc_first) & TARGET_PAGE_MASK) != 0) {
+ dc->base.is_jmp = DISAS_TOO_MANY;
+ }
+}
- insn_len = dc->decoder(env, dc);
- dc->ppc = dc->pc;
- dc->pc += insn_len;
- if (dc->clear_x) {
- cris_clear_x_flag(dc);
- }
+static void cris_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
+{
+ DisasContext *dc = container_of(dcbase, DisasContext, base);
+ DisasJumpType is_jmp = dc->base.is_jmp;
+ target_ulong npc = dc->pc;
- /* Check for delayed branches here. If we do it before
- actually generating any host code, the simulator will just
- loop doing nothing for on this program location. */
- if (dc->delayed_branch) {
- dc->delayed_branch--;
- if (dc->delayed_branch == 0) {
- if (tb->flags & 7) {
- t_gen_movi_env_TN(dslot, 0);
- }
- if (dc->cpustate_changed || !dc->flagx_known
- || (dc->flags_x != (tb->flags & X_FLAG))) {
- cris_store_direct_jmp(dc);
- }
-
- if (dc->clear_locked_irq) {
- dc->clear_locked_irq = 0;
- t_gen_movi_env_TN(locked_irq, 0);
- }
-
- if (dc->jmp == JMP_DIRECT_CC) {
- TCGLabel *l1 = gen_new_label();
- cris_evaluate_flags(dc);
-
- /* Conditional jmp. */
- tcg_gen_brcondi_tl(TCG_COND_EQ,
- env_btaken, 0, l1);
- gen_goto_tb(dc, 1, dc->jmp_pc);
- gen_set_label(l1);
- gen_goto_tb(dc, 0, dc->pc);
- dc->base.is_jmp = DISAS_NORETURN;
- dc->jmp = JMP_NOJMP;
- } else if (dc->jmp == JMP_DIRECT) {
- cris_evaluate_flags(dc);
- gen_goto_tb(dc, 0, dc->jmp_pc);
- dc->base.is_jmp = DISAS_NORETURN;
- dc->jmp = JMP_NOJMP;
- } else {
- TCGv c = tcg_const_tl(dc->pc);
- t_gen_cc_jmp(env_btarget, c);
- tcg_temp_free(c);
- dc->base.is_jmp = DISAS_JUMP;
- }
- break;
- }
- }
-
- /* If we are rexecuting a branch due to exceptions on
- delay slots don't break. */
- if (!(tb->pc & 1) && cs->singlestep_enabled) {
- break;
- }
- } while (!dc->base.is_jmp && !dc->cpustate_changed
- && !tcg_op_buf_full()
- && !singlestep
- && (dc->pc - page_start < TARGET_PAGE_SIZE)
- && num_insns < max_insns);
+ if (is_jmp == DISAS_NORETURN) {
+ /* If we have a broken branch+delayslot sequence, it's too late. */
+ assert(dc->delayed_branch != 1);
+ return;
+ }
if (dc->clear_locked_irq) {
t_gen_movi_env_TN(locked_irq, 0);
}
- npc = dc->pc;
-
- /* Force an update if the per-tb cpu state has changed. */
- if (dc->base.is_jmp == DISAS_NEXT
- && (dc->cpustate_changed || !dc->flagx_known
- || (dc->flags_x != (tb->flags & X_FLAG)))) {
- dc->base.is_jmp = DISAS_UPDATE;
- tcg_gen_movi_tl(env_pc, npc);
- }
/* Broken branch+delayslot sequence. */
if (dc->delayed_branch == 1) {
/* Set env->dslot to the size of the branch insn. */
@@ -3287,45 +3306,57 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
cris_evaluate_flags(dc);
- if (unlikely(cs->singlestep_enabled)) {
- if (dc->base.is_jmp == DISAS_NEXT) {
+ if (unlikely(dc->base.singlestep_enabled)) {
+ switch (is_jmp) {
+ case DISAS_TOO_MANY:
tcg_gen_movi_tl(env_pc, npc);
- }
- t_gen_raise_exception(EXCP_DEBUG);
- } else {
- switch (dc->base.is_jmp) {
- case DISAS_NEXT:
- gen_goto_tb(dc, 1, npc);
- break;
- default:
+ /* fall through */
case DISAS_JUMP:
case DISAS_UPDATE:
- /* indicate that the hash table must be used
- to find the next TB */
- tcg_gen_exit_tb(NULL, 0);
- break;
- case DISAS_NORETURN:
- /* nothing more to generate */
+ t_gen_raise_exception(EXCP_DEBUG);
+ return;
+ default:
break;
}
+ g_assert_not_reached();
}
- gen_tb_end(tb, num_insns);
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
-
-#ifdef DEBUG_DISAS
-#if !DISAS_CRIS
- if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
- && qemu_log_in_addr_range(pc_start)) {
- FILE *logfile = qemu_log_lock();
- qemu_log("--------------\n");
- qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(cs, pc_start, dc->pc - pc_start);
- qemu_log_unlock(logfile);
+ switch (is_jmp) {
+ case DISAS_TOO_MANY:
+ gen_goto_tb(dc, 0, npc);
+ break;
+ case DISAS_JUMP:
+ case DISAS_UPDATE:
+ /* Indicate that interupts must be re-evaluated before the next TB. */
+ tcg_gen_exit_tb(NULL, 0);
+ break;
+ default:
+ g_assert_not_reached();
}
-#endif
-#endif
+}
+
+static void cris_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
+{
+ if (!DISAS_CRIS) {
+ qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
+ log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
+ }
+}
+
+static const TranslatorOps cris_tr_ops = {
+ .init_disas_context = cris_tr_init_disas_context,
+ .tb_start = cris_tr_tb_start,
+ .insn_start = cris_tr_insn_start,
+ .breakpoint_check = cris_tr_breakpoint_check,
+ .translate_insn = cris_tr_translate_insn,
+ .tb_stop = cris_tr_tb_stop,
+ .disas_log = cris_tr_disas_log,
+};
+
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
+{
+ DisasContext dc;
+ translator_loop(&cris_tr_ops, &dc.base, cs, tb, max_insns);
}
void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags)
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 07/15] target/cris: Mark helper_raise_exception noreturn
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (5 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 06/15] target/cris: Convert to TranslatorOps Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 08/15] target/cris: Mark static arrays const Richard Henderson
` (7 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/helper.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/cris/helper.h b/target/cris/helper.h
index 20d21c4358..3abf608682 100644
--- a/target/cris/helper.h
+++ b/target/cris/helper.h
@@ -1,4 +1,4 @@
-DEF_HELPER_2(raise_exception, void, env, i32)
+DEF_HELPER_2(raise_exception, noreturn, env, i32)
DEF_HELPER_2(tlb_flush_pid, void, env, i32)
DEF_HELPER_2(spc_write, void, env, i32)
DEF_HELPER_1(rfe, void, env)
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 08/15] target/cris: Mark static arrays const
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (6 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 07/15] target/cris: Mark helper_raise_exception noreturn Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 09/15] target/cris: Fold unhandled X_FLAG changes into cpustate_changed Richard Henderson
` (6 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 19 ++++++++++---------
target/cris/translate_v10.c.inc | 6 +++---
2 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index eabede5251..e14b7acb10 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -137,14 +137,15 @@ static void gen_BUG(DisasContext *dc, const char *file, int line)
cpu_abort(CPU(dc->cpu), "%s:%d pc=%x\n", file, line, dc->pc);
}
-static const char *regnames_v32[] =
+static const char * const regnames_v32[] =
{
"$r0", "$r1", "$r2", "$r3",
"$r4", "$r5", "$r6", "$r7",
"$r8", "$r9", "$r10", "$r11",
"$r12", "$r13", "$sp", "$acr",
};
-static const char *pregnames_v32[] =
+
+static const char * const pregnames_v32[] =
{
"$bz", "$vr", "$pid", "$srs",
"$wz", "$exs", "$eda", "$mof",
@@ -153,7 +154,7 @@ static const char *pregnames_v32[] =
};
/* We need this table to handle preg-moves with implicit width. */
-static int preg_sizes[] = {
+static const int preg_sizes[] = {
1, /* bz. */
1, /* vr. */
4, /* pid. */
@@ -475,9 +476,9 @@ static inline void t_gen_swapw(TCGv d, TCGv s)
((T0 >> 5) & 0x02020202) |
((T0 >> 7) & 0x01010101));
*/
-static inline void t_gen_swapr(TCGv d, TCGv s)
+static void t_gen_swapr(TCGv d, TCGv s)
{
- struct {
+ static const struct {
int shift; /* LSL when positive, LSR when negative. */
uint32_t mask;
} bitrev[] = {
@@ -1279,7 +1280,7 @@ static int dec_prep_alu_m(CPUCRISState *env, DisasContext *dc,
#if DISAS_CRIS
static const char *cc_name(int cc)
{
- static const char *cc_names[16] = {
+ static const char * const cc_names[16] = {
"cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
"ls", "hi", "ge", "lt", "gt", "le", "a", "p"
};
@@ -2926,7 +2927,7 @@ static int dec_null(CPUCRISState *env, DisasContext *dc)
return 2;
}
-static struct decoder_info {
+static const struct decoder_info {
struct {
uint32_t bits;
uint32_t mask;
@@ -3363,8 +3364,8 @@ void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{
CRISCPU *cpu = CRIS_CPU(cs);
CPUCRISState *env = &cpu->env;
- const char **regnames;
- const char **pregnames;
+ const char * const *regnames;
+ const char * const *pregnames;
int i;
if (!env) {
diff --git a/target/cris/translate_v10.c.inc b/target/cris/translate_v10.c.inc
index 0ba2aca96f..4ab43dc404 100644
--- a/target/cris/translate_v10.c.inc
+++ b/target/cris/translate_v10.c.inc
@@ -21,7 +21,7 @@
#include "qemu/osdep.h"
#include "crisv10-decode.h"
-static const char *regnames_v10[] =
+static const char * const regnames_v10[] =
{
"$r0", "$r1", "$r2", "$r3",
"$r4", "$r5", "$r6", "$r7",
@@ -29,7 +29,7 @@ static const char *regnames_v10[] =
"$r12", "$r13", "$sp", "$pc",
};
-static const char *pregnames_v10[] =
+static const char * const pregnames_v10[] =
{
"$bz", "$vr", "$p2", "$p3",
"$wz", "$ccr", "$p6-prefix", "$mof",
@@ -38,7 +38,7 @@ static const char *pregnames_v10[] =
};
/* We need this table to handle preg-moves with implicit width. */
-static int preg_sizes_v10[] = {
+static const int preg_sizes_v10[] = {
1, /* bz. */
1, /* vr. */
1, /* pid. */
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 09/15] target/cris: Fold unhandled X_FLAG changes into cpustate_changed
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (7 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 08/15] target/cris: Mark static arrays const Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 10/15] target/cris: Add DISAS_UPDATE_NEXT Richard Henderson
` (5 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
We really do this already, by including them into the same test.
This just hoists the expression up a bit.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index e14b7acb10..80276ae84d 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -3217,6 +3217,10 @@ static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
cris_clear_x_flag(dc);
}
+ /* Fold unhandled changes to X_FLAG into cpustate_changed. */
+ dc->cpustate_changed |= !dc->flagx_known;
+ dc->cpustate_changed |= dc->flags_x != (dc->base.tb->flags & X_FLAG);
+
/*
* Check for delayed branches here. If we do it before
* actually generating any host code, the simulator will just
@@ -3227,9 +3231,7 @@ static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
t_gen_movi_env_TN(dslot, 0);
}
- if (dc->cpustate_changed
- || !dc->flagx_known
- || (dc->flags_x != (dc->base.tb->flags & X_FLAG))) {
+ if (dc->cpustate_changed) {
cris_store_direct_jmp(dc);
}
@@ -3263,10 +3265,7 @@ static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
}
/* Force an update if the per-tb cpu state has changed. */
- if (dc->base.is_jmp == DISAS_NEXT
- && (dc->cpustate_changed
- || !dc->flagx_known
- || (dc->flags_x != (dc->base.tb->flags & X_FLAG)))) {
+ if (dc->base.is_jmp == DISAS_NEXT && dc->cpustate_changed) {
dc->base.is_jmp = DISAS_UPDATE;
tcg_gen_movi_tl(env_pc, dc->pc);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 10/15] target/cris: Add DISAS_UPDATE_NEXT
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (8 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 09/15] target/cris: Fold unhandled X_FLAG changes into cpustate_changed Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 11/15] target/cris: Add DISAS_DBRANCH Richard Henderson
` (4 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
Move this pc update into tb_stop.
We will be able to re-use this code shortly.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 80276ae84d..c9822eae4c 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -52,9 +52,15 @@
#define BUG() (gen_BUG(dc, __FILE__, __LINE__))
#define BUG_ON(x) ({if (x) BUG();})
-/* is_jmp field values */
-#define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
-#define DISAS_UPDATE DISAS_TARGET_1 /* cpu state was modified dynamically */
+/*
+ * Target-specific is_jmp field values
+ */
+/* Only pc was modified dynamically */
+#define DISAS_JUMP DISAS_TARGET_0
+/* Cpu state was modified dynamically, including pc */
+#define DISAS_UPDATE DISAS_TARGET_1
+/* Cpu state was modified dynamically, excluding pc -- use npc */
+#define DISAS_UPDATE_NEXT DISAS_TARGET_2
/* Used by the decoder. */
#define EXTRACT_FIELD(src, start, end) \
@@ -3266,8 +3272,8 @@ static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
/* Force an update if the per-tb cpu state has changed. */
if (dc->base.is_jmp == DISAS_NEXT && dc->cpustate_changed) {
- dc->base.is_jmp = DISAS_UPDATE;
- tcg_gen_movi_tl(env_pc, dc->pc);
+ dc->base.is_jmp = DISAS_UPDATE_NEXT;
+ return;
}
/*
@@ -3309,6 +3315,7 @@ static void cris_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
if (unlikely(dc->base.singlestep_enabled)) {
switch (is_jmp) {
case DISAS_TOO_MANY:
+ case DISAS_UPDATE_NEXT:
tcg_gen_movi_tl(env_pc, npc);
/* fall through */
case DISAS_JUMP:
@@ -3325,6 +3332,9 @@ static void cris_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
case DISAS_TOO_MANY:
gen_goto_tb(dc, 0, npc);
break;
+ case DISAS_UPDATE_NEXT:
+ tcg_gen_movi_tl(env_pc, npc);
+ /* fall through */
case DISAS_JUMP:
case DISAS_UPDATE:
/* Indicate that interupts must be re-evaluated before the next TB. */
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 11/15] target/cris: Add DISAS_DBRANCH
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (9 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 10/15] target/cris: Add DISAS_UPDATE_NEXT Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-23 13:43 ` Edgar E. Iglesias
2021-06-22 15:48 ` [PATCH v3 12/15] target/cris: Use tcg_gen_lookup_and_goto_ptr Richard Henderson
` (3 subsequent siblings)
14 siblings, 1 reply; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
Move delayed branch handling to tb_stop, where we can re-use other
end-of-tb code, e.g. the evaluation of flags. Honor single stepping.
Validate that we aren't losing state by overwriting is_jmp.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 96 ++++++++++++++++++++++++-----------------
1 file changed, 56 insertions(+), 40 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index c9822eae4c..f58f6f2e5e 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -61,6 +61,8 @@
#define DISAS_UPDATE DISAS_TARGET_1
/* Cpu state was modified dynamically, excluding pc -- use npc */
#define DISAS_UPDATE_NEXT DISAS_TARGET_2
+/* PC update for delayed branch, see cpustate_changed otherwise */
+#define DISAS_DBRANCH DISAS_TARGET_3
/* Used by the decoder. */
#define EXTRACT_FIELD(src, start, end) \
@@ -3228,50 +3230,22 @@ static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
dc->cpustate_changed |= dc->flags_x != (dc->base.tb->flags & X_FLAG);
/*
- * Check for delayed branches here. If we do it before
- * actually generating any host code, the simulator will just
- * loop doing nothing for on this program location.
+ * All branches are delayed branches, handled immediately below.
+ * We don't expect to see odd combinations of exit conditions.
*/
+ assert(dc->base.is_jmp == DISAS_NEXT || dc->cpustate_changed);
+
if (dc->delayed_branch && --dc->delayed_branch == 0) {
- if (dc->base.tb->flags & 7) {
- t_gen_movi_env_TN(dslot, 0);
- }
+ dc->base.is_jmp = DISAS_DBRANCH;
+ return;
+ }
- if (dc->cpustate_changed) {
- cris_store_direct_jmp(dc);
- }
-
- if (dc->clear_locked_irq) {
- dc->clear_locked_irq = 0;
- t_gen_movi_env_TN(locked_irq, 0);
- }
-
- if (dc->jmp == JMP_DIRECT_CC) {
- TCGLabel *l1 = gen_new_label();
- cris_evaluate_flags(dc);
-
- /* Conditional jmp. */
- tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
- gen_goto_tb(dc, 1, dc->jmp_pc);
- gen_set_label(l1);
- gen_goto_tb(dc, 0, dc->pc);
- dc->base.is_jmp = DISAS_NORETURN;
- dc->jmp = JMP_NOJMP;
- } else if (dc->jmp == JMP_DIRECT) {
- cris_evaluate_flags(dc);
- gen_goto_tb(dc, 0, dc->jmp_pc);
- dc->base.is_jmp = DISAS_NORETURN;
- dc->jmp = JMP_NOJMP;
- } else {
- TCGv c = tcg_const_tl(dc->pc);
- t_gen_cc_jmp(env_btarget, c);
- tcg_temp_free(c);
- dc->base.is_jmp = DISAS_JUMP;
- }
+ if (dc->base.is_jmp != DISAS_NEXT) {
+ return;
}
/* Force an update if the per-tb cpu state has changed. */
- if (dc->base.is_jmp == DISAS_NEXT && dc->cpustate_changed) {
+ if (dc->cpustate_changed) {
dc->base.is_jmp = DISAS_UPDATE_NEXT;
return;
}
@@ -3281,8 +3255,7 @@ static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
* If we can detect the length of the next insn easily, we should.
* In the meantime, simply stop when we do cross.
*/
- if (dc->base.is_jmp == DISAS_NEXT
- && ((dc->pc ^ dc->base.pc_first) & TARGET_PAGE_MASK) != 0) {
+ if ((dc->pc ^ dc->base.pc_first) & TARGET_PAGE_MASK) {
dc->base.is_jmp = DISAS_TOO_MANY;
}
}
@@ -3312,6 +3285,49 @@ static void cris_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
cris_evaluate_flags(dc);
+ /* Evaluate delayed branch destination and fold to another is_jmp case. */
+ if (is_jmp == DISAS_DBRANCH) {
+ if (dc->base.tb->flags & 7) {
+ t_gen_movi_env_TN(dslot, 0);
+ }
+
+ switch (dc->jmp) {
+ case JMP_DIRECT:
+ npc = dc->jmp_pc;
+ is_jmp = dc->cpustate_changed ? DISAS_UPDATE_NEXT : DISAS_TOO_MANY;
+ break;
+
+ case JMP_DIRECT_CC:
+ /*
+ * Use a conditional branch if either taken or not-taken path
+ * can use goto_tb. If neither can, then treat it as indirect.
+ */
+ if (likely(!dc->base.singlestep_enabled)
+ && likely(!dc->cpustate_changed)
+ && (use_goto_tb(dc, dc->jmp_pc) || use_goto_tb(dc, npc))) {
+ TCGLabel *not_taken = gen_new_label();
+
+ tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, not_taken);
+ gen_goto_tb(dc, 1, dc->jmp_pc);
+ gen_set_label(not_taken);
+
+ /* not-taken case handled below. */
+ is_jmp = DISAS_TOO_MANY;
+ break;
+ }
+ tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
+ /* fall through */
+
+ case JMP_INDIRECT:
+ t_gen_cc_jmp(env_btarget, tcg_constant_tl(npc));
+ is_jmp = dc->cpustate_changed ? DISAS_UPDATE : DISAS_JUMP;
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+ }
+
if (unlikely(dc->base.singlestep_enabled)) {
switch (is_jmp) {
case DISAS_TOO_MANY:
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v3 11/15] target/cris: Add DISAS_DBRANCH
2021-06-22 15:48 ` [PATCH v3 11/15] target/cris: Add DISAS_DBRANCH Richard Henderson
@ 2021-06-23 13:43 ` Edgar E. Iglesias
2021-06-23 13:55 ` Richard Henderson
0 siblings, 1 reply; 20+ messages in thread
From: Edgar E. Iglesias @ 2021-06-23 13:43 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, Jun 22, 2021 at 08:48:16AM -0700, Richard Henderson wrote:
> Move delayed branch handling to tb_stop, where we can re-use other
> end-of-tb code, e.g. the evaluation of flags. Honor single stepping.
> Validate that we aren't losing state by overwriting is_jmp.
Hi Richard,
This patch breaks my kernel boot test:
edgar@zapote:cris-axisdev88$ ./qemu-run.sh
+ MACH=-M axis-dev88
+ QEMU_BUILD_PATH=/home/edgar/src/c/qemu/build-qemu/
+ QEMU=/home/edgar/src/c/qemu/build-qemu//cris-softmmu/qemu-system-cris
+ KERNEL=-kernel kimage
+ NIC0=-netdev user,id=net0,hostfwd=tcp::2256-10.0.2.15:21 -net nic,netdev=net0
+ /home/edgar/src/c/qemu/build-qemu//cris-softmmu/qemu-system-cris -M axis-dev88 -netdev user,id=net0,hostfwd=tcp::2256-10.0.2.15:21 -net nic,netdev=net0 -serial stdio -display none -kernel kimage
Linux version 2.6.33 (edgar@edde) (gcc version 4.3.1 20080521 (prerelease) [gcc-4_3-branch revision 135713] (GCC 4.3.1 Axis release R93/1.93) ) #4 Thu Jan 13 15:11:20 CET 2011
bootconsole [early0] enabled
ROM fs in RAM, size 6946816 bytes
Setting up paging and the MMU.
Linux/CRISv32 port on ETRAX FS (C) 2003, 2004 Axis Communications AB
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 4080
Kernel command line: root=/dev/mtdblock3 init=/linuxrc rootfstype=jffs2 mmc_core.use_spi_crc=0 mmc_spi.spi_mode=3
PID hash table entries: 128 (order: -4, 512 bytes)
Dentry cache hash table entries: 4096 (order: 1, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 0, 8192 bytes)
Memory: 22864k/32768k available (2260k kernel code, 9904k reserved, 504k data, 80k init)
Hierarchical RCU implementation.
NR_IRQS:80
Enabling watchdog...
Calibrating delay loop... qemu-system-cris: ../qemu/target/cris/translate.c:3236: cris_tr_translate_insn: Assertion `dc->base.is_jmp == DISAS_NEXT || dc->cpustate_changed' failed.
Aborted (core dumped)
I can share the image if you like.
Best regards,
Edgar
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/cris/translate.c | 96 ++++++++++++++++++++++++-----------------
> 1 file changed, 56 insertions(+), 40 deletions(-)
>
> diff --git a/target/cris/translate.c b/target/cris/translate.c
> index c9822eae4c..f58f6f2e5e 100644
> --- a/target/cris/translate.c
> +++ b/target/cris/translate.c
> @@ -61,6 +61,8 @@
> #define DISAS_UPDATE DISAS_TARGET_1
> /* Cpu state was modified dynamically, excluding pc -- use npc */
> #define DISAS_UPDATE_NEXT DISAS_TARGET_2
> +/* PC update for delayed branch, see cpustate_changed otherwise */
> +#define DISAS_DBRANCH DISAS_TARGET_3
>
> /* Used by the decoder. */
> #define EXTRACT_FIELD(src, start, end) \
> @@ -3228,50 +3230,22 @@ static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
> dc->cpustate_changed |= dc->flags_x != (dc->base.tb->flags & X_FLAG);
>
> /*
> - * Check for delayed branches here. If we do it before
> - * actually generating any host code, the simulator will just
> - * loop doing nothing for on this program location.
> + * All branches are delayed branches, handled immediately below.
> + * We don't expect to see odd combinations of exit conditions.
> */
> + assert(dc->base.is_jmp == DISAS_NEXT || dc->cpustate_changed);
> +
> if (dc->delayed_branch && --dc->delayed_branch == 0) {
> - if (dc->base.tb->flags & 7) {
> - t_gen_movi_env_TN(dslot, 0);
> - }
> + dc->base.is_jmp = DISAS_DBRANCH;
> + return;
> + }
>
> - if (dc->cpustate_changed) {
> - cris_store_direct_jmp(dc);
> - }
> -
> - if (dc->clear_locked_irq) {
> - dc->clear_locked_irq = 0;
> - t_gen_movi_env_TN(locked_irq, 0);
> - }
> -
> - if (dc->jmp == JMP_DIRECT_CC) {
> - TCGLabel *l1 = gen_new_label();
> - cris_evaluate_flags(dc);
> -
> - /* Conditional jmp. */
> - tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
> - gen_goto_tb(dc, 1, dc->jmp_pc);
> - gen_set_label(l1);
> - gen_goto_tb(dc, 0, dc->pc);
> - dc->base.is_jmp = DISAS_NORETURN;
> - dc->jmp = JMP_NOJMP;
> - } else if (dc->jmp == JMP_DIRECT) {
> - cris_evaluate_flags(dc);
> - gen_goto_tb(dc, 0, dc->jmp_pc);
> - dc->base.is_jmp = DISAS_NORETURN;
> - dc->jmp = JMP_NOJMP;
> - } else {
> - TCGv c = tcg_const_tl(dc->pc);
> - t_gen_cc_jmp(env_btarget, c);
> - tcg_temp_free(c);
> - dc->base.is_jmp = DISAS_JUMP;
> - }
> + if (dc->base.is_jmp != DISAS_NEXT) {
> + return;
> }
>
> /* Force an update if the per-tb cpu state has changed. */
> - if (dc->base.is_jmp == DISAS_NEXT && dc->cpustate_changed) {
> + if (dc->cpustate_changed) {
> dc->base.is_jmp = DISAS_UPDATE_NEXT;
> return;
> }
> @@ -3281,8 +3255,7 @@ static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
> * If we can detect the length of the next insn easily, we should.
> * In the meantime, simply stop when we do cross.
> */
> - if (dc->base.is_jmp == DISAS_NEXT
> - && ((dc->pc ^ dc->base.pc_first) & TARGET_PAGE_MASK) != 0) {
> + if ((dc->pc ^ dc->base.pc_first) & TARGET_PAGE_MASK) {
> dc->base.is_jmp = DISAS_TOO_MANY;
> }
> }
> @@ -3312,6 +3285,49 @@ static void cris_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
>
> cris_evaluate_flags(dc);
>
> + /* Evaluate delayed branch destination and fold to another is_jmp case. */
> + if (is_jmp == DISAS_DBRANCH) {
> + if (dc->base.tb->flags & 7) {
> + t_gen_movi_env_TN(dslot, 0);
> + }
> +
> + switch (dc->jmp) {
> + case JMP_DIRECT:
> + npc = dc->jmp_pc;
> + is_jmp = dc->cpustate_changed ? DISAS_UPDATE_NEXT : DISAS_TOO_MANY;
> + break;
> +
> + case JMP_DIRECT_CC:
> + /*
> + * Use a conditional branch if either taken or not-taken path
> + * can use goto_tb. If neither can, then treat it as indirect.
> + */
> + if (likely(!dc->base.singlestep_enabled)
> + && likely(!dc->cpustate_changed)
> + && (use_goto_tb(dc, dc->jmp_pc) || use_goto_tb(dc, npc))) {
> + TCGLabel *not_taken = gen_new_label();
> +
> + tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, not_taken);
> + gen_goto_tb(dc, 1, dc->jmp_pc);
> + gen_set_label(not_taken);
> +
> + /* not-taken case handled below. */
> + is_jmp = DISAS_TOO_MANY;
> + break;
> + }
> + tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
> + /* fall through */
> +
> + case JMP_INDIRECT:
> + t_gen_cc_jmp(env_btarget, tcg_constant_tl(npc));
> + is_jmp = dc->cpustate_changed ? DISAS_UPDATE : DISAS_JUMP;
> + break;
> +
> + default:
> + g_assert_not_reached();
> + }
> + }
> +
> if (unlikely(dc->base.singlestep_enabled)) {
> switch (is_jmp) {
> case DISAS_TOO_MANY:
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v3 11/15] target/cris: Add DISAS_DBRANCH
2021-06-23 13:43 ` Edgar E. Iglesias
@ 2021-06-23 13:55 ` Richard Henderson
2021-06-23 14:17 ` Edgar E. Iglesias
0 siblings, 1 reply; 20+ messages in thread
From: Richard Henderson @ 2021-06-23 13:55 UTC (permalink / raw)
To: Edgar E. Iglesias; +Cc: qemu-devel
On 6/23/21 6:43 AM, Edgar E. Iglesias wrote:
> On Tue, Jun 22, 2021 at 08:48:16AM -0700, Richard Henderson wrote:
>> Move delayed branch handling to tb_stop, where we can re-use other
>> end-of-tb code, e.g. the evaluation of flags. Honor single stepping.
>> Validate that we aren't losing state by overwriting is_jmp.
>
> Hi Richard,
>
> This patch breaks my kernel boot test:
>
> edgar@zapote:cris-axisdev88$ ./qemu-run.sh
> + MACH=-M axis-dev88
> + QEMU_BUILD_PATH=/home/edgar/src/c/qemu/build-qemu/
> + QEMU=/home/edgar/src/c/qemu/build-qemu//cris-softmmu/qemu-system-cris
> + KERNEL=-kernel kimage
> + NIC0=-netdev user,id=net0,hostfwd=tcp::2256-10.0.2.15:21 -net nic,netdev=net0
> + /home/edgar/src/c/qemu/build-qemu//cris-softmmu/qemu-system-cris -M axis-dev88 -netdev user,id=net0,hostfwd=tcp::2256-10.0.2.15:21 -net nic,netdev=net0 -serial stdio -display none -kernel kimage
> Linux version 2.6.33 (edgar@edde) (gcc version 4.3.1 20080521 (prerelease) [gcc-4_3-branch revision 135713] (GCC 4.3.1 Axis release R93/1.93) ) #4 Thu Jan 13 15:11:20 CET 2011
> bootconsole [early0] enabled
> ROM fs in RAM, size 6946816 bytes
> Setting up paging and the MMU.
> Linux/CRISv32 port on ETRAX FS (C) 2003, 2004 Axis Communications AB
> Built 1 zonelists in Zone order, mobility grouping on. Total pages: 4080
> Kernel command line: root=/dev/mtdblock3 init=/linuxrc rootfstype=jffs2 mmc_core.use_spi_crc=0 mmc_spi.spi_mode=3
> PID hash table entries: 128 (order: -4, 512 bytes)
> Dentry cache hash table entries: 4096 (order: 1, 16384 bytes)
> Inode-cache hash table entries: 2048 (order: 0, 8192 bytes)
> Memory: 22864k/32768k available (2260k kernel code, 9904k reserved, 504k data, 80k init)
> Hierarchical RCU implementation.
> NR_IRQS:80
> Enabling watchdog...
> Calibrating delay loop... qemu-system-cris: ../qemu/target/cris/translate.c:3236: cris_tr_translate_insn: Assertion `dc->base.is_jmp == DISAS_NEXT || dc->cpustate_changed' failed.
> Aborted (core dumped)
Ach, I see it -- rfe and rfn set DISAS_UPDATE without cpustate_changed.
Could you try adding dc->cpustate_changed = 1 in dec_rfe_etc, please.
r~
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v3 11/15] target/cris: Add DISAS_DBRANCH
2021-06-23 13:55 ` Richard Henderson
@ 2021-06-23 14:17 ` Edgar E. Iglesias
2021-06-28 14:56 ` Richard Henderson
0 siblings, 1 reply; 20+ messages in thread
From: Edgar E. Iglesias @ 2021-06-23 14:17 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Wed, Jun 23, 2021 at 06:55:49AM -0700, Richard Henderson wrote:
> On 6/23/21 6:43 AM, Edgar E. Iglesias wrote:
> > On Tue, Jun 22, 2021 at 08:48:16AM -0700, Richard Henderson wrote:
> > > Move delayed branch handling to tb_stop, where we can re-use other
> > > end-of-tb code, e.g. the evaluation of flags. Honor single stepping.
> > > Validate that we aren't losing state by overwriting is_jmp.
> >
> > Hi Richard,
> >
> > This patch breaks my kernel boot test:
> >
> > edgar@zapote:cris-axisdev88$ ./qemu-run.sh
> > + MACH=-M axis-dev88
> > + QEMU_BUILD_PATH=/home/edgar/src/c/qemu/build-qemu/
> > + QEMU=/home/edgar/src/c/qemu/build-qemu//cris-softmmu/qemu-system-cris
> > + KERNEL=-kernel kimage
> > + NIC0=-netdev user,id=net0,hostfwd=tcp::2256-10.0.2.15:21 -net nic,netdev=net0
> > + /home/edgar/src/c/qemu/build-qemu//cris-softmmu/qemu-system-cris -M axis-dev88 -netdev user,id=net0,hostfwd=tcp::2256-10.0.2.15:21 -net nic,netdev=net0 -serial stdio -display none -kernel kimage
> > Linux version 2.6.33 (edgar@edde) (gcc version 4.3.1 20080521 (prerelease) [gcc-4_3-branch revision 135713] (GCC 4.3.1 Axis release R93/1.93) ) #4 Thu Jan 13 15:11:20 CET 2011
> > bootconsole [early0] enabled
> > ROM fs in RAM, size 6946816 bytes
> > Setting up paging and the MMU.
> > Linux/CRISv32 port on ETRAX FS (C) 2003, 2004 Axis Communications AB
> > Built 1 zonelists in Zone order, mobility grouping on. Total pages: 4080
> > Kernel command line: root=/dev/mtdblock3 init=/linuxrc rootfstype=jffs2 mmc_core.use_spi_crc=0 mmc_spi.spi_mode=3
> > PID hash table entries: 128 (order: -4, 512 bytes)
> > Dentry cache hash table entries: 4096 (order: 1, 16384 bytes)
> > Inode-cache hash table entries: 2048 (order: 0, 8192 bytes)
> > Memory: 22864k/32768k available (2260k kernel code, 9904k reserved, 504k data, 80k init)
> > Hierarchical RCU implementation.
> > NR_IRQS:80
> > Enabling watchdog...
> > Calibrating delay loop... qemu-system-cris: ../qemu/target/cris/translate.c:3236: cris_tr_translate_insn: Assertion `dc->base.is_jmp == DISAS_NEXT || dc->cpustate_changed' failed.
> > Aborted (core dumped)
>
> Ach, I see it -- rfe and rfn set DISAS_UPDATE without cpustate_changed.
> Could you try adding dc->cpustate_changed = 1 in dec_rfe_etc, please.
>
Great, that fixes it! This now passes all my tests.
With that fix, on the full series:
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Cheers,
Edgar
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v3 11/15] target/cris: Add DISAS_DBRANCH
2021-06-23 14:17 ` Edgar E. Iglesias
@ 2021-06-28 14:56 ` Richard Henderson
0 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-28 14:56 UTC (permalink / raw)
To: Edgar E. Iglesias; +Cc: qemu-devel
On 6/23/21 7:17 AM, Edgar E. Iglesias wrote:
> On Wed, Jun 23, 2021 at 06:55:49AM -0700, Richard Henderson wrote:
>> On 6/23/21 6:43 AM, Edgar E. Iglesias wrote:
>>> On Tue, Jun 22, 2021 at 08:48:16AM -0700, Richard Henderson wrote:
>>>> Move delayed branch handling to tb_stop, where we can re-use other
>>>> end-of-tb code, e.g. the evaluation of flags. Honor single stepping.
>>>> Validate that we aren't losing state by overwriting is_jmp.
>>>
>>> Hi Richard,
>>>
>>> This patch breaks my kernel boot test:
>>>
>>> edgar@zapote:cris-axisdev88$ ./qemu-run.sh
>>> + MACH=-M axis-dev88
>>> + QEMU_BUILD_PATH=/home/edgar/src/c/qemu/build-qemu/
>>> + QEMU=/home/edgar/src/c/qemu/build-qemu//cris-softmmu/qemu-system-cris
>>> + KERNEL=-kernel kimage
>>> + NIC0=-netdev user,id=net0,hostfwd=tcp::2256-10.0.2.15:21 -net nic,netdev=net0
>>> + /home/edgar/src/c/qemu/build-qemu//cris-softmmu/qemu-system-cris -M axis-dev88 -netdev user,id=net0,hostfwd=tcp::2256-10.0.2.15:21 -net nic,netdev=net0 -serial stdio -display none -kernel kimage
>>> Linux version 2.6.33 (edgar@edde) (gcc version 4.3.1 20080521 (prerelease) [gcc-4_3-branch revision 135713] (GCC 4.3.1 Axis release R93/1.93) ) #4 Thu Jan 13 15:11:20 CET 2011
>>> bootconsole [early0] enabled
>>> ROM fs in RAM, size 6946816 bytes
>>> Setting up paging and the MMU.
>>> Linux/CRISv32 port on ETRAX FS (C) 2003, 2004 Axis Communications AB
>>> Built 1 zonelists in Zone order, mobility grouping on. Total pages: 4080
>>> Kernel command line: root=/dev/mtdblock3 init=/linuxrc rootfstype=jffs2 mmc_core.use_spi_crc=0 mmc_spi.spi_mode=3
>>> PID hash table entries: 128 (order: -4, 512 bytes)
>>> Dentry cache hash table entries: 4096 (order: 1, 16384 bytes)
>>> Inode-cache hash table entries: 2048 (order: 0, 8192 bytes)
>>> Memory: 22864k/32768k available (2260k kernel code, 9904k reserved, 504k data, 80k init)
>>> Hierarchical RCU implementation.
>>> NR_IRQS:80
>>> Enabling watchdog...
>>> Calibrating delay loop... qemu-system-cris: ../qemu/target/cris/translate.c:3236: cris_tr_translate_insn: Assertion `dc->base.is_jmp == DISAS_NEXT || dc->cpustate_changed' failed.
>>> Aborted (core dumped)
>>
>> Ach, I see it -- rfe and rfn set DISAS_UPDATE without cpustate_changed.
>> Could you try adding dc->cpustate_changed = 1 in dec_rfe_etc, please.
>>
>
> Great, that fixes it! This now passes all my tests.
>
> With that fix, on the full series:
> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Thanks. Based on private email with Edgar, I'll queue this to tcg-next.
r~
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v3 12/15] target/cris: Use tcg_gen_lookup_and_goto_ptr
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (10 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 11/15] target/cris: Add DISAS_DBRANCH Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 13/15] target/cris: Improve JMP_INDIRECT Richard Henderson
` (2 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
We can use this in gen_goto_tb and for DISAS_JUMP
to indirectly chain to the next TB.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index f58f6f2e5e..ea6efe19d9 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -546,7 +546,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
tcg_gen_exit_tb(dc->base.tb, n);
} else {
tcg_gen_movi_tl(env_pc, dest);
- tcg_gen_exit_tb(NULL, 0);
+ tcg_gen_lookup_and_goto_ptr();
}
}
@@ -3352,6 +3352,8 @@ static void cris_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
tcg_gen_movi_tl(env_pc, npc);
/* fall through */
case DISAS_JUMP:
+ tcg_gen_lookup_and_goto_ptr();
+ break;
case DISAS_UPDATE:
/* Indicate that interupts must be re-evaluated before the next TB. */
tcg_gen_exit_tb(NULL, 0);
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 13/15] target/cris: Improve JMP_INDIRECT
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (11 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 12/15] target/cris: Use tcg_gen_lookup_and_goto_ptr Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 14/15] target/cris: Remove dc->flagx_known Richard Henderson
2021-06-22 15:48 ` [PATCH v3 15/15] target/cris: Do not exit tb for X_FLAG changes Richard Henderson
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
Use movcond instead of brcond to set env_pc.
Discard the btarget and btaken variables to improve
register allocation and avoid unnecessary writeback.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index ea6efe19d9..05be0a41bd 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -522,17 +522,6 @@ static void t_gen_swapr(TCGv d, TCGv s)
tcg_temp_free(org_s);
}
-static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
-{
- TCGLabel *l1 = gen_new_label();
-
- /* Conditional jmp. */
- tcg_gen_mov_tl(env_pc, pc_false);
- tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
- tcg_gen_mov_tl(env_pc, pc_true);
- gen_set_label(l1);
-}
-
static bool use_goto_tb(DisasContext *dc, target_ulong dest)
{
return ((dest ^ dc->base.pc_first) & TARGET_PAGE_MASK) == 0;
@@ -3319,8 +3308,17 @@ static void cris_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
/* fall through */
case JMP_INDIRECT:
- t_gen_cc_jmp(env_btarget, tcg_constant_tl(npc));
+ tcg_gen_movcond_tl(TCG_COND_NE, env_pc,
+ env_btaken, tcg_constant_tl(0),
+ env_btarget, tcg_constant_tl(npc));
is_jmp = dc->cpustate_changed ? DISAS_UPDATE : DISAS_JUMP;
+
+ /*
+ * We have now consumed btaken and btarget. Hint to the
+ * tcg compiler that the writeback to env may be dropped.
+ */
+ tcg_gen_discard_tl(env_btaken);
+ tcg_gen_discard_tl(env_btarget);
break;
default:
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 14/15] target/cris: Remove dc->flagx_known
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (12 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 13/15] target/cris: Improve JMP_INDIRECT Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
2021-06-22 15:48 ` [PATCH v3 15/15] target/cris: Do not exit tb for X_FLAG changes Richard Henderson
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
Ever since 2a44f7f17364, flagx_known is always true.
Fold away all of the tests against the flag.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 99 ++++++++-------------------------
target/cris/translate_v10.c.inc | 6 +-
2 files changed, 24 insertions(+), 81 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 05be0a41bd..45548ffb5e 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -120,8 +120,6 @@ typedef struct DisasContext {
int cc_x_uptodate; /* 1 - ccs, 2 - known | X_FLAG. 0 not up-to-date. */
int flags_uptodate; /* Whether or not $ccs is up-to-date. */
- int flagx_known; /* Whether or not flags_x has the x flag known at
- translation time. */
int flags_x;
int clear_x; /* Clear x after this insn? */
@@ -377,66 +375,26 @@ static inline void t_gen_add_flag(TCGv d, int flag)
static inline void t_gen_addx_carry(DisasContext *dc, TCGv d)
{
- if (dc->flagx_known) {
- if (dc->flags_x) {
- TCGv c;
-
- c = tcg_temp_new();
- t_gen_mov_TN_preg(c, PR_CCS);
- /* C flag is already at bit 0. */
- tcg_gen_andi_tl(c, c, C_FLAG);
- tcg_gen_add_tl(d, d, c);
- tcg_temp_free(c);
- }
- } else {
- TCGv x, c;
+ if (dc->flags_x) {
+ TCGv c = tcg_temp_new();
- x = tcg_temp_new();
- c = tcg_temp_new();
- t_gen_mov_TN_preg(x, PR_CCS);
- tcg_gen_mov_tl(c, x);
-
- /* Propagate carry into d if X is set. Branch free. */
+ t_gen_mov_TN_preg(c, PR_CCS);
+ /* C flag is already at bit 0. */
tcg_gen_andi_tl(c, c, C_FLAG);
- tcg_gen_andi_tl(x, x, X_FLAG);
- tcg_gen_shri_tl(x, x, 4);
-
- tcg_gen_and_tl(x, x, c);
- tcg_gen_add_tl(d, d, x);
- tcg_temp_free(x);
+ tcg_gen_add_tl(d, d, c);
tcg_temp_free(c);
}
}
static inline void t_gen_subx_carry(DisasContext *dc, TCGv d)
{
- if (dc->flagx_known) {
- if (dc->flags_x) {
- TCGv c;
-
- c = tcg_temp_new();
- t_gen_mov_TN_preg(c, PR_CCS);
- /* C flag is already at bit 0. */
- tcg_gen_andi_tl(c, c, C_FLAG);
- tcg_gen_sub_tl(d, d, c);
- tcg_temp_free(c);
- }
- } else {
- TCGv x, c;
+ if (dc->flags_x) {
+ TCGv c = tcg_temp_new();
- x = tcg_temp_new();
- c = tcg_temp_new();
- t_gen_mov_TN_preg(x, PR_CCS);
- tcg_gen_mov_tl(c, x);
-
- /* Propagate carry into d if X is set. Branch free. */
+ t_gen_mov_TN_preg(c, PR_CCS);
+ /* C flag is already at bit 0. */
tcg_gen_andi_tl(c, c, C_FLAG);
- tcg_gen_andi_tl(x, x, X_FLAG);
- tcg_gen_shri_tl(x, x, 4);
-
- tcg_gen_and_tl(x, x, c);
- tcg_gen_sub_tl(d, d, x);
- tcg_temp_free(x);
+ tcg_gen_sub_tl(d, d, c);
tcg_temp_free(c);
}
}
@@ -541,11 +499,9 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
static inline void cris_clear_x_flag(DisasContext *dc)
{
- if (dc->flagx_known && dc->flags_x) {
+ if (dc->flags_x) {
dc->flags_uptodate = 0;
}
-
- dc->flagx_known = 1;
dc->flags_x = 0;
}
@@ -630,12 +586,10 @@ static void cris_evaluate_flags(DisasContext *dc)
break;
}
- if (dc->flagx_known) {
- if (dc->flags_x) {
- tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], X_FLAG);
- } else if (dc->cc_op == CC_OP_FLAGS) {
- tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~X_FLAG);
- }
+ if (dc->flags_x) {
+ tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], X_FLAG);
+ } else if (dc->cc_op == CC_OP_FLAGS) {
+ tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~X_FLAG);
}
dc->flags_uptodate = 1;
}
@@ -670,16 +624,11 @@ static void cris_update_cc_op(DisasContext *dc, int op, int size)
static inline void cris_update_cc_x(DisasContext *dc)
{
/* Save the x flag state at the time of the cc snapshot. */
- if (dc->flagx_known) {
- if (dc->cc_x_uptodate == (2 | dc->flags_x)) {
- return;
- }
- tcg_gen_movi_tl(cc_x, dc->flags_x);
- dc->cc_x_uptodate = 2 | dc->flags_x;
- } else {
- tcg_gen_andi_tl(cc_x, cpu_PR[PR_CCS], X_FLAG);
- dc->cc_x_uptodate = 1;
+ if (dc->cc_x_uptodate == (2 | dc->flags_x)) {
+ return;
}
+ tcg_gen_movi_tl(cc_x, dc->flags_x);
+ dc->cc_x_uptodate = 2 | dc->flags_x;
}
/* Update cc prior to executing ALU op. Needs source operands untouched. */
@@ -1131,7 +1080,7 @@ static void gen_store (DisasContext *dc, TCGv addr, TCGv val,
/* Conditional writes. We only support the kind were X and P are known
at translation time. */
- if (dc->flagx_known && dc->flags_x && (dc->tb_flags & P_FLAG)) {
+ if (dc->flags_x && (dc->tb_flags & P_FLAG)) {
dc->postinc = 0;
cris_evaluate_flags(dc);
tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], C_FLAG);
@@ -1140,7 +1089,7 @@ static void gen_store (DisasContext *dc, TCGv addr, TCGv val,
tcg_gen_qemu_st_tl(val, addr, mem_index, MO_TE + ctz32(size));
- if (dc->flagx_known && dc->flags_x) {
+ if (dc->flags_x) {
cris_evaluate_flags(dc);
tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~C_FLAG);
}
@@ -1727,8 +1676,8 @@ static int dec_addc_r(CPUCRISState *env, DisasContext *dc)
LOG_DIS("addc $r%u, $r%u\n",
dc->op1, dc->op2);
cris_evaluate_flags(dc);
+
/* Set for this insn. */
- dc->flagx_known = 1;
dc->flags_x = X_FLAG;
cris_cc_mask(dc, CC_MASK_NZVC);
@@ -2015,7 +1964,6 @@ static int dec_setclrf(CPUCRISState *env, DisasContext *dc)
}
if (flags & X_FLAG) {
- dc->flagx_known = 1;
if (set) {
dc->flags_x = X_FLAG;
} else {
@@ -2479,7 +2427,6 @@ static int dec_addc_mr(CPUCRISState *env, DisasContext *dc)
cris_evaluate_flags(dc);
/* Set for this insn. */
- dc->flagx_known = 1;
dc->flags_x = X_FLAG;
cris_alu_m_alloc_temps(t);
@@ -3139,7 +3086,6 @@ static void cris_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
dc->ppc = pc_start;
dc->pc = pc_start;
dc->flags_uptodate = 1;
- dc->flagx_known = 1;
dc->flags_x = tb_flags & X_FLAG;
dc->cc_x_uptodate = 0;
dc->cc_mask = 0;
@@ -3215,7 +3161,6 @@ static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
}
/* Fold unhandled changes to X_FLAG into cpustate_changed. */
- dc->cpustate_changed |= !dc->flagx_known;
dc->cpustate_changed |= dc->flags_x != (dc->base.tb->flags & X_FLAG);
/*
diff --git a/target/cris/translate_v10.c.inc b/target/cris/translate_v10.c.inc
index 4ab43dc404..f500e93447 100644
--- a/target/cris/translate_v10.c.inc
+++ b/target/cris/translate_v10.c.inc
@@ -106,9 +106,8 @@ static void gen_store_v10(DisasContext *dc, TCGv addr, TCGv val,
cris_store_direct_jmp(dc);
}
- /* Conditional writes. We only support the kind were X is known
- at translation time. */
- if (dc->flagx_known && dc->flags_x) {
+ /* Conditional writes. */
+ if (dc->flags_x) {
gen_store_v10_conditional(dc, addr, val, size, mem_index);
return;
}
@@ -376,7 +375,6 @@ static unsigned int dec10_setclrf(DisasContext *dc)
if (flags & X_FLAG) {
- dc->flagx_known = 1;
if (set)
dc->flags_x = X_FLAG;
else
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v3 15/15] target/cris: Do not exit tb for X_FLAG changes
2021-06-22 15:48 [PATCH v3 00/15] target/cris: Convert to TranslatorOps Richard Henderson
` (13 preceding siblings ...)
2021-06-22 15:48 ` [PATCH v3 14/15] target/cris: Remove dc->flagx_known Richard Henderson
@ 2021-06-22 15:48 ` Richard Henderson
14 siblings, 0 replies; 20+ messages in thread
From: Richard Henderson @ 2021-06-22 15:48 UTC (permalink / raw)
To: qemu-devel; +Cc: edgar.iglesias
We always know the exact value of X, that's all that matters.
This avoids splitting the TB e.g. between "ax" and "addq".
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/cris/translate.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 45548ffb5e..78cc70a320 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -3160,9 +3160,6 @@ static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
cris_clear_x_flag(dc);
}
- /* Fold unhandled changes to X_FLAG into cpustate_changed. */
- dc->cpustate_changed |= dc->flags_x != (dc->base.tb->flags & X_FLAG);
-
/*
* All branches are delayed branches, handled immediately below.
* We don't expect to see odd combinations of exit conditions.
--
2.25.1
^ permalink raw reply related [flat|nested] 20+ messages in thread