Note: I looked into dropping dc->do_debug. However, I don't see
an easy way to do it given that TOO_MANY is also valid
when we just translate more than max_insns. Thus, the check
for do_debug in "case DISAS_PC_CC_UPDATED" would still need
additional state to know whether or not we came from
breakpoint_check.
Acked-by: Cornelia Huck
Reviewed-by: David Hildenbrand
Tested-by: David Hildenbrand
Cc: David Hildenbrand
Cc: Cornelia Huck
Cc: Alexander Graf
Cc: qemu-s3...@nongnu.org
Signed-off-by: Emilio G. Cota
---
target/s390x/translate.c | 162 +++
1 file changed, 80 insertions(+), 82 deletions(-)
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index a65e9cd..2cbd870 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -64,6 +64,7 @@ struct DisasContext {
uint64_t pc_tmp;
uint32_t ilen;
enum cc_op cc_op;
+bool do_debug;
};
/* Information carried about a condition to be evaluated. */
@@ -6158,98 +6159,87 @@ static DisasJumpType translate_one(CPUS390XState *env,
DisasContext *s)
return ret;
}
-void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
+static void s390x_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
{
-CPUS390XState *env = cs->env_ptr;
-DisasContext dc;
-uint64_t next_page_start;
-int num_insns, max_insns;
-DisasJumpType status;
-bool do_debug;
+DisasContext *dc = container_of(dcbase, DisasContext, base);
-dc.base.pc_first = tb->pc;
/* 31-bit mode */
-if (!(tb->flags & FLAG_MASK_64)) {
-dc.base.pc_first &= 0x7fff;
+if (!(dc->base.tb->flags & FLAG_MASK_64)) {
+dc->base.pc_first &= 0x7fff;
+dc->base.pc_next = dc->base.pc_first;
}
-dc.base.pc_next = dc.base.pc_first;
-dc.base.tb = tb;
-dc.base.singlestep_enabled = cs->singlestep_enabled;
-dc.cc_op = CC_OP_DYNAMIC;
-dc.ex_value = dc.base.tb->cs_base;
-do_debug = cs->singlestep_enabled;
+dc->cc_op = CC_OP_DYNAMIC;
+dc->ex_value = dc->base.tb->cs_base;
+dc->do_debug = dc->base.singlestep_enabled;
+}
-next_page_start = (dc.base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+static void s390x_tr_tb_start(DisasContextBase *db, CPUState *cs)
+{
+}
-num_insns = 0;
-max_insns = tb_cflags(tb) & CF_COUNT_MASK;
-if (max_insns == 0) {
-max_insns = CF_COUNT_MASK;
-}
-if (max_insns > TCG_MAX_INSNS) {
-max_insns = TCG_MAX_INSNS;
-}
+static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
+{
+DisasContext *dc = container_of(dcbase, DisasContext, base);
-gen_tb_start(tb);
+tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
+}
-do {
-tcg_gen_insn_start(dc.base.pc_next, dc.cc_op);
-num_insns++;
+static bool s390x_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
+ const CPUBreakpoint *bp)
+{
+DisasContext *dc = container_of(dcbase, DisasContext, base);
-if (unlikely(cpu_breakpoint_test(cs, dc.base.pc_next, BP_ANY))) {
-status = DISAS_PC_STALE;
-do_debug = true;
-/* 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.base.pc_next += 2;
-break;
-}
+dc->base.is_jmp = DISAS_PC_STALE;
+dc->do_debug = true;
+/* 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 does the right thing. */
+dc->base.pc_next += 2;
+return true;
+}
-if (num_insns == max_insns && (tb_cflags(tb) & CF_LAST_IO)) {
-gen_io_start();
-}
+static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
+{
+CPUS390XState *env = cs->env_ptr;
+DisasContext *dc = container_of(dcbase, DisasContext, base);
-status = translate_one(env, &dc);
-
-/* If we reach a page boundary, are single stepping,
- or exhaust instruction count, stop generation. */
-if (status == DISAS_NEXT
-&& (dc.base.pc_next >= next_page_start
-|| tcg_op_buf_full()
-|| num_insns >= max_insns
-|| singlestep
-|| dc.base.singlestep_enabled
-|| dc.ex_value)) {
-status = DISAS_TOO_MANY;
-}
-} while (status == DISAS_NEXT);
+dc->base.is_jmp = translate_one(env, dc);
+if (dc->base.is_jmp == DISAS_NEXT) {
+uint64_t next_page;
-if (tb_cflags(tb) & CF_LAST_IO) {
-gen_io_end();
+next_page = (dc->base.pc_first & TARGE