All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework
@ 2017-06-28 12:16 Lluís Vilanova
  2017-06-28 12:20 ` [Qemu-devel] [PATCH v11 01/29] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
                   ` (28 more replies)
  0 siblings, 29 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 12:16 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini

This series proposes a generic (target-agnostic) instruction translation
framework.

It basically provides a generic main loop for instruction disassembly, which
calls target-specific functions when necessary. This generalization makes
inserting new code in the main loop easier, and helps in keeping all targets in
synch as to the contents of it.

This series also paves the way towards adding events to trace guest code
execution (BBLs and instructions).

I've ported i386/x86-64 and arm/aarch64 as an example to see how it fits in the
current organization, but will port the rest when this series gets merged.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---

Changes in v11
==============

* Convert gen_intermediate_code_a64 [Emilio G. Cota].
* Replace "cpu_env" argument in icount functions with "tcg_ctx.cpu_env"
  [Emilio G. Cota].
* Drop QTAILQ_FOREACH_CONTINUE and cpu_breakpoint_get in favour of an explicit
  breakpoint traversal [Richard Henderson].
* Rename translate-block.[ch] into translator.[ch] [Emilio G. Cota].
* Revert DJ_* names into DISAS_*, and provide generic DISAS_TARGET_* enum values
  instead of defining them as integers on each target.
* Do not use DisasContextBase directly in target code (helps the compiler's
  alias analysis) [Richard Henderson].
* Make all generic translator hooks mandatory [Richard Henderson].
* Rename TranslatorOps::disas_insn as TranslatorOps::translate_insn
  [Richard Henderson].
* Generalize TranslatorOps::disas_flags into TranslatorOps::disas_log to support
  future targets [Richard Henderson].
* Split arm and aarch64 changes in different patches [Emilio G. Cota].
* Make translator op structs constant [Richard Henderson].
* Write a single entry point for both arm and aarch64 translation
  [Richard Henderson].
* Change format of commit titles [Emilio G. Cota].
* Remove cross-page check from generic code (it's already embedded in more
  complex, and mandatory, checks in most targets).


Changes in v10
==============

* Rebase on 931892e8a6.
* Fix build errors for hppa, nios2 and openrisc.


Changes in v9
=============

* Further increase inter-mail sleep time during sending.


Changes in v8
=============

* Increase inter-mail sleep time during sending (list keeps refusing some emails
  due to an excessive send rate).


Changes in v7
=============

* Change BreakpointHitType (BH_*) for BreakpointCheckType (BC_*).
* Move target-specific translation functions to a struct (TranslatorOps).
* Split target-specific changes into multiple patches.
* Rebase on edf8bc9842.


Changes in v6
=============

* Rebase on upstream master (64175afc69).
* Reorder fields in DisasContextBase to minimize padding [Richard Henderson].


Changes in v5
=============

* Remove stray uses of "restrict" keyword.


Changes in v4
=============

* Document new macro QTAILQ_FOREACH_CONTINUE [Peter Maydell].
* Fix coding style errors reported by checkpatch.
* Remove use of "restrict" in added functions; it makes older gcc versions barf
  about compilation errors.


Changes in v3
=============

* Rebase on 0737f32daf.


Changes in v2
=============

* Port ARM and AARCH64 targets.
* Fold single-stepping checks into "max_insns" [Richard Henderson].
* Move instruction start marks to target code [Richard Henderson].
* Add target hook for TB start.
* Check for TCG temporary leaks.
* Move instruction disassembly into a target hook.
* Make breakpoint_hit() return an enum to accomodate target's needs (ARM).


Lluís Vilanova (29):
      Pass generic CPUState to gen_intermediate_code()
      cpu-exec: Avoid global variables in icount-related functions
      target: [tcg] Use a generic enum for DISAS_ values
      target: [tcg] Add generic translation framework
      target/i386: [tcg] Port to DisasContextBase
      target/i386: [tcg] Refactor init_disas_context
      target/i386: [tcg] Refactor init_globals
      target/i386: [tcg] Refactor insn_start
      target/i386: [tcg] Refactor breakpoint_check
      target/i386: [tcg] Refactor translate_insn
      target/i386: [tcg] Refactor tb_stop
      target/i386: [tcg] Refactor disas_log
      target/i386: [tcg] Port to generic translation framework
      target/arm: [tcg] Port to DisasContextBase
      target/arm: [tcg] Port to init_disas_context
      target/arm: [tcg,a64] Port to init_disas_context
      target/arm: [tcg] Port to init_globals
      target/arm: [tcg] Port to tb_start
      target/arm: [tcg] Port to insn_start
      target/arm: [tcg,a64] Port to insn_start
      target/arm: [tcg] Port to breakpoint_check
      target/arm: [tcg,a64] Port to breakpoint_check
      target/arm: [tcg] Port to translate_insn
      target/arm: [tcg,a64] Port to translate_insn
      target/arm: [tcg] Port to tb_stop
      target/arm: [tcg,a64] Port to tb_stop
      target/arm: [tcg] Port to disas_log
      target/arm: [tcg,a64] Port to disas_log
      target/arm: [tcg] Port to generic translation framework


 accel/tcg/Makefile.objs       |    1 
 accel/tcg/translate-all.c     |    2 
 accel/tcg/translator.c        |  153 +++++++++++++++
 include/exec/exec-all.h       |    8 -
 include/exec/gen-icount.h     |   10 -
 include/exec/translator.h     |  142 ++++++++++++++
 target/alpha/translate.c      |   11 -
 target/arm/translate-a64.c    |  280 +++++++++++++--------------
 target/arm/translate.c        |  419 +++++++++++++++++++++--------------------
 target/arm/translate.h        |   41 ++--
 target/cris/translate.c       |   24 +-
 target/hppa/translate.c       |    5 
 target/i386/translate.c       |  306 +++++++++++++++---------------
 target/lm32/translate.c       |   28 ++-
 target/m68k/translate.c       |   22 +-
 target/microblaze/translate.c |   28 ++-
 target/mips/translate.c       |   15 +
 target/moxie/translate.c      |   14 +
 target/nios2/translate.c      |   11 +
 target/openrisc/translate.c   |   26 ++-
 target/ppc/translate.c        |   15 +
 target/s390x/translate.c      |   16 +-
 target/sh4/translate.c        |   15 +
 target/sparc/translate.c      |   11 -
 target/tilegx/translate.c     |    7 -
 target/tricore/translate.c    |    9 -
 target/unicore32/translate.c  |   24 +-
 target/xtensa/translate.c     |   17 +-
 28 files changed, 996 insertions(+), 664 deletions(-)
 create mode 100644 accel/tcg/translator.c
 create mode 100644 include/exec/translator.h


To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Emilio G. Cota <cota@braap.org>

^ permalink raw reply	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 01/29] Pass generic CPUState to gen_intermediate_code()
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
@ 2017-06-28 12:20 ` Lluís Vilanova
  2017-06-29 22:52   ` Emilio G. Cota
  2017-07-01 22:44   ` Richard Henderson
  2017-06-28 12:24 ` [Qemu-devel] [PATCH v11 02/29] cpu-exec: Avoid global variables in icount-related functions Lluís Vilanova
                   ` (27 subsequent siblings)
  28 siblings, 2 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 12:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell,
	Edgar E. Iglesias, Eduardo Habkost, Michael Walle,
	Laurent Vivier, Aurelien Jarno, Yongbok Kim, Anthony Green,
	Chris Wulff, Marek Vasut, Stafford Horne, David Gibson,
	Alexander Graf, Mark Cave-Ayland, Artyom Tarasenko,
	Bastian Koppelmann, Guan Xuetao, Max Filippov, open list:ARM,
	open list:PowerPC

Needed to implement a target-agnostic gen_intermediate_code() in the
future.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 accel/tcg/translate-all.c     |    2 +-
 include/exec/exec-all.h       |    2 +-
 target/alpha/translate.c      |   11 +++++------
 target/arm/translate-a64.c    |    6 +++---
 target/arm/translate.c        |   18 +++++++++---------
 target/arm/translate.h        |    4 ++--
 target/cris/translate.c       |   17 ++++++++---------
 target/hppa/translate.c       |    5 ++---
 target/i386/translate.c       |   13 ++++++-------
 target/lm32/translate.c       |   22 +++++++++++-----------
 target/m68k/translate.c       |   15 +++++++--------
 target/microblaze/translate.c |   22 +++++++++++-----------
 target/mips/translate.c       |   15 +++++++--------
 target/moxie/translate.c      |   14 +++++++-------
 target/nios2/translate.c      |    5 ++---
 target/openrisc/translate.c   |   20 ++++++++++----------
 target/ppc/translate.c        |   15 +++++++--------
 target/s390x/translate.c      |   13 ++++++-------
 target/sh4/translate.c        |   15 +++++++--------
 target/sparc/translate.c      |   11 +++++------
 target/tilegx/translate.c     |    7 +++----
 target/tricore/translate.c    |    9 ++++-----
 target/unicore32/translate.c  |   17 ++++++++---------
 target/xtensa/translate.c     |   13 ++++++-------
 24 files changed, 138 insertions(+), 153 deletions(-)

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index f6ad46b613..2dc93f420a 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1299,7 +1299,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
     tcg_func_start(&tcg_ctx);
 
     tcg_ctx.cpu = ENV_GET_CPU(env);
-    gen_intermediate_code(env, tb);
+    gen_intermediate_code(cpu, tb);
     tcg_ctx.cpu = NULL;
 
     trace_translate_block(tb, tb->pc, tb->tc_ptr);
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 724ec73dce..a7cd106587 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -43,7 +43,7 @@ typedef ram_addr_t tb_page_addr_t;
 
 #include "qemu/log.h"
 
-void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb);
+void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
 void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb,
                           target_ulong *data);
 
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 232af9e177..c1227c51b0 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -2911,10 +2911,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
     return ret;
 }
 
-void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    AlphaCPU *cpu = alpha_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUAlphaState *env = cpu->env_ptr;
     DisasContext ctx, *ctxp = &ctx;
     target_ulong pc_start;
     target_ulong pc_mask;
@@ -2929,7 +2928,7 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
     ctx.pc = pc_start;
     ctx.mem_idx = cpu_mmu_index(env, false);
     ctx.implver = env->implver;
-    ctx.singlestep_enabled = cs->singlestep_enabled;
+    ctx.singlestep_enabled = cpu->singlestep_enabled;
 
 #ifdef CONFIG_USER_ONLY
     ctx.ir = cpu_std_ir;
@@ -2972,7 +2971,7 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
         tcg_gen_insn_start(ctx.pc);
         num_insns++;
 
-        if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, ctx.pc, BP_ANY))) {
             ret = gen_excp(&ctx, EXCP_DEBUG, 0);
             /* The address covered by the breakpoint must be included in
                [tb->pc, tb->pc + tb->size) in order to for it to be
@@ -3047,7 +3046,7 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
         && qemu_log_in_addr_range(pc_start)) {
         qemu_log_lock();
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(cs, pc_start, ctx.pc - pc_start, 1);
+        log_target_disas(cpu, pc_start, ctx.pc - pc_start, 1);
         qemu_log("\n");
         qemu_log_unlock();
     }
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index e55547d95d..f9bd1a9679 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11190,10 +11190,10 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
     free_tmp_a64(s);
 }
 
-void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
+void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
 {
-    CPUState *cs = CPU(cpu);
-    CPUARMState *env = &cpu->env;
+    CPUARMState *env = cs->env_ptr;
+    ARMCPU *cpu = arm_env_get_cpu(env);
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_start;
     target_ulong next_page_start;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 0862f9e4aa..032a263604 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11787,10 +11787,10 @@ static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
-    ARMCPU *cpu = arm_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUARMState *env = cpu->env_ptr;
+    ARMCPU *arm_cpu = arm_env_get_cpu(env);
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_start;
     target_ulong next_page_start;
@@ -11814,7 +11814,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
-    dc->singlestep_enabled = cs->singlestep_enabled;
+    dc->singlestep_enabled = cpu->singlestep_enabled;
     dc->condjmp = 0;
 
     dc->aarch64 = 0;
@@ -11840,7 +11840,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
     dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
     dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
     dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(tb->flags);
-    dc->cp_regs = cpu->cp_regs;
+    dc->cp_regs = arm_cpu->cp_regs;
     dc->features = env->features;
 
     /* Single step state. The code-generation logic here is:
@@ -11941,9 +11941,9 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
         }
 #endif
 
-        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
             CPUBreakpoint *bp;
-            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
+            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
                 if (bp->pc == dc->pc) {
                     if (bp->flags & BP_CPU) {
                         gen_set_condexec(dc);
@@ -12042,7 +12042,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
         if (dc->condjmp) {
             /* FIXME:  This can theoretically happen with self-modifying
                code.  */
-            cpu_abort(cs, "IO on conditional branch instruction");
+            cpu_abort(cpu, "IO on conditional branch instruction");
         }
         gen_io_end();
     }
@@ -12156,7 +12156,7 @@ done_generating:
         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,
+        log_target_disas(cpu, pc_start, dc->pc - pc_start,
                          dc->thumb | (dc->sctlr_b << 1));
         qemu_log("\n");
         qemu_log_unlock();
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 15d383d9af..e5da614db5 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -146,7 +146,7 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);
-void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb);
+void gen_intermediate_code_a64(CPUState *cpu, TranslationBlock *tb);
 void gen_a64_set_pc_im(uint64_t val);
 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
                             fprintf_function cpu_fprintf, int flags);
@@ -155,7 +155,7 @@ static inline void a64_translate_init(void)
 {
 }
 
-static inline void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
+static inline void gen_intermediate_code_a64(CPUState *cpu, TranslationBlock *tb)
 {
 }
 
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 0ee05ca02d..35931e7061 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -3080,10 +3080,9 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
  */
 
 /* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUCRISState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    CRISCPU *cpu = cris_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUCRISState *env = cpu->env_ptr;
     uint32_t pc_start;
     unsigned int insn_len;
     struct DisasContext ctx;
@@ -3105,13 +3104,13 @@ void gen_intermediate_code(CPUCRISState *env, struct TranslationBlock *tb)
      * delayslot, like in real hw.
      */
     pc_start = tb->pc & ~1;
-    dc->cpu = cpu;
+    dc->cpu = cris_env_get_cpu(env);
     dc->tb = tb;
 
     dc->is_jmp = DISAS_NEXT;
     dc->ppc = pc_start;
     dc->pc = pc_start;
-    dc->singlestep_enabled = cs->singlestep_enabled;
+    dc->singlestep_enabled = cpu->singlestep_enabled;
     dc->flags_uptodate = 1;
     dc->flagx_known = 1;
     dc->flags_x = tb->flags & X_FLAG;
@@ -3151,7 +3150,7 @@ void gen_intermediate_code(CPUCRISState *env, struct TranslationBlock *tb)
                            ? dc->ppc | 1 : dc->pc);
         num_insns++;
 
-        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, dc->pc, BP_ANY))) {
             cris_evaluate_flags(dc);
             tcg_gen_movi_tl(env_pc, dc->pc);
             t_gen_raise_exception(EXCP_DEBUG);
@@ -3225,7 +3224,7 @@ void gen_intermediate_code(CPUCRISState *env, struct TranslationBlock *tb)
 
         /* If we are rexecuting a branch due to exceptions on
            delay slots don't break.  */
-        if (!(tb->pc & 1) && cs->singlestep_enabled) {
+        if (!(tb->pc & 1) && cpu->singlestep_enabled) {
             break;
         }
     } while (!dc->is_jmp && !dc->cpustate_changed
@@ -3258,7 +3257,7 @@ void gen_intermediate_code(CPUCRISState *env, struct TranslationBlock *tb)
 
     cris_evaluate_flags(dc);
 
-    if (unlikely(cs->singlestep_enabled)) {
+    if (unlikely(cpu->singlestep_enabled)) {
         if (dc->is_jmp == DISAS_NEXT) {
             tcg_gen_movi_tl(env_pc, npc);
         }
@@ -3293,7 +3292,7 @@ void gen_intermediate_code(CPUCRISState *env, struct TranslationBlock *tb)
         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,
+        log_target_disas(cpu, pc_start, dc->pc - pc_start,
                          env->pregs[PR_VR]);
         qemu_log("\nisize=%d osize=%d\n",
                  dc->pc - pc_start, tcg_op_buf_count());
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index e10abc5e04..900870cd5a 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -3740,10 +3740,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
     return gen_illegal(ctx);
 }
 
-void gen_intermediate_code(CPUHPPAState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
 {
-    HPPACPU *cpu = hppa_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUHPPAState *env = cs->env_ptr;
     DisasContext ctx;
     ExitStatus ret;
     int num_insns, max_insns, i;
diff --git a/target/i386/translate.c b/target/i386/translate.c
index ed3b896db4..b94303ff10 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8378,10 +8378,9 @@ void tcg_x86_init(void)
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
-    X86CPU *cpu = x86_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUX86State *env = cpu->env_ptr;
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_ptr;
     uint32_t flags;
@@ -8404,7 +8403,7 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
     dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
     dc->iopl = (flags >> IOPL_SHIFT) & 3;
     dc->tf = (flags >> TF_SHIFT) & 1;
-    dc->singlestep_enabled = cs->singlestep_enabled;
+    dc->singlestep_enabled = cpu->singlestep_enabled;
     dc->cc_op = CC_OP_DYNAMIC;
     dc->cc_op_dirty = false;
     dc->cs_base = cs_base;
@@ -8426,7 +8425,7 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
     dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
 #endif
     dc->flags = flags;
-    dc->jmp_opt = !(dc->tf || cs->singlestep_enabled ||
+    dc->jmp_opt = !(dc->tf || cpu->singlestep_enabled ||
                     (flags & HF_INHIBIT_IRQ_MASK));
     /* Do not optimize repz jumps at all in icount mode, because
        rep movsS instructions are execured with different paths
@@ -8475,7 +8474,7 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
         num_insns++;
 
         /* If RF is set, suppress an internally generated breakpoint.  */
-        if (unlikely(cpu_breakpoint_test(cs, pc_ptr,
+        if (unlikely(cpu_breakpoint_test(cpu, pc_ptr,
                                          tb->flags & HF_RF_MASK
                                          ? BP_GDB : BP_ANY))) {
             gen_debug(dc, pc_ptr - dc->cs_base);
@@ -8551,7 +8550,7 @@ done_generating:
         else
 #endif
             disas_flags = !dc->code32;
-        log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags);
+        log_target_disas(cpu, pc_start, pc_ptr - pc_start, disas_flags);
         qemu_log("\n");
         qemu_log_unlock();
     }
diff --git a/target/lm32/translate.c b/target/lm32/translate.c
index 692882f447..0ac34fc620 100644
--- a/target/lm32/translate.c
+++ b/target/lm32/translate.c
@@ -1044,10 +1044,10 @@ static inline void decode(DisasContext *dc, uint32_t ir)
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    LM32CPU *cpu = lm32_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPULM32State *env = cpu->env_ptr;
+    LM32CPU *lm32_cpu = lm32_env_get_cpu(env);
     struct DisasContext ctx, *dc = &ctx;
     uint32_t pc_start;
     uint32_t next_page_start;
@@ -1055,14 +1055,14 @@ void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
     int max_insns;
 
     pc_start = tb->pc;
-    dc->features = cpu->features;
-    dc->num_breakpoints = cpu->num_breakpoints;
-    dc->num_watchpoints = cpu->num_watchpoints;
+    dc->features = lm32_cpu->features;
+    dc->num_breakpoints = lm32_cpu->num_breakpoints;
+    dc->num_watchpoints = lm32_cpu->num_watchpoints;
     dc->tb = tb;
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
-    dc->singlestep_enabled = cs->singlestep_enabled;
+    dc->singlestep_enabled = cpu->singlestep_enabled;
 
     if (pc_start & 3) {
         qemu_log_mask(LOG_GUEST_ERROR,
@@ -1085,7 +1085,7 @@ void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
         tcg_gen_insn_start(dc->pc);
         num_insns++;
 
-        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, dc->pc, BP_ANY))) {
             tcg_gen_movi_tl(cpu_pc, dc->pc);
             t_gen_raise_exception(dc, EXCP_DEBUG);
             dc->is_jmp = DISAS_UPDATE;
@@ -1108,7 +1108,7 @@ void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
         dc->pc += 4;
     } while (!dc->is_jmp
          && !tcg_op_buf_full()
-         && !cs->singlestep_enabled
+         && !cpu->singlestep_enabled
          && !singlestep
          && (dc->pc < next_page_start)
          && num_insns < max_insns);
@@ -1117,7 +1117,7 @@ void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
         gen_io_end();
     }
 
-    if (unlikely(cs->singlestep_enabled)) {
+    if (unlikely(cpu->singlestep_enabled)) {
         if (dc->is_jmp == DISAS_NEXT) {
             tcg_gen_movi_tl(cpu_pc, dc->pc);
         }
@@ -1150,7 +1150,7 @@ void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
         && qemu_log_in_addr_range(pc_start)) {
         qemu_log_lock();
         qemu_log("\n");
-        log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
+        log_target_disas(cpu, pc_start, dc->pc - pc_start, 0);
         qemu_log("\nisize=%d osize=%d\n",
                  dc->pc - pc_start, tcg_op_buf_count());
         qemu_log_unlock();
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 7aa0fdc238..01ef3923c9 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5369,10 +5369,9 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
-    M68kCPU *cpu = m68k_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUM68KState *env = cpu->env_ptr;
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_start;
     int pc_offset;
@@ -5389,7 +5388,7 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
     dc->pc = pc_start;
     dc->cc_op = CC_OP_DYNAMIC;
     dc->cc_op_synced = 1;
-    dc->singlestep_enabled = cs->singlestep_enabled;
+    dc->singlestep_enabled = cpu->singlestep_enabled;
     dc->user = (env->sr & SR_S) == 0;
     dc->done_mac = 0;
     dc->writeback_mask = 0;
@@ -5409,7 +5408,7 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
         tcg_gen_insn_start(dc->pc, dc->cc_op);
         num_insns++;
 
-        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, dc->pc, BP_ANY))) {
             gen_exception(dc, dc->pc, EXCP_DEBUG);
             dc->is_jmp = DISAS_JUMP;
             /* The address covered by the breakpoint must be included in
@@ -5427,14 +5426,14 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
         dc->insn_pc = dc->pc;
 	disas_m68k_insn(env, dc);
     } while (!dc->is_jmp && !tcg_op_buf_full() &&
-             !cs->singlestep_enabled &&
+             !cpu->singlestep_enabled &&
              !singlestep &&
              (pc_offset) < (TARGET_PAGE_SIZE - 32) &&
              num_insns < max_insns);
 
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
-    if (unlikely(cs->singlestep_enabled)) {
+    if (unlikely(cpu->singlestep_enabled)) {
         /* Make sure the pc is updated, and raise a debug exception.  */
         if (!dc->is_jmp) {
             update_cc_op(dc);
@@ -5467,7 +5466,7 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
         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, 0);
+        log_target_disas(cpu, pc_start, dc->pc - pc_start, 0);
         qemu_log("\n");
         qemu_log_unlock();
     }
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index 0bb609513c..d5f499658d 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -1594,10 +1594,10 @@ static inline void decode(DisasContext *dc, uint32_t ir)
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    MicroBlazeCPU *cpu = mb_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUMBState *env = cpu->env_ptr;
+    MicroBlazeCPU *mb_cpu = mb_env_get_cpu(env);
     uint32_t pc_start;
     struct DisasContext ctx;
     struct DisasContext *dc = &ctx;
@@ -1607,7 +1607,7 @@ void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
     int max_insns;
 
     pc_start = tb->pc;
-    dc->cpu = cpu;
+    dc->cpu = mb_cpu;
     dc->tb = tb;
     org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
 
@@ -1618,13 +1618,13 @@ void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
         dc->jmp = JMP_INDIRECT;
     }
     dc->pc = pc_start;
-    dc->singlestep_enabled = cs->singlestep_enabled;
+    dc->singlestep_enabled = cpu->singlestep_enabled;
     dc->cpustate_changed = 0;
     dc->abort_at_next_insn = 0;
     dc->nr_nops = 0;
 
     if (pc_start & 3) {
-        cpu_abort(cs, "Microblaze: unaligned PC=%x\n", pc_start);
+        cpu_abort(cpu, "Microblaze: unaligned PC=%x\n", pc_start);
     }
 
     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
@@ -1650,7 +1650,7 @@ void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
         }
 #endif
 
-        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, dc->pc, BP_ANY))) {
             t_gen_raise_exception(dc, EXCP_DEBUG);
             dc->is_jmp = DISAS_UPDATE;
             /* The address covered by the breakpoint must be included in
@@ -1707,7 +1707,7 @@ void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
                 break;
             }
         }
-        if (cs->singlestep_enabled) {
+        if (cpu->singlestep_enabled) {
             break;
         }
     } while (!dc->is_jmp && !dc->cpustate_changed
@@ -1728,7 +1728,7 @@ void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
 
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
-    /* Force an update if the per-tb cpu state has changed.  */
+    /* Force an update if the per-tb mb_cpu state has changed.  */
     if (dc->is_jmp == DISAS_NEXT
         && (dc->cpustate_changed || org_flags != dc->tb_flags)) {
         dc->is_jmp = DISAS_UPDATE;
@@ -1736,7 +1736,7 @@ void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
     }
     t_sync_flags(dc);
 
-    if (unlikely(cs->singlestep_enabled)) {
+    if (unlikely(cpu->singlestep_enabled)) {
         TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
 
         if (dc->is_jmp != DISAS_JUMP) {
@@ -1773,7 +1773,7 @@ void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
         qemu_log_lock();
         qemu_log("--------------\n");
 #if DISAS_GNU
-        log_target_disas(cs, pc_start, dc->pc - pc_start, 0);
+        log_target_disas(cpu, pc_start, dc->pc - pc_start, 0);
 #endif
         qemu_log("\nisize=%d osize=%d\n",
                  dc->pc - pc_start, tcg_op_buf_count());
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 559f8fed89..1f9e02f426 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -19878,10 +19878,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
     }
 }
 
-void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    MIPSCPU *cpu = mips_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUMIPSState *env = cpu->env_ptr;
     DisasContext ctx;
     target_ulong pc_start;
     target_ulong next_page_start;
@@ -19894,7 +19893,7 @@ void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     ctx.pc = pc_start;
     ctx.saved_pc = -1;
-    ctx.singlestep_enabled = cs->singlestep_enabled;
+    ctx.singlestep_enabled = cpu->singlestep_enabled;
     ctx.insn_flags = env->insn_flags;
     ctx.CP0_Config1 = env->CP0_Config1;
     ctx.tb = tb;
@@ -19941,7 +19940,7 @@ void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
         tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
         num_insns++;
 
-        if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, ctx.pc, BP_ANY))) {
             save_cpu_state(&ctx, 1);
             ctx.bstate = BS_BRANCH;
             gen_helper_raise_exception_debug(cpu_env);
@@ -19996,7 +19995,7 @@ void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
            This is what GDB expects and is consistent with what the
            hardware does (e.g. if a delay slot instruction faults, the
            reported PC is the PC of the branch).  */
-        if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
+        if (cpu->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
             break;
         }
 
@@ -20017,7 +20016,7 @@ void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
     if (tb->cflags & CF_LAST_IO) {
         gen_io_end();
     }
-    if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
+    if (cpu->singlestep_enabled && ctx.bstate != BS_BRANCH) {
         save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
         gen_helper_raise_exception_debug(cpu_env);
     } else {
@@ -20049,7 +20048,7 @@ done_generating:
         && qemu_log_in_addr_range(pc_start)) {
         qemu_log_lock();
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
+        log_target_disas(cpu, pc_start, ctx.pc - pc_start, 0);
         qemu_log("\n");
         qemu_log_unlock();
     }
diff --git a/target/moxie/translate.c b/target/moxie/translate.c
index 0660b44c08..176063a1de 100644
--- a/target/moxie/translate.c
+++ b/target/moxie/translate.c
@@ -822,10 +822,10 @@ static int decode_opc(MoxieCPU *cpu, DisasContext *ctx)
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    MoxieCPU *cpu = moxie_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUMoxieState *env = cpu->env_ptr;
+    MoxieCPU *moxie_cpu = moxie_env_get_cpu(env);
     DisasContext ctx;
     target_ulong pc_start;
     int num_insns, max_insns;
@@ -851,7 +851,7 @@ void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb)
         tcg_gen_insn_start(ctx.pc);
         num_insns++;
 
-        if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, ctx.pc, BP_ANY))) {
             tcg_gen_movi_i32(cpu_pc, ctx.pc);
             gen_helper_debug(cpu_env);
             ctx.bstate = BS_EXCP;
@@ -864,12 +864,12 @@ void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb)
         }
 
         ctx.opcode = cpu_lduw_code(env, ctx.pc);
-        ctx.pc += decode_opc(cpu, &ctx);
+        ctx.pc += decode_opc(moxie_cpu, &ctx);
 
         if (num_insns >= max_insns) {
             break;
         }
-        if (cs->singlestep_enabled) {
+        if (cpu->singlestep_enabled) {
             break;
         }
         if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) {
@@ -877,7 +877,7 @@ void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb)
         }
     } while (ctx.bstate == BS_NONE && !tcg_op_buf_full());
 
-    if (cs->singlestep_enabled) {
+    if (cpu->singlestep_enabled) {
         tcg_gen_movi_tl(cpu_pc, ctx.pc);
         gen_helper_debug(cpu_env);
     } else {
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 2f3c2e5dfb..8b97d6585f 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -799,10 +799,9 @@ static void gen_exception(DisasContext *dc, uint32_t excp)
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUNios2State *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
-    Nios2CPU *cpu = nios2_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUNios2State *env = cs->env_ptr;
     DisasContext dc1, *dc = &dc1;
     int num_insns;
     int max_insns;
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index e49518e893..4a28c96e53 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -1518,10 +1518,10 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
     }
 }
 
-void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUOpenRISCState *env = cpu->env_ptr;
+    OpenRISCCPU *or_cpu = openrisc_env_get_cpu(env);
     struct DisasContext ctx, *dc = &ctx;
     uint32_t pc_start;
     uint32_t next_page_start;
@@ -1533,10 +1533,10 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
-    dc->mem_idx = cpu_mmu_index(&cpu->env, false);
+    dc->mem_idx = cpu_mmu_index(&or_cpu->env, false);
     dc->tb_flags = tb->flags;
     dc->delayed_branch = (dc->tb_flags & TB_FLAGS_DFLAG) != 0;
-    dc->singlestep_enabled = cs->singlestep_enabled;
+    dc->singlestep_enabled = cpu->singlestep_enabled;
 
     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     num_insns = 0;
@@ -1571,7 +1571,7 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
 			   | (num_insns ? 2 : 0));
         num_insns++;
 
-        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, dc->pc, BP_ANY))) {
             tcg_gen_movi_tl(cpu_pc, dc->pc);
             gen_exception(dc, EXCP_DEBUG);
             dc->is_jmp = DISAS_UPDATE;
@@ -1586,7 +1586,7 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
         }
-        disas_openrisc_insn(dc, cpu);
+        disas_openrisc_insn(dc, or_cpu);
         dc->pc = dc->pc + 4;
 
         /* delay slot */
@@ -1601,7 +1601,7 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
         }
     } while (!dc->is_jmp
              && !tcg_op_buf_full()
-             && !cs->singlestep_enabled
+             && !cpu->singlestep_enabled
              && !singlestep
              && (dc->pc < next_page_start)
              && num_insns < max_insns);
@@ -1619,7 +1619,7 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
         dc->is_jmp = DISAS_UPDATE;
         tcg_gen_movi_tl(cpu_pc, dc->pc);
     }
-    if (unlikely(cs->singlestep_enabled)) {
+    if (unlikely(cpu->singlestep_enabled)) {
         gen_exception(dc, EXCP_DEBUG);
     } else {
         switch (dc->is_jmp) {
@@ -1647,7 +1647,7 @@ void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
 
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
         && qemu_log_in_addr_range(pc_start)) {
-        log_target_disas(cs, pc_start, tb->size, 0);
+        log_target_disas(cpu, pc_start, tb->size, 0);
         qemu_log("\n");
         qemu_log_unlock();
     }
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index c0cd64d927..9a934117d8 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7203,10 +7203,9 @@ void ppc_cpu_dump_statistics(CPUState *cs, FILE*f,
 }
 
 /*****************************************************************************/
-void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUPPCState *env = cpu->env_ptr;
     DisasContext ctx, *ctxp = &ctx;
     opc_handler_t **table, *handler;
     target_ulong pc_start;
@@ -7267,7 +7266,7 @@ void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
         ctx.singlestep_enabled = 0;
     if ((env->flags & POWERPC_FLAG_BE) && msr_be)
         ctx.singlestep_enabled |= CPU_BRANCH_STEP;
-    if (unlikely(cs->singlestep_enabled)) {
+    if (unlikely(cpu->singlestep_enabled)) {
         ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
     }
 #if defined (DO_SINGLE_STEP) && 0
@@ -7290,7 +7289,7 @@ void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
         tcg_gen_insn_start(ctx.nip);
         num_insns++;
 
-        if (unlikely(cpu_breakpoint_test(cs, ctx.nip, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, ctx.nip, BP_ANY))) {
             gen_debug_exception(ctxp);
             /* The address covered by the breakpoint must be included in
                [tb->pc, tb->pc + tb->size) in order to for it to be
@@ -7369,7 +7368,7 @@ void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
                      ctx.exception != POWERPC_EXCP_BRANCH)) {
             gen_exception_nip(ctxp, POWERPC_EXCP_TRACE, ctx.nip);
         } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
-                            (cs->singlestep_enabled) ||
+                            (cpu->singlestep_enabled) ||
                             singlestep ||
                             num_insns >= max_insns)) {
             /* if we reach a page boundary or are single stepping, stop
@@ -7389,7 +7388,7 @@ void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
     if (ctx.exception == POWERPC_EXCP_NONE) {
         gen_goto_tb(&ctx, 0, ctx.nip);
     } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
-        if (unlikely(cs->singlestep_enabled)) {
+        if (unlikely(cpu->singlestep_enabled)) {
             gen_debug_exception(ctxp);
         }
         /* Generate the return instruction */
@@ -7408,7 +7407,7 @@ void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
         flags |= ctx.le_mode << 16;
         qemu_log_lock();
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(cs, pc_start, ctx.nip - pc_start, flags);
+        log_target_disas(cpu, pc_start, ctx.nip - pc_start, flags);
         qemu_log("\n");
         qemu_log_unlock();
     }
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 592d6b0f38..19ea08bb9d 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -5764,10 +5764,9 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
     return ret;
 }
 
-void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    S390CPU *cpu = s390_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUS390XState *env = cpu->env_ptr;
     DisasContext dc;
     target_ulong pc_start;
     uint64_t next_page_start;
@@ -5786,7 +5785,7 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
     dc.pc = pc_start;
     dc.cc_op = CC_OP_DYNAMIC;
     dc.ex_value = tb->cs_base;
-    do_debug = dc.singlestep_enabled = cs->singlestep_enabled;
+    do_debug = dc.singlestep_enabled = cpu->singlestep_enabled;
 
     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
 
@@ -5805,7 +5804,7 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
         tcg_gen_insn_start(dc.pc, dc.cc_op);
         num_insns++;
 
-        if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, dc.pc, BP_ANY))) {
             status = EXIT_PC_STALE;
             do_debug = true;
             /* The address covered by the breakpoint must be included in
@@ -5829,7 +5828,7 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
                 || tcg_op_buf_full()
                 || num_insns >= max_insns
                 || singlestep
-                || cs->singlestep_enabled
+                || cpu->singlestep_enabled
                 || dc.ex_value)) {
             status = EXIT_PC_STALE;
         }
@@ -5880,7 +5879,7 @@ void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
             qemu_log("IN: EXECUTE %016" PRIx64 "\n", dc.ex_value);
         } else {
             qemu_log("IN: %s\n", lookup_symbol(pc_start));
-            log_target_disas(cs, pc_start, dc.pc - pc_start, 1);
+            log_target_disas(cpu, pc_start, dc.pc - pc_start, 1);
             qemu_log("\n");
         }
         qemu_log_unlock();
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
index 8bc132b27b..6a797072d4 100644
--- a/target/sh4/translate.c
+++ b/target/sh4/translate.c
@@ -1815,10 +1815,9 @@ static void decode_opc(DisasContext * ctx)
     }
 }
 
-void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    SuperHCPU *cpu = sh_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUSH4State *env = cpu->env_ptr;
     DisasContext ctx;
     target_ulong pc_start;
     int num_insns;
@@ -1834,7 +1833,7 @@ void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
        so assume it is a dynamic branch.  */
     ctx.delayed_pc = -1; /* use delayed pc from env pointer */
     ctx.tb = tb;
-    ctx.singlestep_enabled = cs->singlestep_enabled;
+    ctx.singlestep_enabled = cpu->singlestep_enabled;
     ctx.features = env->features;
     ctx.has_movcal = (ctx.tbflags & TB_FLAG_PENDING_MOVCA);
 
@@ -1852,7 +1851,7 @@ void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
         tcg_gen_insn_start(ctx.pc, ctx.envflags);
         num_insns++;
 
-        if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, ctx.pc, BP_ANY))) {
             /* We have hit a breakpoint - make sure PC is up-to-date */
             gen_save_cpu_state(&ctx, true);
             gen_helper_debug(cpu_env);
@@ -1874,7 +1873,7 @@ void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
 	ctx.pc += 2;
 	if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
 	    break;
-        if (cs->singlestep_enabled) {
+        if (cpu->singlestep_enabled) {
 	    break;
         }
         if (num_insns >= max_insns)
@@ -1884,7 +1883,7 @@ void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
     }
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
-    if (cs->singlestep_enabled) {
+    if (cpu->singlestep_enabled) {
         gen_save_cpu_state(&ctx, true);
         gen_helper_debug(cpu_env);
     } else {
@@ -1915,7 +1914,7 @@ void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
         && qemu_log_in_addr_range(pc_start)) {
         qemu_log_lock();
 	qemu_log("IN:\n");	/* , lookup_symbol(pc_start)); */
-        log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
+        log_target_disas(cpu, pc_start, ctx.pc - pc_start, 0);
 	qemu_log("\n");
         qemu_log_unlock();
     }
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index aa6734d54e..90c43e4460 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -5747,10 +5747,9 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
     }
 }
 
-void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
+void gen_intermediate_code(CPUState *cpu, TranslationBlock * tb)
 {
-    SPARCCPU *cpu = sparc_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUSPARCState *env = cpu->env_ptr;
     target_ulong pc_start, last_pc;
     DisasContext dc1, *dc = &dc1;
     int num_insns;
@@ -5768,7 +5767,7 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
     dc->def = env->def;
     dc->fpu_enabled = tb_fpu_enabled(tb->flags);
     dc->address_mask_32bit = tb_am_enabled(tb->flags);
-    dc->singlestep = (cs->singlestep_enabled || singlestep);
+    dc->singlestep = (cpu->singlestep_enabled || singlestep);
 #ifndef CONFIG_USER_ONLY
     dc->supervisor = (tb->flags & TB_FLAG_SUPER) != 0;
 #endif
@@ -5800,7 +5799,7 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
         num_insns++;
         last_pc = dc->pc;
 
-        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, dc->pc, BP_ANY))) {
             if (dc->pc != pc_start) {
                 save_state(dc);
             }
@@ -5864,7 +5863,7 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
         qemu_log_lock();
         qemu_log("--------------\n");
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(cs, pc_start, last_pc + 4 - pc_start, 0);
+        log_target_disas(cpu, pc_start, last_pc + 4 - pc_start, 0);
         qemu_log("\n");
         qemu_log_unlock();
     }
diff --git a/target/tilegx/translate.c b/target/tilegx/translate.c
index ff2ef7b63d..a86e9e9d22 100644
--- a/target/tilegx/translate.c
+++ b/target/tilegx/translate.c
@@ -2370,12 +2370,11 @@ static void translate_one_bundle(DisasContext *dc, uint64_t bundle)
     }
 }
 
-void gen_intermediate_code(CPUTLGState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    TileGXCPU *cpu = tilegx_env_get_cpu(env);
+    CPUTLGState *env = cpu->env_ptr;
     DisasContext ctx;
     DisasContext *dc = &ctx;
-    CPUState *cs = CPU(cpu);
     uint64_t pc_start = tb->pc;
     uint64_t next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     int num_insns = 0;
@@ -2397,7 +2396,7 @@ void gen_intermediate_code(CPUTLGState *env, struct TranslationBlock *tb)
     if (!max_insns) {
         max_insns = CF_COUNT_MASK;
     }
-    if (cs->singlestep_enabled || singlestep) {
+    if (cpu->singlestep_enabled || singlestep) {
         max_insns = 1;
     }
     if (max_insns > TCG_MAX_INSNS) {
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
index ddd2dd07dd..1930da2f2a 100644
--- a/target/tricore/translate.c
+++ b/target/tricore/translate.c
@@ -8782,10 +8782,9 @@ static void decode_opc(CPUTriCoreState *env, DisasContext *ctx, int *is_branch)
     }
 }
 
-void gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    TriCoreCPU *cpu = tricore_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUTriCoreState *env = cpu->env_ptr;
     DisasContext ctx;
     target_ulong pc_start;
     int num_insns, max_insns;
@@ -8806,7 +8805,7 @@ void gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb)
     ctx.pc = pc_start;
     ctx.saved_pc = -1;
     ctx.tb = tb;
-    ctx.singlestep_enabled = cs->singlestep_enabled;
+    ctx.singlestep_enabled = cpu->singlestep_enabled;
     ctx.bstate = BS_NONE;
     ctx.mem_idx = cpu_mmu_index(env, false);
 
@@ -8840,7 +8839,7 @@ void gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb)
         && qemu_log_in_addr_range(pc_start)) {
         qemu_log_lock();
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
+        log_target_disas(cpu, pc_start, ctx.pc - pc_start, 0);
         qemu_log("\n");
         qemu_log_unlock();
     }
diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c
index 666a2016a8..494ed58c10 100644
--- a/target/unicore32/translate.c
+++ b/target/unicore32/translate.c
@@ -1869,10 +1869,9 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
 }
 
 /* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
-    UniCore32CPU *cpu = uc32_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUUniCore32State *env = cpu->env_ptr;
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_start;
     uint32_t next_page_start;
@@ -1888,7 +1887,7 @@ void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
-    dc->singlestep_enabled = cs->singlestep_enabled;
+    dc->singlestep_enabled = cpu->singlestep_enabled;
     dc->condjmp = 0;
     cpu_F0s = tcg_temp_new_i32();
     cpu_F1s = tcg_temp_new_i32();
@@ -1917,7 +1916,7 @@ void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
         tcg_gen_insn_start(dc->pc);
         num_insns++;
 
-        if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, dc->pc, BP_ANY))) {
             gen_set_pc_im(dc->pc);
             gen_exception(EXCP_DEBUG);
             dc->is_jmp = DISAS_JUMP;
@@ -1949,7 +1948,7 @@ void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
          * Also stop translation when a page boundary is reached.  This
          * ensures prefetch aborts occur at the right place.  */
     } while (!dc->is_jmp && !tcg_op_buf_full() &&
-             !cs->singlestep_enabled &&
+             !cpu->singlestep_enabled &&
              !singlestep &&
              dc->pc < next_page_start &&
              num_insns < max_insns);
@@ -1958,7 +1957,7 @@ void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
         if (dc->condjmp) {
             /* FIXME:  This can theoretically happen with self-modifying
                code.  */
-            cpu_abort(cs, "IO on conditional branch instruction");
+            cpu_abort(cpu, "IO on conditional branch instruction");
         }
         gen_io_end();
     }
@@ -1966,7 +1965,7 @@ void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
     /* At this stage dc->condjmp will only be set when the skipped
        instruction was a conditional branch or trap, and the PC has
        already been written.  */
-    if (unlikely(cs->singlestep_enabled)) {
+    if (unlikely(cpu->singlestep_enabled)) {
         /* Make sure the pc is updated, and raise a debug exception.  */
         if (dc->condjmp) {
             if (dc->is_jmp == DISAS_SYSCALL) {
@@ -2027,7 +2026,7 @@ done_generating:
         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, 0);
+        log_target_disas(cpu, pc_start, dc->pc - pc_start, 0);
         qemu_log("\n");
         qemu_log_unlock();
     }
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 263002486c..63e4f25c08 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -3117,10 +3117,9 @@ static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc)
     }
 }
 
-void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
-    XtensaCPU *cpu = xtensa_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUXtensaState *env = cpu->env_ptr;
     DisasContext dc;
     int insn_count = 0;
     int max_insns = tb->cflags & CF_COUNT_MASK;
@@ -3136,7 +3135,7 @@ void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
     }
 
     dc.config = env->config;
-    dc.singlestep_enabled = cs->singlestep_enabled;
+    dc.singlestep_enabled = cpu->singlestep_enabled;
     dc.tb = tb;
     dc.pc = pc_start;
     dc.ring = tb->flags & XTENSA_TBFLAG_RING_MASK;
@@ -3179,7 +3178,7 @@ void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
         tcg_gen_insn_start(dc.pc);
         ++insn_count;
 
-        if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) {
+        if (unlikely(cpu_breakpoint_test(cpu, dc.pc, BP_ANY))) {
             tcg_gen_movi_i32(cpu_pc, dc.pc);
             gen_exception(&dc, EXCP_DEBUG);
             dc.is_jmp = DISAS_UPDATE;
@@ -3215,7 +3214,7 @@ void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
         if (dc.icount) {
             tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);
         }
-        if (cs->singlestep_enabled) {
+        if (cpu->singlestep_enabled) {
             tcg_gen_movi_i32(cpu_pc, dc.pc);
             gen_exception(&dc, EXCP_DEBUG);
             break;
@@ -3247,7 +3246,7 @@ done:
         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, 0);
+        log_target_disas(cpu, pc_start, dc.pc - pc_start, 0);
         qemu_log("\n");
         qemu_log_unlock();
     }

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 02/29] cpu-exec: Avoid global variables in icount-related functions
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
  2017-06-28 12:20 ` [Qemu-devel] [PATCH v11 01/29] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
@ 2017-06-28 12:24 ` Lluís Vilanova
  2017-06-29 22:56   ` Emilio G. Cota
  2017-06-28 12:28 ` [Qemu-devel] [PATCH v11 03/29] target: [tcg] Use a generic enum for DISAS_ values Lluís Vilanova
                   ` (26 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 12:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 include/exec/gen-icount.h |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index 62d462e494..3fb17d435a 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -19,7 +19,7 @@ static inline void gen_tb_start(TranslationBlock *tb)
         count = tcg_temp_new_i32();
     }
 
-    tcg_gen_ld_i32(count, cpu_env,
+    tcg_gen_ld_i32(count, tcg_ctx.tcg_env,
                    -ENV_OFFSET + offsetof(CPUState, icount_decr.u32));
 
     if (tb->cflags & CF_USE_ICOUNT) {
@@ -37,7 +37,7 @@ static inline void gen_tb_start(TranslationBlock *tb)
     tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, exitreq_label);
 
     if (tb->cflags & CF_USE_ICOUNT) {
-        tcg_gen_st16_i32(count, cpu_env,
+        tcg_gen_st16_i32(count, tcg_ctx.tcg_env,
                          -ENV_OFFSET + offsetof(CPUState, icount_decr.u16.low));
     }
 
@@ -62,14 +62,14 @@ static void gen_tb_end(TranslationBlock *tb, int num_insns)
 static inline void gen_io_start(void)
 {
     TCGv_i32 tmp = tcg_const_i32(1);
-    tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
+    tcg_gen_st_i32(tmp, tcg_ctx.tcg_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
     tcg_temp_free_i32(tmp);
 }
 
 static inline void gen_io_end(void)
 {
     TCGv_i32 tmp = tcg_const_i32(0);
-    tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
+    tcg_gen_st_i32(tmp, tcg_ctx.tcg_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
     tcg_temp_free_i32(tmp);
 }
 

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 03/29] target: [tcg] Use a generic enum for DISAS_ values
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
  2017-06-28 12:20 ` [Qemu-devel] [PATCH v11 01/29] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
  2017-06-28 12:24 ` [Qemu-devel] [PATCH v11 02/29] cpu-exec: Avoid global variables in icount-related functions Lluís Vilanova
@ 2017-06-28 12:28 ` Lluís Vilanova
  2017-06-29 23:09   ` Emilio G. Cota
  2017-07-01 22:48   ` Richard Henderson
  2017-06-28 12:32 ` [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework Lluís Vilanova
                   ` (25 subsequent siblings)
  28 siblings, 2 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 12:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell,
	Edgar E. Iglesias, Eduardo Habkost, Michael Walle,
	Laurent Vivier, Chris Wulff, Marek Vasut, Stafford Horne,
	Alexander Graf, Guan Xuetao, Max Filippov, open list:ARM

Used later. An enum makes expected values explicit and bounds the value space of
switches.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 include/exec/exec-all.h       |    6 ------
 include/exec/translator.h     |   38 ++++++++++++++++++++++++++++++++++++++
 target/arm/translate.h        |   26 ++++++++++++++++----------
 target/cris/translate.c       |    7 ++++++-
 target/i386/translate.c       |    4 ++++
 target/lm32/translate.c       |    6 ++++++
 target/m68k/translate.c       |    7 ++++++-
 target/microblaze/translate.c |    6 ++++++
 target/nios2/translate.c      |    6 ++++++
 target/openrisc/translate.c   |    6 ++++++
 target/s390x/translate.c      |    3 ++-
 target/unicore32/translate.c  |    7 ++++++-
 target/xtensa/translate.c     |    4 ++++
 13 files changed, 106 insertions(+), 20 deletions(-)
 create mode 100644 include/exec/translator.h

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index a7cd106587..7e58d64313 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -35,12 +35,6 @@ typedef abi_ulong tb_page_addr_t;
 typedef ram_addr_t tb_page_addr_t;
 #endif
 
-/* is_jmp field values */
-#define DISAS_NEXT    0 /* next instruction can be analyzed */
-#define DISAS_JUMP    1 /* only pc was modified dynamically */
-#define DISAS_UPDATE  2 /* cpu state was modified dynamically */
-#define DISAS_TB_JUMP 3 /* only pc was modified statically */
-
 #include "qemu/log.h"
 
 void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
diff --git a/include/exec/translator.h b/include/exec/translator.h
new file mode 100644
index 0000000000..1ffab03a53
--- /dev/null
+++ b/include/exec/translator.h
@@ -0,0 +1,38 @@
+/*
+ * Generic intermediate code generation.
+ *
+ * Copyright (C) 2016-2017 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef EXEC__TRANSLATOR_H
+#define EXEC__TRANSLATOR_H
+
+/**
+ * DisasJumpType:
+ * @DISAS_NEXT: Next instruction in program order.
+ * @DISAS_TOO_MANY: Too many instructions translated.
+ * @DISAS_TARGET: Start of target-specific conditions.
+ *
+ * What instruction to disassemble next.
+ */
+typedef enum DisasJumpType {
+    DISAS_NEXT,
+    DISAS_TOO_MANY,
+    DISAS_TARGET_0,
+    DISAS_TARGET_1,
+    DISAS_TARGET_2,
+    DISAS_TARGET_3,
+    DISAS_TARGET_4,
+    DISAS_TARGET_5,
+    DISAS_TARGET_6,
+    DISAS_TARGET_7,
+    DISAS_TARGET_8,
+    DISAS_TARGET_9,
+    DISAS_TARGET_10,
+    DISAS_TARGET_11,
+} DisasJumpType;
+
+#endif  /* EXEC__TRANSLATOR_H */
diff --git a/target/arm/translate.h b/target/arm/translate.h
index e5da614db5..aba3f44c9f 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -1,6 +1,9 @@
 #ifndef TARGET_ARM_TRANSLATE_H
 #define TARGET_ARM_TRANSLATE_H
 
+#include "exec/translator.h"
+
+
 /* internal defines */
 typedef struct DisasContext {
     target_ulong pc;
@@ -119,30 +122,33 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
     s->insn_start_idx = 0;
 }
 
-/* target-specific extra values for is_jmp */
+/* 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 */
 /* These instructions trap after executing, so the A32/T32 decoder must
  * defer them until after the conditional execution state has been updated.
  * WFI also needs special handling when single-stepping.
  */
-#define DISAS_WFI 4
-#define DISAS_SWI 5
+#define DISAS_WFI DISAS_TARGET_3
+#define DISAS_SWI DISAS_TARGET_4
 /* For instructions which unconditionally cause an exception we can skip
  * emitting unreachable code at the end of the TB in the A64 decoder
  */
-#define DISAS_EXC 6
+#define DISAS_EXC DISAS_TARGET_5
 /* WFE */
-#define DISAS_WFE 7
-#define DISAS_HVC 8
-#define DISAS_SMC 9
-#define DISAS_YIELD 10
+#define DISAS_WFE DISAS_TARGET_6
+#define DISAS_HVC DISAS_TARGET_7
+#define DISAS_SMC DISAS_TARGET_8
+#define DISAS_YIELD DISAS_TARGET_9
 /* M profile branch which might be an exception return (and so needs
  * custom end-of-TB code)
  */
-#define DISAS_BX_EXCRET 11
+#define DISAS_BX_EXCRET DISAS_TARGET_10
 /* For instructions which want an immediate exit to the main loop,
  * as opposed to attempting to use lookup_and_goto_ptr.
  */
-#define DISAS_EXIT 12
+#define DISAS_EXIT DISAS_TARGET_11
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 35931e7061..164eed2e9c 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -31,6 +31,7 @@
 #include "exec/helper-proto.h"
 #include "mmu.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
 #include "crisv32-decode.h"
 
 #include "exec/helper-gen.h"
@@ -50,7 +51,11 @@
 #define BUG() (gen_BUG(dc, __FILE__, __LINE__))
 #define BUG_ON(x) ({if (x) BUG();})
 
-#define DISAS_SWI 5
+/* 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 */
+#define DISAS_SWI     DISAS_TARGET_3
 
 /* Used by the decoder.  */
 #define EXTRACT_FIELD(src, start, end) \
diff --git a/target/i386/translate.c b/target/i386/translate.c
index b94303ff10..5b02637400 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -24,6 +24,7 @@
 #include "exec/exec-all.h"
 #include "tcg-op.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
@@ -71,6 +72,9 @@
 
 //#define MACRO_TEST   1
 
+/* is_jmp field values */
+#define DISAS_TB_JUMP DISAS_TARGET_0 /* only pc was modified statically */
+
 /* global register indexes */
 static TCGv_env cpu_env;
 static TCGv cpu_A0;
diff --git a/target/lm32/translate.c b/target/lm32/translate.c
index 0ac34fc620..c33884e18e 100644
--- a/target/lm32/translate.c
+++ b/target/lm32/translate.c
@@ -22,6 +22,7 @@
 #include "disas/disas.h"
 #include "exec/helper-proto.h"
 #include "exec/exec-all.h"
+#include "exec/translator.h"
 #include "tcg-op.h"
 
 #include "exec/cpu_ldst.h"
@@ -47,6 +48,11 @@
 
 #define MEM_INDEX 0
 
+/* 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 */
+
 static TCGv_env cpu_env;
 static TCGv cpu_R[32];
 static TCGv cpu_pc;
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 01ef3923c9..26afa3cf8c 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -25,6 +25,7 @@
 #include "tcg-op.h"
 #include "qemu/log.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
@@ -173,7 +174,11 @@ static void do_writebacks(DisasContext *s)
     }
 }
 
-#define DISAS_JUMP_NEXT 4
+/* 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 */
+#define DISAS_JUMP_NEXT DISAS_TARGET_3
 
 #if defined(CONFIG_USER_ONLY)
 #define IS_USER(s) 1
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index d5f499658d..f6cbf29299 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -27,6 +27,7 @@
 #include "microblaze-decode.h"
 #include "exec/cpu_ldst.h"
 #include "exec/helper-gen.h"
+#include "exec/translator.h"
 
 #include "trace-tcg.h"
 #include "exec/log.h"
@@ -46,6 +47,11 @@
 #define EXTRACT_FIELD(src, start, end) \
             (((src) >> start) & ((1 << (end - start + 1)) - 1))
 
+/* 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 */
+
 static TCGv env_debug;
 static TCGv_env cpu_env;
 static TCGv cpu_R[32];
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 8b97d6585f..6b0961837d 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -29,6 +29,12 @@
 #include "exec/helper-gen.h"
 #include "exec/log.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
+
+/* 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 */
 
 #define INSTRUCTION_FLG(func, flags) { (func), (flags) }
 #define INSTRUCTION(func)                  \
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index 4a28c96e53..b3ca1bd586 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -27,6 +27,7 @@
 #include "qemu/log.h"
 #include "qemu/bitops.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
@@ -37,6 +38,11 @@
 #define LOG_DIS(str, ...) \
     qemu_log_mask(CPU_LOG_TB_IN_ASM, "%08x: " str, dc->pc, ## __VA_ARGS__)
 
+/* 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 */
+
 typedef struct DisasContext {
     TranslationBlock *tb;
     target_ulong pc;
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 19ea08bb9d..ccddbc907b 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -76,7 +76,8 @@ typedef struct {
     } u;
 } DisasCompare;
 
-#define DISAS_EXCP 4
+/* is_jmp field values */
+#define DISAS_EXCP DISAS_TARGET_0
 
 #ifdef DEBUG_INLINE_BRANCHES
 static uint64_t inline_branch_hit[CC_OP_MAX];
diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c
index 494ed58c10..194aaf64ca 100644
--- a/target/unicore32/translate.c
+++ b/target/unicore32/translate.c
@@ -16,6 +16,7 @@
 #include "tcg-op.h"
 #include "qemu/log.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
@@ -45,9 +46,13 @@ typedef struct DisasContext {
 #define IS_USER(s)      1
 #endif
 
+/* 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 */
 /* These instructions trap after executing, so defer them until after the
    conditional executions state has been updated.  */
-#define DISAS_SYSCALL 5
+#define DISAS_SYSCALL DISAS_TARGET_3
 
 static TCGv_env cpu_env;
 static TCGv_i32 cpu_R[32];
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 63e4f25c08..1f4b214c6a 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -38,6 +38,7 @@
 #include "sysemu/sysemu.h"
 #include "exec/cpu_ldst.h"
 #include "exec/semihost.h"
+#include "exec/translator.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
@@ -46,6 +47,9 @@
 #include "exec/log.h"
 
 
+/* is_jmp field values */
+#define DISAS_UPDATE  DISAS_TARGET_0 /* cpu state was modified dynamically */
+
 typedef struct DisasContext {
     const XtensaConfig *config;
     TranslationBlock *tb;

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (2 preceding siblings ...)
  2017-06-28 12:28 ` [Qemu-devel] [PATCH v11 03/29] target: [tcg] Use a generic enum for DISAS_ values Lluís Vilanova
@ 2017-06-28 12:32 ` Lluís Vilanova
  2017-06-30  0:02   ` Emilio G. Cota
                     ` (2 more replies)
  2017-06-28 12:36 ` [Qemu-devel] [PATCH v11 05/29] target/i386: [tcg] Port to DisasContextBase Lluís Vilanova
                   ` (24 subsequent siblings)
  28 siblings, 3 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 12:32 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 accel/tcg/Makefile.objs   |    1 
 accel/tcg/translator.c    |  153 +++++++++++++++++++++++++++++++++++++++++++++
 include/exec/gen-icount.h |    2 -
 include/exec/translator.h |  104 +++++++++++++++++++++++++++++++
 4 files changed, 259 insertions(+), 1 deletion(-)
 create mode 100644 accel/tcg/translator.c

diff --git a/accel/tcg/Makefile.objs b/accel/tcg/Makefile.objs
index f173cd5397..3a5da5357c 100644
--- a/accel/tcg/Makefile.objs
+++ b/accel/tcg/Makefile.objs
@@ -1,3 +1,4 @@
 obj-$(CONFIG_SOFTMMU) += tcg-all.o
 obj-$(CONFIG_SOFTMMU) += cputlb.o
 obj-y += cpu-exec.o cpu-exec-common.o translate-all.o translate-common.o
+obj-y += translator.o
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
new file mode 100644
index 0000000000..b941ebdc62
--- /dev/null
+++ b/accel/tcg/translator.c
@@ -0,0 +1,153 @@
+/*
+ * Generic intermediate code generation.
+ *
+ * Copyright (C) 2016-2017 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "cpu.h"
+#include "tcg/tcg.h"
+#include "tcg/tcg-op.h"
+#include "exec/exec-all.h"
+#include "exec/gen-icount.h"
+#include "exec/log.h"
+#include "exec/translator.h"
+
+
+static inline void translate_block_tcg_check(const DisasContextBase *db)
+{
+    if (tcg_check_temp_count()) {
+        error_report("warning: TCG temporary leaks before "TARGET_FMT_lx,
+                     db->pc_next);
+    }
+}
+
+void translate_block(const TranslatorOps *ops, DisasContextBase *db,
+                     CPUState *cpu, TranslationBlock *tb)
+{
+    int max_insns;
+
+    /* Initialize DisasContext */
+    db->tb = tb;
+    db->pc_first = tb->pc;
+    db->pc_next = db->pc_first;
+    db->is_jmp = DISAS_NEXT;
+    db->num_insns = 0;
+    db->singlestep_enabled = cpu->singlestep_enabled;
+    ops->init_disas_context(db, cpu);
+
+    /* Initialize globals */
+    ops->init_globals(db, cpu);
+    tcg_clear_temp_count();
+
+    /* Instruction counting */
+    max_insns = db->tb->cflags & CF_COUNT_MASK;
+    if (max_insns == 0) {
+        max_insns = CF_COUNT_MASK;
+    }
+    if (max_insns > TCG_MAX_INSNS) {
+        max_insns = TCG_MAX_INSNS;
+    }
+    if (db->singlestep_enabled || singlestep) {
+        max_insns = 1;
+    }
+
+    /* Start translating */
+    gen_tb_start(db->tb);
+    ops->tb_start(db, cpu);
+
+    while (true) {
+        db->num_insns++;
+        ops->insn_start(db, cpu);
+
+        /* Early exit before breakpoint checks */
+        if (unlikely(db->is_jmp != DISAS_NEXT)) {
+            break;
+        }
+
+        /* Pass breakpoint hits to target for further processing */
+        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
+            CPUBreakpoint *bp;
+            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
+                if (bp->pc == db->pc_next) {
+                    BreakpointCheckType bp_check =
+                        ops->breakpoint_check(db, cpu, bp);
+                    switch (bp_check) {
+                    case BC_MISS:
+                        /* Target ignored this breakpoint, go to next */
+                        break;
+                    case BC_HIT_INSN:
+                        /* Hit, keep translating */
+                        /*
+                         * TODO: if we're never going to have more than one
+                         *       BP in a single address, we can simply use a
+                         *       bool here.
+                         */
+                        goto done_breakpoints;
+                    case BC_HIT_TB:
+                        /* Hit, end TB */
+                        goto done_generating;
+                    default:
+                        g_assert_not_reached();
+                    }
+                }
+            }
+        }
+    done_breakpoints:
+
+        /* Accept I/O on last instruction */
+        if (db->num_insns == max_insns && (db->tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+
+        /* Disassemble one instruction */
+        db->pc_next = ops->translate_insn(db, cpu);
+
+        /**************************************************/
+        /* Conditions to stop translation                 */
+        /**************************************************/
+
+        /* Target-specific conditions set by disassembly */
+        if (db->is_jmp != DISAS_NEXT) {
+            break;
+        }
+
+        /* Too many instructions */
+        if (tcg_op_buf_full() || db->num_insns >= max_insns) {
+            db->is_jmp = DISAS_TOO_MANY;
+            break;
+        }
+
+        translate_block_tcg_check(db);
+    }
+
+    ops->tb_stop(db, cpu);
+
+    if (db->tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+
+done_generating:
+    gen_tb_end(db->tb, db->num_insns);
+
+    translate_block_tcg_check(db);
+
+#ifdef DEBUG_DISAS
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
+        && qemu_log_in_addr_range(db->pc_first)) {
+        qemu_log_lock();
+        qemu_log("----------------\n");
+        ops->disas_log(db, cpu);
+        qemu_log("\n");
+        qemu_log_unlock();
+    }
+#endif
+
+    db->tb->size = db->pc_next - db->pc_first;
+    db->tb->icount = db->num_insns;
+}
diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index 3fb17d435a..d66ca09f60 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -44,7 +44,7 @@ static inline void gen_tb_start(TranslationBlock *tb)
     tcg_temp_free_i32(count);
 }
 
-static void gen_tb_end(TranslationBlock *tb, int num_insns)
+static inline void gen_tb_end(TranslationBlock *tb, int num_insns)
 {
     if (tb->cflags & CF_USE_ICOUNT) {
         /* Update the num_insn immediate parameter now that we know
diff --git a/include/exec/translator.h b/include/exec/translator.h
index 1ffab03a53..c6fe64f988 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -10,6 +10,38 @@
 #ifndef EXEC__TRANSLATOR_H
 #define EXEC__TRANSLATOR_H
 
+/*
+ * Include this header from a target-specific file, and add a
+ *
+ *     DisasContextBase base;
+ *
+ * member in your target-specific DisasContext.
+ */
+
+
+#include "exec/exec-all.h"
+#include "tcg/tcg.h"
+
+
+/**
+ * BreakpointCheckType:
+ * @BC_MISS: No hit
+ * @BC_HIT_INSN: Hit, but continue translating TB
+ * @BC_HIT_TB: Hit, stop translating TB
+ *
+ * How to react to a breakpoint. A hit means no more breakpoints will be checked
+ * for the current instruction.
+ *
+ * Not all breakpoints associated to an address are necessarily raised by
+ * targets (e.g., due to conditions encoded in their flags), so tey can decide
+ * that a breakpoint missed the address (@BP_MISS).
+ */
+typedef enum BreakpointCheckType {
+    BC_MISS,
+    BC_HIT_INSN,
+    BC_HIT_TB,
+} BreakpointCheckType;
+
 /**
  * DisasJumpType:
  * @DISAS_NEXT: Next instruction in program order.
@@ -33,6 +65,78 @@ typedef enum DisasJumpType {
     DISAS_TARGET_9,
     DISAS_TARGET_10,
     DISAS_TARGET_11,
+    DISAS_TARGET_12,
+    DISAS_TARGET_13,
+    DISAS_TARGET_14,
 } DisasJumpType;
 
+/**
+ * DisasContextBase:
+ * @tb: Translation block for this disassembly.
+ * @pc_first: Address of first guest instruction in this TB.
+ * @pc_next: Address of next guest instruction in this TB (current during
+ *           disassembly).
+ * @is_jmp: What instruction to disassemble next.
+ * @num_insns: Number of translated instructions (including current).
+ * @singlestep_enabled: "Hardware" single stepping enabled.
+ *
+ * Architecture-agnostic disassembly context.
+ */
+typedef struct DisasContextBase {
+    TranslationBlock *tb;
+    target_ulong pc_first;
+    target_ulong pc_next;
+    DisasJumpType is_jmp;
+    unsigned int num_insns;
+    bool singlestep_enabled;
+} DisasContextBase;
+
+/**
+ * TranslatorOps:
+ * @init_disas_context: Initialize a DisasContext struct (DisasContextBase has
+ *                      already been initialized).
+ * @init_globals: Initialize global variables.
+ * @tb_start: Start translating a new TB.
+ * @insn_start: Start translating a new instruction.
+ * @breakpoint_check: Check if a breakpoint did hit. When called, the breakpoint
+ *                    has already been checked to match the PC.
+ * @disas_insn: Disassemble one instruction an return the PC for the next
+ *              one. Can set db->is_jmp to DJ_TARGET or above to stop
+ *              translation.
+ * @tb_stop: Stop translating a TB.
+ * @disas_flags: Get flags argument for log_target_disas().
+ *
+ * Target-specific operations for the generic translator loop.
+ */
+typedef struct TranslatorOps {
+    void (*init_disas_context)(DisasContextBase *db, CPUState *cpu);
+    void (*init_globals)(DisasContextBase *db, CPUState *cpu);
+    void (*tb_start)(DisasContextBase *db, CPUState *cpu);
+    void (*insn_start)(DisasContextBase *db, CPUState *cpu);
+    BreakpointCheckType (*breakpoint_check)(DisasContextBase *db, CPUState *cpu,
+                                            const CPUBreakpoint *bp);
+    target_ulong (*translate_insn)(DisasContextBase *db, CPUState *cpu);
+    void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
+    void (*disas_log)(const DisasContextBase *db, CPUState *cpu);
+} TranslatorOps;
+
+/**
+ * translate_block:
+ * @ops: Target-specific operations.
+ * @db: Disassembly context.
+ * @cpu: Target vCPU.
+ * @tb: Translation block.
+ *
+ * Generic translator loop.
+ *
+ * Translation will stop in the following cases (in order):
+ * - When set by #TranslatorOps::insn_start.
+ * - When set by #TranslatorOps::translate_insn.
+ * - When the TCG operation buffer is full.
+ * - When single-stepping is enabled (system-wide or on the current vCPU).
+ * - When too many instructions have been translated.
+ */
+void translate_block(const TranslatorOps *ops, DisasContextBase *db,
+                     CPUState *cpu, TranslationBlock *tb);
+
 #endif  /* EXEC__TRANSLATOR_H */

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 05/29] target/i386: [tcg] Port to DisasContextBase
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (3 preceding siblings ...)
  2017-06-28 12:32 ` [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework Lluís Vilanova
@ 2017-06-28 12:36 ` Lluís Vilanova
  2017-06-29 23:33   ` Emilio G. Cota
  2017-07-01 23:39   ` Richard Henderson
  2017-06-28 12:40 ` [Qemu-devel] [PATCH v11 06/29] target/i386: [tcg] Refactor init_disas_context Lluís Vilanova
                   ` (23 subsequent siblings)
  28 siblings, 2 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 12:36 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/i386/translate.c |  142 +++++++++++++++++++++++------------------------
 1 file changed, 70 insertions(+), 72 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 5b02637400..8cf2485e2c 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -99,6 +99,8 @@ static int x86_64_hregs;
 #endif
 
 typedef struct DisasContext {
+    DisasContextBase base;
+
     /* current insn context */
     int override; /* -1 if no override */
     int prefix;
@@ -106,8 +108,6 @@ typedef struct DisasContext {
     TCGMemOp dflag;
     target_ulong pc_start;
     target_ulong pc; /* pc = eip + cs_base */
-    int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
-                   static state change (stop translation) */
     /* current block context */
     target_ulong cs_base; /* base of CS segment */
     int pe;     /* protected mode */
@@ -128,12 +128,10 @@ typedef struct DisasContext {
     int cpl;
     int iopl;
     int tf;     /* TF cpu flag */
-    int singlestep_enabled; /* "hardware" single step enabled */
     int jmp_opt; /* use direct block chaining for direct jumps */
     int repz_opt; /* optimize jumps within repz instructions */
     int mem_index; /* select memory access functions */
     uint64_t flags; /* all execution flags */
-    struct TranslationBlock *tb;
     int popl_esp_hack; /* for correct popl with esp base handling */
     int rip_offset; /* only used in x86_64, but left for simplicity */
     int cpuid_features;
@@ -1123,7 +1121,7 @@ static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
 
 static inline void gen_ins(DisasContext *s, TCGMemOp ot)
 {
-    if (s->tb->cflags & CF_USE_ICOUNT) {
+    if (s->base.tb->cflags & CF_USE_ICOUNT) {
         gen_io_start();
     }
     gen_string_movl_A0_EDI(s);
@@ -1138,14 +1136,14 @@ static inline void gen_ins(DisasContext *s, TCGMemOp ot)
     gen_op_movl_T0_Dshift(ot);
     gen_op_add_reg_T0(s->aflag, R_EDI);
     gen_bpt_io(s, cpu_tmp2_i32, ot);
-    if (s->tb->cflags & CF_USE_ICOUNT) {
+    if (s->base.tb->cflags & CF_USE_ICOUNT) {
         gen_io_end();
     }
 }
 
 static inline void gen_outs(DisasContext *s, TCGMemOp ot)
 {
-    if (s->tb->cflags & CF_USE_ICOUNT) {
+    if (s->base.tb->cflags & CF_USE_ICOUNT) {
         gen_io_start();
     }
     gen_string_movl_A0_ESI(s);
@@ -1158,7 +1156,7 @@ static inline void gen_outs(DisasContext *s, TCGMemOp ot)
     gen_op_movl_T0_Dshift(ot);
     gen_op_add_reg_T0(s->aflag, R_ESI);
     gen_bpt_io(s, cpu_tmp2_i32, ot);
-    if (s->tb->cflags & CF_USE_ICOUNT) {
+    if (s->base.tb->cflags & CF_USE_ICOUNT) {
         gen_io_end();
     }
 }
@@ -2141,7 +2139,7 @@ static inline int insn_const_size(TCGMemOp ot)
 static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
 {
 #ifndef CONFIG_USER_ONLY
-    return (pc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK) ||
+    return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) ||
            (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
 #else
     return true;
@@ -2156,7 +2154,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
         /* jump to same page: we can use a direct jump */
         tcg_gen_goto_tb(tb_num);
         gen_jmp_im(eip);
-        tcg_gen_exit_tb((uintptr_t)s->tb + tb_num);
+        tcg_gen_exit_tb((uintptr_t)s->base.tb + tb_num);
     } else {
         /* jump to another page */
         gen_jmp_im(eip);
@@ -2177,7 +2175,7 @@ static inline void gen_jcc(DisasContext *s, int b,
 
         gen_set_label(l1);
         gen_goto_tb(s, 1, val);
-        s->is_jmp = DISAS_TB_JUMP;
+        s->base.is_jmp = DISAS_TB_JUMP;
     } else {
         l1 = gen_new_label();
         l2 = gen_new_label();
@@ -2248,11 +2246,11 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
            stop as a special handling must be done to disable hardware
            interrupts for the next instruction */
         if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
-            s->is_jmp = DISAS_TB_JUMP;
+            s->base.is_jmp = DISAS_TB_JUMP;
     } else {
         gen_op_movl_seg_T0_vm(seg_reg);
         if (seg_reg == R_SS)
-            s->is_jmp = DISAS_TB_JUMP;
+            s->base.is_jmp = DISAS_TB_JUMP;
     }
 }
 
@@ -2424,7 +2422,7 @@ static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
     gen_update_cc_op(s);
     gen_jmp_im(cur_eip);
     gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
-    s->is_jmp = DISAS_TB_JUMP;
+    s->base.is_jmp = DISAS_TB_JUMP;
 }
 
 /* Generate #UD for the current instruction.  The assumption here is that
@@ -2462,7 +2460,7 @@ static void gen_interrupt(DisasContext *s, int intno,
     gen_jmp_im(cur_eip);
     gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
                                tcg_const_i32(next_eip - cur_eip));
-    s->is_jmp = DISAS_TB_JUMP;
+    s->base.is_jmp = DISAS_TB_JUMP;
 }
 
 static void gen_debug(DisasContext *s, target_ulong cur_eip)
@@ -2470,7 +2468,7 @@ static void gen_debug(DisasContext *s, target_ulong cur_eip)
     gen_update_cc_op(s);
     gen_jmp_im(cur_eip);
     gen_helper_debug(cpu_env);
-    s->is_jmp = DISAS_TB_JUMP;
+    s->base.is_jmp = DISAS_TB_JUMP;
 }
 
 static void gen_set_hflag(DisasContext *s, uint32_t mask)
@@ -2526,10 +2524,10 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, TCGv jr)
         gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
     }
 
-    if (s->tb->flags & HF_RF_MASK) {
+    if (s->base.tb->flags & HF_RF_MASK) {
         gen_helper_reset_rf(cpu_env);
     }
-    if (s->singlestep_enabled) {
+    if (s->base.singlestep_enabled) {
         gen_helper_debug(cpu_env);
     } else if (recheck_tf) {
         gen_helper_rechecking_single_step(cpu_env);
@@ -2545,7 +2543,7 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, TCGv jr)
     } else {
         tcg_gen_exit_tb(0);
     }
-    s->is_jmp = DISAS_TB_JUMP;
+    s->base.is_jmp = DISAS_TB_JUMP;
 }
 
 static inline void
@@ -2584,7 +2582,7 @@ static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
     set_cc_op(s, CC_OP_DYNAMIC);
     if (s->jmp_opt) {
         gen_goto_tb(s, tb_num, eip);
-        s->is_jmp = DISAS_TB_JUMP;
+        s->base.is_jmp = DISAS_TB_JUMP;
     } else {
         gen_jmp_im(eip);
         gen_eob(s);
@@ -4419,7 +4417,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
     }
 }
 
-/* convert one instruction. s->is_jmp is set if the translation must
+/* convert one instruction. s->base.is_jmp is set if the translation must
    be stopped. Return the next pc value */
 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                                target_ulong pc_start)
@@ -5379,7 +5377,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_movl_seg_T0(s, reg);
         gen_pop_update(s, ot);
         /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp.  */
-        if (s->is_jmp) {
+        if (s->base.is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             if (reg == R_SS) {
                 s->tf = 0;
@@ -5394,7 +5392,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         ot = gen_pop_T0(s);
         gen_movl_seg_T0(s, (b >> 3) & 7);
         gen_pop_update(s, ot);
-        if (s->is_jmp) {
+        if (s->base.is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             gen_eob(s);
         }
@@ -5445,7 +5443,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
         gen_movl_seg_T0(s, reg);
         /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp.  */
-        if (s->is_jmp) {
+        if (s->base.is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             if (reg == R_SS) {
                 s->tf = 0;
@@ -5654,7 +5652,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_movl_seg_T0(s, op);
         /* then put the data */
         gen_op_mov_reg_v(ot, reg, cpu_T1);
-        if (s->is_jmp) {
+        if (s->base.is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             gen_eob(s);
         }
@@ -6310,7 +6308,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
             gen_ins(s, ot);
-            if (s->tb->cflags & CF_USE_ICOUNT) {
+            if (s->base.tb->cflags & CF_USE_ICOUNT) {
                 gen_jmp(s, s->pc - s->cs_base);
             }
         }
@@ -6325,7 +6323,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
             gen_outs(s, ot);
-            if (s->tb->cflags & CF_USE_ICOUNT) {
+            if (s->base.tb->cflags & CF_USE_ICOUNT) {
                 gen_jmp(s, s->pc - s->cs_base);
             }
         }
@@ -6341,14 +6339,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         tcg_gen_movi_tl(cpu_T0, val);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_start();
 	}
         tcg_gen_movi_i32(cpu_tmp2_i32, val);
         gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
         gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
         gen_bpt_io(s, cpu_tmp2_i32, ot);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6362,14 +6360,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                      svm_is_rep(prefixes));
         gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
 
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_start();
 	}
         tcg_gen_movi_i32(cpu_tmp2_i32, val);
         tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
         gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
         gen_bpt_io(s, cpu_tmp2_i32, ot);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6380,14 +6378,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_start();
 	}
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
         gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
         gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
         gen_bpt_io(s, cpu_tmp2_i32, ot);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6400,14 +6398,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                      svm_is_rep(prefixes));
         gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
 
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_start();
 	}
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
         tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
         gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
         gen_bpt_io(s, cpu_tmp2_i32, ot);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6946,7 +6944,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
             gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
-            s->is_jmp = DISAS_TB_JUMP;
+            s->base.is_jmp = DISAS_TB_JUMP;
         }
         break;
     case 0x9b: /* fwait */
@@ -7115,11 +7113,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x131: /* rdtsc */
         gen_update_cc_op(s);
         gen_jmp_im(pc_start - s->cs_base);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_start();
 	}
         gen_helper_rdtsc(cpu_env);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -7191,7 +7189,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
             gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
-            s->is_jmp = DISAS_TB_JUMP;
+            s->base.is_jmp = DISAS_TB_JUMP;
         }
         break;
     case 0x100:
@@ -7374,7 +7372,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
                              tcg_const_i32(s->pc - pc_start));
             tcg_gen_exit_tb(0);
-            s->is_jmp = DISAS_TB_JUMP;
+            s->base.is_jmp = DISAS_TB_JUMP;
             break;
 
         case 0xd9: /* VMMCALL */
@@ -7574,11 +7572,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             }
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
-            if (s->tb->cflags & CF_USE_ICOUNT) {
+            if (s->base.tb->cflags & CF_USE_ICOUNT) {
                 gen_io_start();
             }
             gen_helper_rdtscp(cpu_env);
-            if (s->tb->cflags & CF_USE_ICOUNT) {
+            if (s->base.tb->cflags & CF_USE_ICOUNT) {
                 gen_io_end();
                 gen_jmp(s, s->pc - s->cs_base);
             }
@@ -7943,24 +7941,24 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_update_cc_op(s);
                 gen_jmp_im(pc_start - s->cs_base);
                 if (b & 2) {
-                    if (s->tb->cflags & CF_USE_ICOUNT) {
+                    if (s->base.tb->cflags & CF_USE_ICOUNT) {
                         gen_io_start();
                     }
                     gen_op_mov_v_reg(ot, cpu_T0, rm);
                     gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
                                          cpu_T0);
-                    if (s->tb->cflags & CF_USE_ICOUNT) {
+                    if (s->base.tb->cflags & CF_USE_ICOUNT) {
                         gen_io_end();
                     }
                     gen_jmp_im(s->pc - s->cs_base);
                     gen_eob(s);
                 } else {
-                    if (s->tb->cflags & CF_USE_ICOUNT) {
+                    if (s->base.tb->cflags & CF_USE_ICOUNT) {
                         gen_io_start();
                     }
                     gen_helper_read_crN(cpu_T0, cpu_env, tcg_const_i32(reg));
                     gen_op_mov_reg_v(ot, rm, cpu_T0);
-                    if (s->tb->cflags & CF_USE_ICOUNT) {
+                    if (s->base.tb->cflags & CF_USE_ICOUNT) {
                         gen_io_end();
                     }
                 }
@@ -8386,15 +8384,13 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
     CPUX86State *env = cpu->env_ptr;
     DisasContext dc1, *dc = &dc1;
-    target_ulong pc_ptr;
     uint32_t flags;
-    target_ulong pc_start;
     target_ulong cs_base;
     int num_insns;
     int max_insns;
 
     /* generate intermediate code */
-    pc_start = tb->pc;
+    dc->base.pc_first = tb->pc;
     cs_base = tb->cs_base;
     flags = tb->flags;
 
@@ -8407,11 +8403,11 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
     dc->iopl = (flags >> IOPL_SHIFT) & 3;
     dc->tf = (flags >> TF_SHIFT) & 1;
-    dc->singlestep_enabled = cpu->singlestep_enabled;
+    dc->base.singlestep_enabled = cpu->singlestep_enabled;
     dc->cc_op = CC_OP_DYNAMIC;
     dc->cc_op_dirty = false;
     dc->cs_base = cs_base;
-    dc->tb = tb;
+    dc->base.tb = tb;
     dc->popl_esp_hack = 0;
     /* select memory access functions */
     dc->mem_index = 0;
@@ -8461,8 +8457,8 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     cpu_ptr1 = tcg_temp_new_ptr();
     cpu_cc_srcT = tcg_temp_local_new();
 
-    dc->is_jmp = DISAS_NEXT;
-    pc_ptr = pc_start;
+    dc->base.is_jmp = DISAS_NEXT;
+    dc->base.pc_next = dc->base.pc_first;
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
@@ -8474,37 +8470,38 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 
     gen_tb_start(tb);
     for(;;) {
-        tcg_gen_insn_start(pc_ptr, dc->cc_op);
+        tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
         num_insns++;
 
         /* If RF is set, suppress an internally generated breakpoint.  */
-        if (unlikely(cpu_breakpoint_test(cpu, pc_ptr,
+        if (unlikely(cpu_breakpoint_test(cpu, dc->base.pc_next,
                                          tb->flags & HF_RF_MASK
                                          ? BP_GDB : BP_ANY))) {
-            gen_debug(dc, pc_ptr - dc->cs_base);
+            gen_debug(dc, dc->base.pc_next - dc->cs_base);
             /* 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.  */
-            pc_ptr += 1;
+            dc->base.pc_next += 1;
             goto done_generating;
         }
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
         }
 
-        pc_ptr = disas_insn(env, dc, pc_ptr);
+        dc->base.pc_next = disas_insn(env, dc, dc->base.pc_next);
         /* stop translation if indicated */
-        if (dc->is_jmp)
+        if (dc->base.is_jmp) {
             break;
+        }
         /* if single step mode, we generate only one instruction and
            generate an exception */
         /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
            the flag and abort the translation to give the irqs a
            change to be happen */
-        if (dc->tf || dc->singlestep_enabled ||
+        if (dc->tf || dc->base.singlestep_enabled ||
             (flags & HF_INHIBIT_IRQ_MASK)) {
-            gen_jmp_im(pc_ptr - dc->cs_base);
+            gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
@@ -8515,23 +8512,23 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
            because an exception hasn't stopped this code.
          */
         if ((tb->cflags & CF_USE_ICOUNT)
-            && ((pc_ptr & TARGET_PAGE_MASK)
-                != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
-                || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
-            gen_jmp_im(pc_ptr - dc->cs_base);
+            && ((dc->base.pc_next & TARGET_PAGE_MASK)
+                != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
+                || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) {
+            gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
         /* if too long translation, stop generation too */
         if (tcg_op_buf_full() ||
-            (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
+            (dc->base.pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32) ||
             num_insns >= max_insns) {
-            gen_jmp_im(pc_ptr - dc->cs_base);
+            gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
         if (singlestep) {
-            gen_jmp_im(pc_ptr - dc->cs_base);
+            gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
@@ -8543,24 +8540,25 @@ done_generating:
 
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
-        && qemu_log_in_addr_range(pc_start)) {
+        && qemu_log_in_addr_range(dc->base.pc_first)) {
         int disas_flags;
         qemu_log_lock();
         qemu_log("----------------\n");
-        qemu_log("IN: %s\n", lookup_symbol(pc_start));
+        qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
 #ifdef TARGET_X86_64
         if (dc->code64)
             disas_flags = 2;
         else
 #endif
             disas_flags = !dc->code32;
-        log_target_disas(cpu, pc_start, pc_ptr - pc_start, disas_flags);
+        log_target_disas(cpu, dc->base.pc_first, dc->base.pc_next - dc->base.pc_first,
+                         disas_flags);
         qemu_log("\n");
         qemu_log_unlock();
     }
 #endif
 
-    tb->size = pc_ptr - pc_start;
+    tb->size = dc->base.pc_next - dc->base.pc_first;
     tb->icount = num_insns;
 }
 

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 06/29] target/i386: [tcg] Refactor init_disas_context
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (4 preceding siblings ...)
  2017-06-28 12:36 ` [Qemu-devel] [PATCH v11 05/29] target/i386: [tcg] Port to DisasContextBase Lluís Vilanova
@ 2017-06-28 12:40 ` Lluís Vilanova
  2017-06-29 23:51   ` Emilio G. Cota
  2017-07-01 23:50   ` Richard Henderson
  2017-06-28 12:44 ` [Qemu-devel] [PATCH v11 07/29] target/i386: [tcg] Refactor init_globals Lluís Vilanova
                   ` (22 subsequent siblings)
  28 siblings, 2 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 12:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/i386/translate.c |   43 ++++++++++++++++++++++++-------------------
 1 file changed, 24 insertions(+), 19 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 8cf2485e2c..04453ce48a 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8379,20 +8379,12 @@ void tcg_x86_init(void)
     }
 }
 
-/* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
+static void i386_trblock_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
 {
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
     CPUX86State *env = cpu->env_ptr;
-    DisasContext dc1, *dc = &dc1;
-    uint32_t flags;
-    target_ulong cs_base;
-    int num_insns;
-    int max_insns;
-
-    /* generate intermediate code */
-    dc->base.pc_first = tb->pc;
-    cs_base = tb->cs_base;
-    flags = tb->flags;
+    uint32_t flags = dc->base.tb->flags;
+    target_ulong cs_base = dc->base.tb->cs_base;
 
     dc->pe = (flags >> HF_PE_SHIFT) & 1;
     dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
@@ -8403,11 +8395,9 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
     dc->iopl = (flags >> IOPL_SHIFT) & 3;
     dc->tf = (flags >> TF_SHIFT) & 1;
-    dc->base.singlestep_enabled = cpu->singlestep_enabled;
     dc->cc_op = CC_OP_DYNAMIC;
     dc->cc_op_dirty = false;
     dc->cs_base = cs_base;
-    dc->base.tb = tb;
     dc->popl_esp_hack = 0;
     /* select memory access functions */
     dc->mem_index = 0;
@@ -8425,7 +8415,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
 #endif
     dc->flags = flags;
-    dc->jmp_opt = !(dc->tf || cpu->singlestep_enabled ||
+    dc->jmp_opt = !(dc->tf || dc->base.singlestep_enabled ||
                     (flags & HF_INHIBIT_IRQ_MASK));
     /* Do not optimize repz jumps at all in icount mode, because
        rep movsS instructions are execured with different paths
@@ -8437,12 +8427,29 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
        record/replay modes and there will always be an
        additional step for ecx=0 when icount is enabled.
      */
-    dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT);
+    dc->repz_opt = !dc->jmp_opt && !(dc->base.tb->cflags & CF_USE_ICOUNT);
 #if 0
     /* check addseg logic */
     if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
         printf("ERROR addseg\n");
 #endif
+}
+
+/* generate intermediate code for basic block 'tb'.  */
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
+{
+    CPUX86State *env = cpu->env_ptr;
+    DisasContext dc1, *dc = &dc1;
+    int num_insns;
+    int max_insns;
+
+    /* generate intermediate code */
+    dc->base.singlestep_enabled = cpu->singlestep_enabled;
+    dc->base.tb = tb;
+    dc->base.is_jmp = DISAS_NEXT;
+    dc->base.pc_first = tb->pc;
+    dc->base.pc_next = dc->base.pc_first;
+    i386_trblock_init_disas_context(&dc->base, cpu);
 
     cpu_T0 = tcg_temp_new();
     cpu_T1 = tcg_temp_new();
@@ -8457,8 +8464,6 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     cpu_ptr1 = tcg_temp_new_ptr();
     cpu_cc_srcT = tcg_temp_local_new();
 
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.pc_next = dc->base.pc_first;
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
@@ -8500,7 +8505,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
            the flag and abort the translation to give the irqs a
            change to be happen */
         if (dc->tf || dc->base.singlestep_enabled ||
-            (flags & HF_INHIBIT_IRQ_MASK)) {
+            (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
             gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 07/29] target/i386: [tcg] Refactor init_globals
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (5 preceding siblings ...)
  2017-06-28 12:40 ` [Qemu-devel] [PATCH v11 06/29] target/i386: [tcg] Refactor init_disas_context Lluís Vilanova
@ 2017-06-28 12:44 ` Lluís Vilanova
  2017-06-30  0:06   ` Emilio G. Cota
  2017-07-02  0:25   ` Richard Henderson
  2017-06-28 12:48 ` [Qemu-devel] [PATCH v11 08/29] target/i386: [tcg] Refactor insn_start Lluís Vilanova
                   ` (21 subsequent siblings)
  28 siblings, 2 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 12:44 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/i386/translate.c |   29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 04453ce48a..d015ea73fa 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8435,6 +8435,22 @@ static void i386_trblock_init_disas_context(DisasContextBase *dcbase, CPUState *
 #endif
 }
 
+static void i386_trblock_init_globals(DisasContextBase *dcbase, CPUState *cpu)
+{
+    cpu_T0 = tcg_temp_new();
+    cpu_T1 = tcg_temp_new();
+    cpu_A0 = tcg_temp_new();
+
+    cpu_tmp0 = tcg_temp_new();
+    cpu_tmp1_i64 = tcg_temp_new_i64();
+    cpu_tmp2_i32 = tcg_temp_new_i32();
+    cpu_tmp3_i32 = tcg_temp_new_i32();
+    cpu_tmp4 = tcg_temp_new();
+    cpu_ptr0 = tcg_temp_new_ptr();
+    cpu_ptr1 = tcg_temp_new_ptr();
+    cpu_cc_srcT = tcg_temp_local_new();
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -8451,18 +8467,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     dc->base.pc_next = dc->base.pc_first;
     i386_trblock_init_disas_context(&dc->base, cpu);
 
-    cpu_T0 = tcg_temp_new();
-    cpu_T1 = tcg_temp_new();
-    cpu_A0 = tcg_temp_new();
-
-    cpu_tmp0 = tcg_temp_new();
-    cpu_tmp1_i64 = tcg_temp_new_i64();
-    cpu_tmp2_i32 = tcg_temp_new_i32();
-    cpu_tmp3_i32 = tcg_temp_new_i32();
-    cpu_tmp4 = tcg_temp_new();
-    cpu_ptr0 = tcg_temp_new_ptr();
-    cpu_ptr1 = tcg_temp_new_ptr();
-    cpu_cc_srcT = tcg_temp_local_new();
+    i386_trblock_init_globals(&dc->base, cpu);
 
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 08/29] target/i386: [tcg] Refactor insn_start
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (6 preceding siblings ...)
  2017-06-28 12:44 ` [Qemu-devel] [PATCH v11 07/29] target/i386: [tcg] Refactor init_globals Lluís Vilanova
@ 2017-06-28 12:48 ` Lluís Vilanova
  2017-06-30  0:08   ` Emilio G. Cota
  2017-07-02  0:26   ` Richard Henderson
  2017-06-28 12:52 ` [Qemu-devel] [PATCH v11 09/29] target/i386: [tcg] Refactor breakpoint_check Lluís Vilanova
                   ` (20 subsequent siblings)
  28 siblings, 2 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 12:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/i386/translate.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index d015ea73fa..ad57be2928 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8451,6 +8451,13 @@ static void i386_trblock_init_globals(DisasContextBase *dcbase, CPUState *cpu)
     cpu_cc_srcT = tcg_temp_local_new();
 }
 
+static void i386_trblock_insn_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -8480,7 +8487,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 
     gen_tb_start(tb);
     for(;;) {
-        tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
+        i386_trblock_insn_start(&dc->base, cpu);
         num_insns++;
 
         /* If RF is set, suppress an internally generated breakpoint.  */

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 09/29] target/i386: [tcg] Refactor breakpoint_check
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (7 preceding siblings ...)
  2017-06-28 12:48 ` [Qemu-devel] [PATCH v11 08/29] target/i386: [tcg] Refactor insn_start Lluís Vilanova
@ 2017-06-28 12:52 ` Lluís Vilanova
  2017-06-30  0:24   ` Emilio G. Cota
  2017-07-02  0:28   ` Richard Henderson
  2017-06-28 12:57 ` [Qemu-devel] [PATCH v11 10/29] target/i386: [tcg] Refactor translate_insn Lluís Vilanova
                   ` (19 subsequent siblings)
  28 siblings, 2 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 12:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/i386/translate.c |   59 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index ad57be2928..3eee348de7 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -18,6 +18,7 @@
  */
 #include "qemu/osdep.h"
 
+#include "qemu/error-report.h"
 #include "qemu/host-utils.h"
 #include "cpu.h"
 #include "disas/disas.h"
@@ -8458,6 +8459,25 @@ static void i386_trblock_insn_start(DisasContextBase *dcbase, CPUState *cpu)
     tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
 }
 
+static BreakpointCheckType i386_trblock_breakpoint_check(
+    DisasContextBase *dcbase, CPUState *cpu, const CPUBreakpoint *bp)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    /* If RF is set, suppress an internally generated breakpoint.  */
+    int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
+    if (bp->flags & flags) {
+        gen_debug(dc, dc->base.pc_next - dc->cs_base);
+        /* 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 += 1;
+        return BC_HIT_TB;
+    } else {
+        return BC_MISS;
+    }
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -8490,18 +8510,35 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         i386_trblock_insn_start(&dc->base, cpu);
         num_insns++;
 
-        /* If RF is set, suppress an internally generated breakpoint.  */
-        if (unlikely(cpu_breakpoint_test(cpu, dc->base.pc_next,
-                                         tb->flags & HF_RF_MASK
-                                         ? BP_GDB : BP_ANY))) {
-            gen_debug(dc, dc->base.pc_next - dc->cs_base);
-            /* 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 += 1;
-            goto done_generating;
+        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
+            CPUBreakpoint *bp;
+            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
+                if (bp->pc == dc->base.pc_next) {
+                    BreakpointCheckType bp_check =
+                        i386_trblock_breakpoint_check(&dc->base, cpu, bp);
+                    switch (bp_check) {
+                    case BC_MISS:
+                        /* Target ignored this breakpoint, go to next */
+                        break;
+                    case BC_HIT_INSN:
+                        /* Hit, keep translating */
+                        /*
+                         * TODO: if we're never going to have more than one
+                         *       BP in a single address, we can simply use a
+                         *       bool here.
+                         */
+                        goto done_breakpoints;
+                    case BC_HIT_TB:
+                        /* Hit, end TB */
+                        goto done_generating;
+                    default:
+                        g_assert_not_reached();
+                    }
+                }
+            }
         }
+    done_breakpoints:
+
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
         }

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 10/29] target/i386: [tcg] Refactor translate_insn
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (8 preceding siblings ...)
  2017-06-28 12:52 ` [Qemu-devel] [PATCH v11 09/29] target/i386: [tcg] Refactor breakpoint_check Lluís Vilanova
@ 2017-06-28 12:57 ` Lluís Vilanova
  2017-06-30  0:41   ` Emilio G. Cota
  2017-07-02  0:41   ` Richard Henderson
  2017-06-28 13:01 ` [Qemu-devel] [PATCH v11 11/29] target/i386: [tcg] Refactor tb_stop Lluís Vilanova
                   ` (18 subsequent siblings)
  28 siblings, 2 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 12:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/i386/translate.c |   72 +++++++++++++++++++++++++++++++----------------
 1 file changed, 48 insertions(+), 24 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3eee348de7..da4b409d97 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4420,15 +4420,17 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
 
 /* convert one instruction. s->base.is_jmp is set if the translation must
    be stopped. Return the next pc value */
-static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
-                               target_ulong pc_start)
+static target_ulong disas_insn(DisasContextBase *dcbase, CPUState *cpu)
 {
+    DisasContext *s = container_of(dcbase, DisasContext, base);
+    CPUX86State *env = cpu->env_ptr;
     int b, prefixes;
     int shift;
     TCGMemOp ot, aflag, dflag;
     int modrm, reg, rm, mod, op, opreg, val;
     target_ulong next_eip, tval;
     int rex_w, rex_r;
+    target_ulong pc_start = s->base.pc_next;
 
     s->pc_start = s->pc = pc_start;
     prefixes = 0;
@@ -8478,10 +8480,51 @@ static BreakpointCheckType i386_trblock_breakpoint_check(
     }
 }
 
+static target_ulong i386_trblock_translate_insn(DisasContextBase *dcbase,
+                                                CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    target_ulong pc_next = disas_insn(&dc->base, cpu);
+
+    if (dc->base.is_jmp) {
+        return pc_next;
+    }
+
+    if (dc->tf || (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
+        /* if single step mode, we generate only one instruction and
+           generate an exception */
+        /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
+           the flag and abort the translation to give the irqs a
+           change to be happen */
+        gen_jmp_im(pc_next - dc->cs_base);
+        gen_eob(dc);
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    } else if ((dc->base.tb->cflags & CF_USE_ICOUNT)
+               && ((dc->base.pc_next & TARGET_PAGE_MASK)
+                   != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1)
+                       & TARGET_PAGE_MASK)
+                   || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) {
+        /* Do not cross the boundary of the pages in icount mode,
+           it can cause an exception. Do it only when boundary is
+           crossed by the first instruction in the block.
+           If current instruction already crossed the bound - it's ok,
+           because an exception hasn't stopped this code.
+         */
+        gen_jmp_im(pc_next - dc->cs_base);
+        gen_eob(dc);
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
+        gen_jmp_im(pc_next - dc->cs_base);
+        gen_eob(dc);
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    }
+
+    return pc_next;
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
-    CPUX86State *env = cpu->env_ptr;
     DisasContext dc1, *dc = &dc1;
     int num_insns;
     int max_insns;
@@ -8543,39 +8586,20 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             gen_io_start();
         }
 
-        dc->base.pc_next = disas_insn(env, dc, dc->base.pc_next);
+        dc->base.pc_next = i386_trblock_translate_insn(&dc->base, cpu);
         /* stop translation if indicated */
         if (dc->base.is_jmp) {
             break;
         }
         /* if single step mode, we generate only one instruction and
            generate an exception */
-        /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
-           the flag and abort the translation to give the irqs a
-           change to be happen */
-        if (dc->tf || dc->base.singlestep_enabled ||
-            (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
-            gen_jmp_im(dc->base.pc_next - dc->cs_base);
-            gen_eob(dc);
-            break;
-        }
-        /* Do not cross the boundary of the pages in icount mode,
-           it can cause an exception. Do it only when boundary is
-           crossed by the first instruction in the block.
-           If current instruction already crossed the bound - it's ok,
-           because an exception hasn't stopped this code.
-         */
-        if ((tb->cflags & CF_USE_ICOUNT)
-            && ((dc->base.pc_next & TARGET_PAGE_MASK)
-                != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
-                || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) {
+        if (dc->base.singlestep_enabled) {
             gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
         /* if too long translation, stop generation too */
         if (tcg_op_buf_full() ||
-            (dc->base.pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32) ||
             num_insns >= max_insns) {
             gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 11/29] target/i386: [tcg] Refactor tb_stop
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (9 preceding siblings ...)
  2017-06-28 12:57 ` [Qemu-devel] [PATCH v11 10/29] target/i386: [tcg] Refactor translate_insn Lluís Vilanova
@ 2017-06-28 13:01 ` Lluís Vilanova
  2017-06-30  0:47   ` Emilio G. Cota
  2017-07-02  0:47   ` Richard Henderson
  2017-06-28 13:05 ` [Qemu-devel] [PATCH v11 12/29] target/i386: [tcg] Refactor disas_log Lluís Vilanova
                   ` (17 subsequent siblings)
  28 siblings, 2 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/i386/translate.c |   26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index da4b409d97..1ca40c2fe4 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8496,8 +8496,6 @@ static target_ulong i386_trblock_translate_insn(DisasContextBase *dcbase,
         /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
            the flag and abort the translation to give the irqs a
            change to be happen */
-        gen_jmp_im(pc_next - dc->cs_base);
-        gen_eob(dc);
         dc->base.is_jmp = DISAS_TOO_MANY;
     } else if ((dc->base.tb->cflags & CF_USE_ICOUNT)
                && ((dc->base.pc_next & TARGET_PAGE_MASK)
@@ -8510,18 +8508,24 @@ static target_ulong i386_trblock_translate_insn(DisasContextBase *dcbase,
            If current instruction already crossed the bound - it's ok,
            because an exception hasn't stopped this code.
          */
-        gen_jmp_im(pc_next - dc->cs_base);
-        gen_eob(dc);
         dc->base.is_jmp = DISAS_TOO_MANY;
     } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
-        gen_jmp_im(pc_next - dc->cs_base);
-        gen_eob(dc);
         dc->base.is_jmp = DISAS_TOO_MANY;
     }
 
     return pc_next;
 }
 
+static void i386_trblock_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    if (dc->base.is_jmp == DISAS_TOO_MANY) {
+        gen_jmp_im(dc->base.pc_next - dc->cs_base);
+        gen_eob(dc);
+    }
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -8594,23 +8598,21 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         /* if single step mode, we generate only one instruction and
            generate an exception */
         if (dc->base.singlestep_enabled) {
-            gen_jmp_im(dc->base.pc_next - dc->cs_base);
-            gen_eob(dc);
+            dc->base.is_jmp = DISAS_TOO_MANY;
             break;
         }
         /* if too long translation, stop generation too */
         if (tcg_op_buf_full() ||
             num_insns >= max_insns) {
-            gen_jmp_im(dc->base.pc_next - dc->cs_base);
-            gen_eob(dc);
+            dc->base.is_jmp = DISAS_TOO_MANY;
             break;
         }
         if (singlestep) {
-            gen_jmp_im(dc->base.pc_next - dc->cs_base);
-            gen_eob(dc);
+            dc->base.is_jmp = DISAS_TOO_MANY;
             break;
         }
     }
+    i386_trblock_tb_stop(&dc->base, cpu);
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
 done_generating:

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 12/29] target/i386: [tcg] Refactor disas_log
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (10 preceding siblings ...)
  2017-06-28 13:01 ` [Qemu-devel] [PATCH v11 11/29] target/i386: [tcg] Refactor tb_stop Lluís Vilanova
@ 2017-06-28 13:05 ` Lluís Vilanova
  2017-06-30  0:50   ` Emilio G. Cota
  2017-07-02  0:49   ` Richard Henderson
  2017-06-28 13:09 ` [Qemu-devel] [PATCH v11 13/29] target/i386: [tcg] Port to generic translation framework Lluís Vilanova
                   ` (16 subsequent siblings)
  28 siblings, 2 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/i386/translate.c |   29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 1ca40c2fe4..3950fe95a4 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8526,6 +8526,24 @@ static void i386_trblock_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
     }
 }
 
+static void i386_trblock_disas_log(const DisasContextBase *dcbase,
+                                   CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    int disas_flags;
+
+    qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
+#ifdef TARGET_X86_64
+    if (dc->code64)
+        disas_flags = 2;
+    else
+#endif
+        disas_flags = !dc->code32;
+    log_target_disas(cpu, dc->base.pc_first, dc->base.pc_next - dc->base.pc_first,
+                     disas_flags);
+
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -8621,18 +8639,9 @@ done_generating:
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
         && qemu_log_in_addr_range(dc->base.pc_first)) {
-        int disas_flags;
         qemu_log_lock();
         qemu_log("----------------\n");
-        qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
-#ifdef TARGET_X86_64
-        if (dc->code64)
-            disas_flags = 2;
-        else
-#endif
-            disas_flags = !dc->code32;
-        log_target_disas(cpu, dc->base.pc_first, dc->base.pc_next - dc->base.pc_first,
-                         disas_flags);
+        i386_trblock_disas_log(&dc->base, cpu);
         qemu_log("\n");
         qemu_log_unlock();
     }

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 13/29] target/i386: [tcg] Port to generic translation framework
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (11 preceding siblings ...)
  2017-06-28 13:05 ` [Qemu-devel] [PATCH v11 12/29] target/i386: [tcg] Refactor disas_log Lluís Vilanova
@ 2017-06-28 13:09 ` Lluís Vilanova
  2017-06-30  1:11   ` Emilio G. Cota
  2017-07-02  0:52   ` Richard Henderson
  2017-06-28 13:13 ` [Qemu-devel] [PATCH v11 14/29] target/arm: [tcg] Port to DisasContextBase Lluís Vilanova
                   ` (15 subsequent siblings)
  28 siblings, 2 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/i386/translate.c |  120 +++++++----------------------------------------
 1 file changed, 18 insertions(+), 102 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3950fe95a4..295be26a95 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8454,6 +8454,10 @@ static void i386_trblock_init_globals(DisasContextBase *dcbase, CPUState *cpu)
     cpu_cc_srcT = tcg_temp_local_new();
 }
 
+static void i386_trblock_tb_start(DisasContextBase *db, CPUState *cpu)
+{
+}
+
 static void i386_trblock_insn_start(DisasContextBase *dcbase, CPUState *cpu)
 {
     DisasContext *dc = container_of(dcbase, DisasContext, base);
@@ -8472,7 +8476,7 @@ static BreakpointCheckType i386_trblock_breakpoint_check(
         /* 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.  */
+           the generic logic setting tb->size later does the right thing.  */
         dc->base.pc_next += 1;
         return BC_HIT_TB;
     } else {
@@ -8544,111 +8548,23 @@ static void i386_trblock_disas_log(const DisasContextBase *dcbase,
 
 }
 
+static const TranslatorOps i386_trblock_ops = {
+    .init_disas_context = i386_trblock_init_disas_context,
+    .init_globals = i386_trblock_init_globals,
+    .tb_start = i386_trblock_tb_start,
+    .insn_start = i386_trblock_insn_start,
+    .breakpoint_check = i386_trblock_breakpoint_check,
+    .translate_insn = i386_trblock_translate_insn,
+    .tb_stop = i386_trblock_tb_stop,
+    .disas_log = i386_trblock_disas_log,
+};
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
-    DisasContext dc1, *dc = &dc1;
-    int num_insns;
-    int max_insns;
-
-    /* generate intermediate code */
-    dc->base.singlestep_enabled = cpu->singlestep_enabled;
-    dc->base.tb = tb;
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.pc_first = tb->pc;
-    dc->base.pc_next = dc->base.pc_first;
-    i386_trblock_init_disas_context(&dc->base, cpu);
-
-    i386_trblock_init_globals(&dc->base, cpu);
-
-    num_insns = 0;
-    max_insns = tb->cflags & CF_COUNT_MASK;
-    if (max_insns == 0) {
-        max_insns = CF_COUNT_MASK;
-    }
-    if (max_insns > TCG_MAX_INSNS) {
-        max_insns = TCG_MAX_INSNS;
-    }
-
-    gen_tb_start(tb);
-    for(;;) {
-        i386_trblock_insn_start(&dc->base, cpu);
-        num_insns++;
-
-        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
-            CPUBreakpoint *bp;
-            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
-                if (bp->pc == dc->base.pc_next) {
-                    BreakpointCheckType bp_check =
-                        i386_trblock_breakpoint_check(&dc->base, cpu, bp);
-                    switch (bp_check) {
-                    case BC_MISS:
-                        /* Target ignored this breakpoint, go to next */
-                        break;
-                    case BC_HIT_INSN:
-                        /* Hit, keep translating */
-                        /*
-                         * TODO: if we're never going to have more than one
-                         *       BP in a single address, we can simply use a
-                         *       bool here.
-                         */
-                        goto done_breakpoints;
-                    case BC_HIT_TB:
-                        /* Hit, end TB */
-                        goto done_generating;
-                    default:
-                        g_assert_not_reached();
-                    }
-                }
-            }
-        }
-    done_breakpoints:
-
-        if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
-        }
-
-        dc->base.pc_next = i386_trblock_translate_insn(&dc->base, cpu);
-        /* stop translation if indicated */
-        if (dc->base.is_jmp) {
-            break;
-        }
-        /* if single step mode, we generate only one instruction and
-           generate an exception */
-        if (dc->base.singlestep_enabled) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-            break;
-        }
-        /* if too long translation, stop generation too */
-        if (tcg_op_buf_full() ||
-            num_insns >= max_insns) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-            break;
-        }
-        if (singlestep) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-            break;
-        }
-    }
-    i386_trblock_tb_stop(&dc->base, cpu);
-    if (tb->cflags & CF_LAST_IO)
-        gen_io_end();
-done_generating:
-    gen_tb_end(tb, num_insns);
-
-#ifdef DEBUG_DISAS
-    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
-        && qemu_log_in_addr_range(dc->base.pc_first)) {
-        qemu_log_lock();
-        qemu_log("----------------\n");
-        i386_trblock_disas_log(&dc->base, cpu);
-        qemu_log("\n");
-        qemu_log_unlock();
-    }
-#endif
+    DisasContext dc1;
 
-    tb->size = dc->base.pc_next - dc->base.pc_first;
-    tb->icount = num_insns;
+    translate_block(&i386_trblock_ops, &dc1.base, cpu, tb);
 }
 
 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 14/29] target/arm: [tcg] Port to DisasContextBase
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (12 preceding siblings ...)
  2017-06-28 13:09 ` [Qemu-devel] [PATCH v11 13/29] target/i386: [tcg] Port to generic translation framework Lluís Vilanova
@ 2017-06-28 13:13 ` Lluís Vilanova
  2017-07-02  1:00   ` Richard Henderson
  2017-06-28 13:17 ` [Qemu-devel] [PATCH v11 15/29] target/arm: [tcg] Port to init_disas_context Lluís Vilanova
                   ` (14 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate-a64.c |  119 ++++++++++++++++++++++----------------------
 target/arm/translate.c     |  114 +++++++++++++++++++++---------------------
 target/arm/translate.h     |   11 ++--
 3 files changed, 121 insertions(+), 123 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index f9bd1a9679..4270ac3847 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -304,7 +304,7 @@ static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
 {
     gen_a64_set_pc_im(s->pc - offset);
     gen_exception_internal(excp);
-    s->is_jmp = DISAS_EXC;
+    s->base.is_jmp = DISAS_EXC;
 }
 
 static void gen_exception_insn(DisasContext *s, int offset, int excp,
@@ -312,7 +312,7 @@ static void gen_exception_insn(DisasContext *s, int offset, int excp,
 {
     gen_a64_set_pc_im(s->pc - offset);
     gen_exception(excp, syndrome, target_el);
-    s->is_jmp = DISAS_EXC;
+    s->base.is_jmp = DISAS_EXC;
 }
 
 static void gen_ss_advance(DisasContext *s)
@@ -340,7 +340,7 @@ static void gen_step_complete_exception(DisasContext *s)
     gen_ss_advance(s);
     gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
                   default_exception_el(s));
-    s->is_jmp = DISAS_EXC;
+    s->base.is_jmp = DISAS_EXC;
 }
 
 static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
@@ -348,13 +348,13 @@ static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
     /* No direct tb linking with singlestep (either QEMU's or the ARM
      * debug architecture kind) or deterministic io
      */
-    if (s->singlestep_enabled || s->ss_active || (s->tb->cflags & CF_LAST_IO)) {
+    if (s->base.singlestep_enabled || s->ss_active || (s->base.tb->cflags & CF_LAST_IO)) {
         return false;
     }
 
 #ifndef CONFIG_USER_ONLY
     /* Only link tbs from inside the same guest page */
-    if ((s->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
+    if ((s->base.tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
         return false;
     }
 #endif
@@ -366,21 +366,21 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
 {
     TranslationBlock *tb;
 
-    tb = s->tb;
+    tb = s->base.tb;
     if (use_goto_tb(s, n, dest)) {
         tcg_gen_goto_tb(n);
         gen_a64_set_pc_im(dest);
         tcg_gen_exit_tb((intptr_t)tb + n);
-        s->is_jmp = DISAS_TB_JUMP;
+        s->base.is_jmp = DISAS_TB_JUMP;
     } else {
         gen_a64_set_pc_im(dest);
         if (s->ss_active) {
             gen_step_complete_exception(s);
-        } else if (s->singlestep_enabled) {
+        } else if (s->base.singlestep_enabled) {
             gen_exception_internal(EXCP_DEBUG);
         } else {
             tcg_gen_lookup_and_goto_ptr(cpu_pc);
-            s->is_jmp = DISAS_TB_JUMP;
+            s->base.is_jmp = DISAS_TB_JUMP;
         }
     }
 }
@@ -1331,16 +1331,16 @@ static void handle_hint(DisasContext *s, uint32_t insn,
     case 0: /* NOP */
         return;
     case 3: /* WFI */
-        s->is_jmp = DISAS_WFI;
+        s->base.is_jmp = DISAS_WFI;
         return;
     case 1: /* YIELD */
         if (!parallel_cpus) {
-            s->is_jmp = DISAS_YIELD;
+            s->base.is_jmp = DISAS_YIELD;
         }
         return;
     case 2: /* WFE */
         if (!parallel_cpus) {
-            s->is_jmp = DISAS_WFE;
+            s->base.is_jmp = DISAS_WFE;
         }
         return;
     case 4: /* SEV */
@@ -1393,7 +1393,7 @@ static void handle_sync(DisasContext *s, uint32_t insn,
          * a self-modified code correctly and also to take
          * any pending interrupts immediately.
          */
-        s->is_jmp = DISAS_UPDATE;
+        s->base.is_jmp = DISAS_UPDATE;
         return;
     default:
         unallocated_encoding(s);
@@ -1424,7 +1424,7 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
         tcg_temp_free_i32(tcg_op);
         /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs.  */
         gen_a64_set_pc_im(s->pc);
-        s->is_jmp = (op == 0x1f ? DISAS_EXIT : DISAS_JUMP);
+        s->base.is_jmp = (op == 0x1f ? DISAS_EXIT : DISAS_JUMP);
         break;
     }
     default:
@@ -1559,7 +1559,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
         break;
     }
 
-    if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
+    if ((s->base.tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
         gen_io_start();
     }
 
@@ -1590,16 +1590,16 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
         }
     }
 
-    if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
+    if ((s->base.tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
         /* I/O operations must end the TB here (whether read or write) */
         gen_io_end();
-        s->is_jmp = DISAS_UPDATE;
+        s->base.is_jmp = DISAS_UPDATE;
     } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
         /* We default to ending the TB on a coprocessor register write,
          * but allow this to be suppressed by the register definition
          * (usually only necessary to work around guest bugs).
          */
-        s->is_jmp = DISAS_UPDATE;
+        s->base.is_jmp = DISAS_UPDATE;
     }
 }
 
@@ -1788,7 +1788,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
             return;
         }
         gen_helper_exception_return(cpu_env);
-        s->is_jmp = DISAS_JUMP;
+        s->base.is_jmp = DISAS_JUMP;
         return;
     case 5: /* DRPS */
         if (rn != 0x1f) {
@@ -1802,7 +1802,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
         return;
     }
 
-    s->is_jmp = DISAS_JUMP;
+    s->base.is_jmp = DISAS_JUMP;
 }
 
 /* C3.2 Branches, exception generating and system instructions */
@@ -11190,23 +11190,23 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
     free_tmp_a64(s);
 }
 
-void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
+void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
+                               TranslationBlock *tb)
 {
     CPUARMState *env = cs->env_ptr;
     ARMCPU *cpu = arm_env_get_cpu(env);
-    DisasContext dc1, *dc = &dc1;
-    target_ulong pc_start;
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
     target_ulong next_page_start;
-    int num_insns;
     int max_insns;
 
-    pc_start = tb->pc;
+    dc->base.tb = tb;
+    dc->base.pc_first = dc->base.tb->pc;
+    dc->base.pc_next = dc->base.pc_first;
+    dc->base.is_jmp = DISAS_NEXT;
+    dc->base.num_insns = 0;
+    dc->base.singlestep_enabled = cs->singlestep_enabled;
 
-    dc->tb = tb;
-
-    dc->is_jmp = DISAS_NEXT;
-    dc->pc = pc_start;
-    dc->singlestep_enabled = cs->singlestep_enabled;
+    dc->pc = dc->base.pc_first;
     dc->condjmp = 0;
 
     dc->aarch64 = 1;
@@ -11217,17 +11217,17 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
                                !arm_el_is_aa64(env, 3);
     dc->thumb = 0;
     dc->sctlr_b = 0;
-    dc->be_data = ARM_TBFLAG_BE_DATA(tb->flags) ? MO_BE : MO_LE;
+    dc->be_data = ARM_TBFLAG_BE_DATA(dc->base.tb->flags) ? MO_BE : MO_LE;
     dc->condexec_mask = 0;
     dc->condexec_cond = 0;
-    dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(tb->flags));
-    dc->tbi0 = ARM_TBFLAG_TBI0(tb->flags);
-    dc->tbi1 = ARM_TBFLAG_TBI1(tb->flags);
+    dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags));
+    dc->tbi0 = ARM_TBFLAG_TBI0(dc->base.tb->flags);
+    dc->tbi1 = ARM_TBFLAG_TBI1(dc->base.tb->flags);
     dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
 #if !defined(CONFIG_USER_ONLY)
     dc->user = (dc->current_el == 0);
 #endif
-    dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(tb->flags);
+    dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
     dc->vec_len = 0;
     dc->vec_stride = 0;
     dc->cp_regs = cpu->cp_regs;
@@ -11248,16 +11248,15 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
      *   emit code to generate a software step exception
      *   end the TB
      */
-    dc->ss_active = ARM_TBFLAG_SS_ACTIVE(tb->flags);
-    dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(tb->flags);
+    dc->ss_active = ARM_TBFLAG_SS_ACTIVE(dc->base.tb->flags);
+    dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(dc->base.tb->flags);
     dc->is_ldex = false;
     dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
 
     init_tmp_a64_array(dc);
 
-    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
-    num_insns = 0;
-    max_insns = tb->cflags & CF_COUNT_MASK;
+    next_page_start = (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+    max_insns = dc->base.tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
         max_insns = CF_COUNT_MASK;
     }
@@ -11270,9 +11269,9 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
     tcg_clear_temp_count();
 
     do {
+        dc->base.num_insns++;
         dc->insn_start_idx = tcg_op_buf_count();
         tcg_gen_insn_start(dc->pc, 0, 0);
-        num_insns++;
 
         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
             CPUBreakpoint *bp;
@@ -11282,14 +11281,14 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
                         gen_a64_set_pc_im(dc->pc);
                         gen_helper_check_breakpoints(cpu_env);
                         /* End the TB early; it likely won't be executed */
-                        dc->is_jmp = DISAS_UPDATE;
+                        dc->base.is_jmp = DISAS_UPDATE;
                     } else {
                         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
                         /* The address covered by the breakpoint must be
-                           included in [tb->pc, tb->pc + tb->size) in order
+                           included in [dc->base.tb->pc, dc->base.tb->pc + dc->base.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.tb->size below does the right thing.  */
                         dc->pc += 4;
                         goto done_generating;
                     }
@@ -11298,7 +11297,7 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
             }
         }
 
-        if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
+        if (dc->base.num_insns == max_insns && (dc->base.tb->cflags & CF_LAST_IO)) {
             gen_io_start();
         }
 
@@ -11313,10 +11312,10 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
              * "did not step an insn" case, and so the syndrome ISV and EX
              * bits should be zero.
              */
-            assert(num_insns == 1);
+            assert(dc->base.num_insns == 1);
             gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
                           default_exception_el(dc));
-            dc->is_jmp = DISAS_EXC;
+            dc->base.is_jmp = DISAS_EXC;
             break;
         }
 
@@ -11332,26 +11331,26 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
          * Also stop translation when a page boundary is reached.  This
          * ensures prefetch aborts occur at the right place.
          */
-    } while (!dc->is_jmp && !tcg_op_buf_full() &&
+    } while (!dc->base.is_jmp && !tcg_op_buf_full() &&
              !cs->singlestep_enabled &&
              !singlestep &&
              !dc->ss_active &&
              dc->pc < next_page_start &&
-             num_insns < max_insns);
+             dc->base.num_insns < max_insns);
 
-    if (tb->cflags & CF_LAST_IO) {
+    if (dc->base.tb->cflags & CF_LAST_IO) {
         gen_io_end();
     }
 
     if (unlikely(cs->singlestep_enabled || dc->ss_active)
-        && dc->is_jmp != DISAS_EXC) {
+        && dc->base.is_jmp != DISAS_EXC) {
         /* Note that this means single stepping WFI doesn't halt the CPU.
          * For conditional branch insns this is harmless unreachable code as
          * gen_goto_tb() has already handled emitting the debug exception
          * (and thus a tb-jump is not possible when singlestepping).
          */
-        assert(dc->is_jmp != DISAS_TB_JUMP);
-        if (dc->is_jmp != DISAS_JUMP) {
+        assert(dc->base.is_jmp != DISAS_TB_JUMP);
+        if (dc->base.is_jmp != DISAS_JUMP) {
             gen_a64_set_pc_im(dc->pc);
         }
         if (cs->singlestep_enabled) {
@@ -11360,7 +11359,7 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
             gen_step_complete_exception(dc);
         }
     } else {
-        switch (dc->is_jmp) {
+        switch (dc->base.is_jmp) {
         case DISAS_NEXT:
             gen_goto_tb(dc, 1, dc->pc);
             break;
@@ -11401,20 +11400,20 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
     }
 
 done_generating:
-    gen_tb_end(tb, num_insns);
+    gen_tb_end(tb, dc->base.num_insns);
 
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
-        qemu_log_in_addr_range(pc_start)) {
+        qemu_log_in_addr_range(dc->base.pc_first)) {
         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("IN: %s\n", lookup_symbol(dc->base.pc_first));
+        log_target_disas(cs, dc->base.pc_first, dc->pc - dc->base.pc_first,
                          4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
         qemu_log("\n");
         qemu_log_unlock();
     }
 #endif
-    tb->size = dc->pc - pc_start;
-    tb->icount = num_insns;
+    dc->base.tb->size = dc->pc - dc->base.pc_first;
+    dc->base.tb->icount = dc->base.num_insns;
 }
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 032a263604..17bc9687b7 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -224,7 +224,7 @@ static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
          * We choose to ignore [1:0] in ARM mode for all architecture versions.
          */
         tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
-        s->is_jmp = DISAS_JUMP;
+        s->base.is_jmp = DISAS_JUMP;
     }
     tcg_gen_mov_i32(cpu_R[reg], var);
     tcg_temp_free_i32(var);
@@ -297,7 +297,7 @@ static void gen_step_complete_exception(DisasContext *s)
     gen_ss_advance(s);
     gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
                   default_exception_el(s));
-    s->is_jmp = DISAS_EXC;
+    s->base.is_jmp = DISAS_EXC;
 }
 
 static void gen_singlestep_exception(DisasContext *s)
@@ -321,7 +321,7 @@ static inline bool is_singlestepping(DisasContext *s)
      * misnamed as it only means "one instruction per TB" and doesn't
      * affect the code we generate.
      */
-    return s->singlestep_enabled || s->ss_active;
+    return s->base.singlestep_enabled || s->ss_active;
 }
 
 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
@@ -928,7 +928,7 @@ static inline void gen_bx_im(DisasContext *s, uint32_t addr)
 {
     TCGv_i32 tmp;
 
-    s->is_jmp = DISAS_JUMP;
+    s->base.is_jmp = DISAS_JUMP;
     if (s->thumb != (addr & 1)) {
         tmp = tcg_temp_new_i32();
         tcg_gen_movi_i32(tmp, addr & 1);
@@ -941,7 +941,7 @@ static inline void gen_bx_im(DisasContext *s, uint32_t addr)
 /* Set PC and Thumb state from var.  var is marked as dead.  */
 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
 {
-    s->is_jmp = DISAS_JUMP;
+    s->base.is_jmp = DISAS_JUMP;
     tcg_gen_andi_i32(cpu_R[15], var, ~1);
     tcg_gen_andi_i32(var, var, 1);
     store_cpu_field(var, thumb);
@@ -955,11 +955,11 @@ static inline void gen_bx(DisasContext *s, TCGv_i32 var)
 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
 {
     /* Generate the same code here as for a simple bx, but flag via
-     * s->is_jmp that we need to do the rest of the work later.
+     * s->base.is_jmp that we need to do the rest of the work later.
      */
     gen_bx(s, var);
     if (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M)) {
-        s->is_jmp = DISAS_BX_EXCRET;
+        s->base.is_jmp = DISAS_BX_EXCRET;
     }
 }
 
@@ -1159,7 +1159,7 @@ static inline void gen_hvc(DisasContext *s, int imm16)
      */
     s->svc_imm = imm16;
     gen_set_pc_im(s, s->pc);
-    s->is_jmp = DISAS_HVC;
+    s->base.is_jmp = DISAS_HVC;
 }
 
 static inline void gen_smc(DisasContext *s)
@@ -1174,7 +1174,7 @@ static inline void gen_smc(DisasContext *s)
     gen_helper_pre_smc(cpu_env, tmp);
     tcg_temp_free_i32(tmp);
     gen_set_pc_im(s, s->pc);
-    s->is_jmp = DISAS_SMC;
+    s->base.is_jmp = DISAS_SMC;
 }
 
 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
@@ -1182,7 +1182,7 @@ static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
     gen_set_condexec(s);
     gen_set_pc_im(s, s->pc - offset);
     gen_exception_internal(excp);
-    s->is_jmp = DISAS_EXC;
+    s->base.is_jmp = DISAS_EXC;
 }
 
 static void gen_exception_insn(DisasContext *s, int offset, int excp,
@@ -1191,14 +1191,14 @@ static void gen_exception_insn(DisasContext *s, int offset, int excp,
     gen_set_condexec(s);
     gen_set_pc_im(s, s->pc - offset);
     gen_exception(excp, syn, target_el);
-    s->is_jmp = DISAS_EXC;
+    s->base.is_jmp = DISAS_EXC;
 }
 
 /* Force a TB lookup after an instruction that changes the CPU state.  */
 static inline void gen_lookup_tb(DisasContext *s)
 {
     tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
-    s->is_jmp = DISAS_EXIT;
+    s->base.is_jmp = DISAS_EXIT;
 }
 
 static inline void gen_hlt(DisasContext *s, int imm)
@@ -4143,7 +4143,7 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
 static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
 {
 #ifndef CONFIG_USER_ONLY
-    return (s->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
+    return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
            ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
 #else
     return true;
@@ -4163,7 +4163,7 @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
     if (use_goto_tb(s, dest)) {
         tcg_gen_goto_tb(n);
         gen_set_pc_im(s, dest);
-        tcg_gen_exit_tb((uintptr_t)s->tb + n);
+        tcg_gen_exit_tb((uintptr_t)s->base.tb + n);
     } else {
         gen_set_pc_im(s, dest);
         gen_goto_ptr();
@@ -4179,7 +4179,7 @@ static inline void gen_jmp (DisasContext *s, uint32_t dest)
         gen_bx_im(s, dest);
     } else {
         gen_goto_tb(s, 0, dest);
-        s->is_jmp = DISAS_TB_JUMP;
+        s->base.is_jmp = DISAS_TB_JUMP;
     }
 }
 
@@ -4430,7 +4430,7 @@ static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
     tcg_temp_free_i32(tcg_tgtmode);
     tcg_temp_free_i32(tcg_regno);
     tcg_temp_free_i32(tcg_reg);
-    s->is_jmp = DISAS_UPDATE;
+    s->base.is_jmp = DISAS_UPDATE;
 }
 
 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
@@ -4452,7 +4452,7 @@ static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
     tcg_temp_free_i32(tcg_tgtmode);
     tcg_temp_free_i32(tcg_regno);
     store_reg(s, rn, tcg_reg);
-    s->is_jmp = DISAS_UPDATE;
+    s->base.is_jmp = DISAS_UPDATE;
 }
 
 /* Store value to PC as for an exception return (ie don't
@@ -4475,7 +4475,7 @@ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
      */
     gen_helper_cpsr_write_eret(cpu_env, cpsr);
     tcg_temp_free_i32(cpsr);
-    s->is_jmp = DISAS_JUMP;
+    s->base.is_jmp = DISAS_JUMP;
 }
 
 /* Generate an old-style exception return. Marks pc as dead. */
@@ -4498,17 +4498,17 @@ static void gen_nop_hint(DisasContext *s, int val)
     case 1: /* yield */
         if (!parallel_cpus) {
             gen_set_pc_im(s, s->pc);
-            s->is_jmp = DISAS_YIELD;
+            s->base.is_jmp = DISAS_YIELD;
         }
         break;
     case 3: /* wfi */
         gen_set_pc_im(s, s->pc);
-        s->is_jmp = DISAS_WFI;
+        s->base.is_jmp = DISAS_WFI;
         break;
     case 2: /* wfe */
         if (!parallel_cpus) {
             gen_set_pc_im(s, s->pc);
-            s->is_jmp = DISAS_WFE;
+            s->base.is_jmp = DISAS_WFE;
         }
         break;
     case 4: /* sev */
@@ -7647,13 +7647,13 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
                 return 1;
             }
             gen_set_pc_im(s, s->pc);
-            s->is_jmp = DISAS_WFI;
+            s->base.is_jmp = DISAS_WFI;
             return 0;
         default:
             break;
         }
 
-        if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
+        if ((s->base.tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
             gen_io_start();
         }
 
@@ -7744,7 +7744,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
             }
         }
 
-        if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
+        if ((s->base.tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
             /* I/O operations must end the TB here (whether read or write) */
             gen_io_end();
             gen_lookup_tb(s);
@@ -8058,7 +8058,7 @@ static void gen_srs(DisasContext *s,
         tcg_temp_free_i32(tmp);
     }
     tcg_temp_free_i32(addr);
-    s->is_jmp = DISAS_UPDATE;
+    s->base.is_jmp = DISAS_UPDATE;
 }
 
 static void disas_arm_insn(DisasContext *s, unsigned int insn)
@@ -8146,7 +8146,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
             /* setend */
             if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
                 gen_helper_setend(cpu_env);
-                s->is_jmp = DISAS_UPDATE;
+                s->base.is_jmp = DISAS_UPDATE;
             }
             return;
         } else if ((insn & 0x0fffff00) == 0x057ff000) {
@@ -9519,7 +9519,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
                     tmp = load_cpu_field(spsr);
                     gen_helper_cpsr_write_eret(cpu_env, tmp);
                     tcg_temp_free_i32(tmp);
-                    s->is_jmp = DISAS_JUMP;
+                    s->base.is_jmp = DISAS_JUMP;
                 }
             }
             break;
@@ -9557,7 +9557,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
             /* swi */
             gen_set_pc_im(s, s->pc);
             s->svc_imm = extract32(insn, 0, 24);
-            s->is_jmp = DISAS_SWI;
+            s->base.is_jmp = DISAS_SWI;
             break;
         default:
         illegal_op:
@@ -11619,7 +11619,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
                 ARCH(6);
                 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
                     gen_helper_setend(cpu_env);
-                    s->is_jmp = DISAS_UPDATE;
+                    s->base.is_jmp = DISAS_UPDATE;
                 }
                 break;
             case 3:
@@ -11713,7 +11713,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
             /* swi */
             gen_set_pc_im(s, s->pc);
             s->svc_imm = extract32(insn, 0, 8);
-            s->is_jmp = DISAS_SWI;
+            s->base.is_jmp = DISAS_SWI;
             break;
         }
         /* generate a conditional jump to next instruction */
@@ -11792,9 +11792,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     CPUARMState *env = cpu->env_ptr;
     ARMCPU *arm_cpu = arm_env_get_cpu(env);
     DisasContext dc1, *dc = &dc1;
-    target_ulong pc_start;
     target_ulong next_page_start;
-    int num_insns;
     int max_insns;
     bool end_of_page;
 
@@ -11804,17 +11802,18 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
      * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
      */
     if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
-        gen_intermediate_code_a64(cpu, tb);
+        gen_intermediate_code_a64(&dc->base, cpu, tb);
         return;
     }
 
-    pc_start = tb->pc;
+    dc->base.tb = tb;
+    dc->base.pc_first = tb->pc;
+    dc->base.pc_next = dc->base.pc_first;
+    dc->base.is_jmp = DISAS_NEXT;
+    dc->base.num_insns = 0;
+    dc->base.singlestep_enabled = cpu->singlestep_enabled;
 
-    dc->tb = tb;
-
-    dc->is_jmp = DISAS_NEXT;
-    dc->pc = pc_start;
-    dc->singlestep_enabled = cpu->singlestep_enabled;
+    dc->pc = dc->base.pc_first;
     dc->condjmp = 0;
 
     dc->aarch64 = 0;
@@ -11871,8 +11870,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     cpu_V1 = cpu_F1d;
     /* FIXME: cpu_M0 can probably be the same as cpu_V0.  */
     cpu_M0 = tcg_temp_new_i64();
-    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
-    num_insns = 0;
+    next_page_start = (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
         max_insns = CF_COUNT_MASK;
@@ -11924,11 +11922,11 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         store_cpu_field(tmp, condexec_bits);
       }
     do {
+        dc->base.num_insns++;
         dc->insn_start_idx = tcg_op_buf_count();
         tcg_gen_insn_start(dc->pc,
                            (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
                            0);
-        num_insns++;
 
 #ifdef CONFIG_USER_ONLY
         /* Intercept jump to the magic kernel page.  */
@@ -11936,7 +11934,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             /* We always get here via a jump, so know we are not in a
                conditional execution block.  */
             gen_exception_internal(EXCP_KERNEL_TRAP);
-            dc->is_jmp = DISAS_EXC;
+            dc->base.is_jmp = DISAS_EXC;
             break;
         }
 #endif
@@ -11950,7 +11948,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
                         gen_set_pc_im(dc, dc->pc);
                         gen_helper_check_breakpoints(cpu_env);
                         /* End the TB early; it's likely not going to be executed */
-                        dc->is_jmp = DISAS_UPDATE;
+                        dc->base.is_jmp = DISAS_UPDATE;
                     } else {
                         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
                         /* The address covered by the breakpoint must be
@@ -11968,7 +11966,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             }
         }
 
-        if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
+        if (dc->base.num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
         }
 
@@ -11983,7 +11981,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
              * "did not step an insn" case, and so the syndrome ISV and EX
              * bits should be zero.
              */
-            assert(num_insns == 1);
+            assert(dc->base.num_insns == 1);
             gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
                           default_exception_el(dc));
             goto done_generating;
@@ -12005,7 +12003,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             disas_arm_insn(dc, insn);
         }
 
-        if (dc->condjmp && !dc->is_jmp) {
+        if (dc->condjmp && !dc->base.is_jmp) {
             gen_set_label(dc->condlabel);
             dc->condjmp = 0;
         }
@@ -12032,11 +12030,11 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         end_of_page = (dc->pc >= next_page_start) ||
             ((dc->pc >= next_page_start - 3) && insn_crosses_page(env, dc));
 
-    } while (!dc->is_jmp && !tcg_op_buf_full() &&
+    } while (!dc->base.is_jmp && !tcg_op_buf_full() &&
              !is_singlestepping(dc) &&
              !singlestep &&
              !end_of_page &&
-             num_insns < max_insns);
+             dc->base.num_insns < max_insns);
 
     if (tb->cflags & CF_LAST_IO) {
         if (dc->condjmp) {
@@ -12051,7 +12049,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
        instruction was a conditional branch or trap, and the PC has
        already been written.  */
     gen_set_condexec(dc);
-    if (dc->is_jmp == DISAS_BX_EXCRET) {
+    if (dc->base.is_jmp == DISAS_BX_EXCRET) {
         /* Exception return branches need some special case code at the
          * end of the TB, which is complex enough that it has to
          * handle the single-step vs not and the condition-failed
@@ -12060,7 +12058,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         gen_bx_excret_final_code(dc);
     } else if (unlikely(is_singlestepping(dc))) {
         /* Unconditional and "condition passed" instruction codepath. */
-        switch (dc->is_jmp) {
+        switch (dc->base.is_jmp) {
         case DISAS_SWI:
             gen_ss_advance(dc);
             gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
@@ -12091,7 +12089,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             - Hardware watchpoints.
            Hardware breakpoints have already been handled and skip this code.
          */
-        switch(dc->is_jmp) {
+        switch(dc->base.is_jmp) {
         case DISAS_NEXT:
             gen_goto_tb(dc, 1, dc->pc);
             break;
@@ -12148,22 +12146,22 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     }
 
 done_generating:
-    gen_tb_end(tb, num_insns);
+    gen_tb_end(tb, dc->base.num_insns);
 
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
-        qemu_log_in_addr_range(pc_start)) {
+        qemu_log_in_addr_range(dc->base.pc_first)) {
         qemu_log_lock();
         qemu_log("----------------\n");
-        qemu_log("IN: %s\n", lookup_symbol(pc_start));
-        log_target_disas(cpu, pc_start, dc->pc - pc_start,
+        qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
+        log_target_disas(cpu, dc->base.pc_first, dc->pc - dc->base.pc_first,
                          dc->thumb | (dc->sctlr_b << 1));
         qemu_log("\n");
         qemu_log_unlock();
     }
 #endif
-    tb->size = dc->pc - pc_start;
-    tb->icount = num_insns;
+    tb->size = dc->pc - dc->base.pc_first;
+    tb->icount = dc->base.num_insns;
 }
 
 static const char *cpu_mode_names[16] = {
diff --git a/target/arm/translate.h b/target/arm/translate.h
index aba3f44c9f..6fe40a344a 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -6,9 +6,10 @@
 
 /* internal defines */
 typedef struct DisasContext {
+    DisasContextBase base;
+
     target_ulong pc;
     uint32_t insn;
-    int is_jmp;
     /* Nonzero if this instruction has been conditionally skipped.  */
     int condjmp;
     /* The label that will be jumped to when the instruction is skipped.  */
@@ -16,8 +17,6 @@ typedef struct DisasContext {
     /* Thumb-2 conditional execution bits.  */
     int condexec_mask;
     int condexec_cond;
-    struct TranslationBlock *tb;
-    int singlestep_enabled;
     int thumb;
     int sctlr_b;
     TCGMemOp be_data;
@@ -152,7 +151,8 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);
-void gen_intermediate_code_a64(CPUState *cpu, TranslationBlock *tb);
+void gen_intermediate_code_a64(DisasContextBase *db, CPUState *cpu,
+                               TranslationBlock *tb);
 void gen_a64_set_pc_im(uint64_t val);
 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
                             fprintf_function cpu_fprintf, int flags);
@@ -161,7 +161,8 @@ static inline void a64_translate_init(void)
 {
 }
 
-static inline void gen_intermediate_code_a64(CPUState *cpu, TranslationBlock *tb)
+static inline void gen_intermediate_code_a64(DisasContextBase *db, CPUState *cpu,
+                                             TranslationBlock *tb)
 {
 }
 

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 15/29] target/arm: [tcg] Port to init_disas_context
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (13 preceding siblings ...)
  2017-06-28 13:13 ` [Qemu-devel] [PATCH v11 14/29] target/arm: [tcg] Port to DisasContextBase Lluís Vilanova
@ 2017-06-28 13:17 ` Lluís Vilanova
  2017-07-02  1:04   ` Richard Henderson
  2017-06-28 13:21 ` [Qemu-devel] [PATCH v11 16/29] target/arm: [tcg, a64] " Lluís Vilanova
                   ` (13 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate.c |   85 +++++++++++++++++++++++++++---------------------
 1 file changed, 47 insertions(+), 38 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 17bc9687b7..23a07fc2c6 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11786,32 +11786,12 @@ static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
     return false;
 }
 
-/* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
+static void arm_trblock_init_disas_context(DisasContextBase *dcbase,
+                                           CPUState *cpu)
 {
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
     CPUARMState *env = cpu->env_ptr;
     ARMCPU *arm_cpu = arm_env_get_cpu(env);
-    DisasContext dc1, *dc = &dc1;
-    target_ulong next_page_start;
-    int max_insns;
-    bool end_of_page;
-
-    /* generate intermediate code */
-
-    /* The A64 decoder has its own top level loop, because it doesn't need
-     * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
-     */
-    if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
-        gen_intermediate_code_a64(&dc->base, cpu, tb);
-        return;
-    }
-
-    dc->base.tb = tb;
-    dc->base.pc_first = tb->pc;
-    dc->base.pc_next = dc->base.pc_first;
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.num_insns = 0;
-    dc->base.singlestep_enabled = cpu->singlestep_enabled;
 
     dc->pc = dc->base.pc_first;
     dc->condjmp = 0;
@@ -11822,23 +11802,23 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
      */
     dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
                                !arm_el_is_aa64(env, 3);
-    dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
-    dc->sctlr_b = ARM_TBFLAG_SCTLR_B(tb->flags);
-    dc->be_data = ARM_TBFLAG_BE_DATA(tb->flags) ? MO_BE : MO_LE;
-    dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
-    dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
-    dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(tb->flags));
+    dc->thumb = ARM_TBFLAG_THUMB(dc->base.tb->flags);
+    dc->sctlr_b = ARM_TBFLAG_SCTLR_B(dc->base.tb->flags);
+    dc->be_data = ARM_TBFLAG_BE_DATA(dc->base.tb->flags) ? MO_BE : MO_LE;
+    dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) & 0xf) << 1;
+    dc->condexec_cond = ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) >> 4;
+    dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags));
     dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
 #if !defined(CONFIG_USER_ONLY)
     dc->user = (dc->current_el == 0);
 #endif
-    dc->ns = ARM_TBFLAG_NS(tb->flags);
-    dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(tb->flags);
-    dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
-    dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
-    dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
-    dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
-    dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(tb->flags);
+    dc->ns = ARM_TBFLAG_NS(dc->base.tb->flags);
+    dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
+    dc->vfp_enabled = ARM_TBFLAG_VFPEN(dc->base.tb->flags);
+    dc->vec_len = ARM_TBFLAG_VECLEN(dc->base.tb->flags);
+    dc->vec_stride = ARM_TBFLAG_VECSTRIDE(dc->base.tb->flags);
+    dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(dc->base.tb->flags);
+    dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(dc->base.tb->flags);
     dc->cp_regs = arm_cpu->cp_regs;
     dc->features = env->features;
 
@@ -11857,10 +11837,39 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
      *   emit code to generate a software step exception
      *   end the TB
      */
-    dc->ss_active = ARM_TBFLAG_SS_ACTIVE(tb->flags);
-    dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(tb->flags);
+    dc->ss_active = ARM_TBFLAG_SS_ACTIVE(dc->base.tb->flags);
+    dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(dc->base.tb->flags);
     dc->is_ldex = false;
     dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
+}
+
+/* generate intermediate code for basic block 'tb'.  */
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
+{
+    CPUARMState *env = cpu->env_ptr;
+    DisasContext dc1, *dc = &dc1;
+    target_ulong next_page_start;
+    int max_insns;
+    bool end_of_page;
+
+    /* generate intermediate code */
+
+    /* The A64 decoder has its own top level loop, because it doesn't need
+     * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
+     */
+    if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
+        gen_intermediate_code_a64(&dc->base, cpu, tb);
+        return;
+    }
+
+    dc->base.tb = tb;
+    dc->base.pc_first = dc->base.tb->pc;
+    dc->base.pc_next = dc->base.pc_first;
+    dc->base.is_jmp = DISAS_NEXT;
+    dc->base.num_insns = 0;
+    dc->base.singlestep_enabled = cpu->singlestep_enabled;
+    arm_trblock_init_disas_context(&dc->base, cpu);
+
 
     cpu_F0s = tcg_temp_new_i32();
     cpu_F1s = tcg_temp_new_i32();

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 16/29] target/arm: [tcg, a64] Port to init_disas_context
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (14 preceding siblings ...)
  2017-06-28 13:17 ` [Qemu-devel] [PATCH v11 15/29] target/arm: [tcg] Port to init_disas_context Lluís Vilanova
@ 2017-06-28 13:21 ` Lluís Vilanova
  2017-07-02  1:13   ` Richard Henderson
  2017-06-28 13:25 ` [Qemu-devel] [PATCH v11 17/29] target/arm: [tcg] Port to init_globals Lluís Vilanova
                   ` (12 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:21 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate-a64.c |   36 ++++++++++++++++++++++--------------
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 4270ac3847..88624a726d 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11190,21 +11190,12 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
     free_tmp_a64(s);
 }
 
-void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
-                               TranslationBlock *tb)
+static void aarch64_trblock_init_disas_context(DisasContextBase *dcbase,
+                                               CPUState *cpu)
 {
-    CPUARMState *env = cs->env_ptr;
-    ARMCPU *cpu = arm_env_get_cpu(env);
     DisasContext *dc = container_of(dcbase, DisasContext, base);
-    target_ulong next_page_start;
-    int max_insns;
-
-    dc->base.tb = tb;
-    dc->base.pc_first = dc->base.tb->pc;
-    dc->base.pc_next = dc->base.pc_first;
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.num_insns = 0;
-    dc->base.singlestep_enabled = cs->singlestep_enabled;
+    CPUARMState *env = cpu->env_ptr;
+    ARMCPU *arm_cpu = arm_env_get_cpu(env);
 
     dc->pc = dc->base.pc_first;
     dc->condjmp = 0;
@@ -11230,7 +11221,7 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
     dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
     dc->vec_len = 0;
     dc->vec_stride = 0;
-    dc->cp_regs = cpu->cp_regs;
+    dc->cp_regs = arm_cpu->cp_regs;
     dc->features = env->features;
 
     /* Single step state. The code-generation logic here is:
@@ -11254,6 +11245,23 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
     dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
 
     init_tmp_a64_array(dc);
+}
+
+void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
+                               TranslationBlock *tb)
+{
+    CPUARMState *env = cs->env_ptr;
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    target_ulong next_page_start;
+    int max_insns;
+
+    dc->base.tb = tb;
+    dc->base.pc_first = dc->base.tb->pc;
+    dc->base.pc_next = dc->base.pc_first;
+    dc->base.is_jmp = DISAS_NEXT;
+    dc->base.num_insns = 0;
+    dc->base.singlestep_enabled = cs->singlestep_enabled;
+    aarch64_trblock_init_disas_context(&dc->base, cs);
 
     next_page_start = (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     max_insns = dc->base.tb->cflags & CF_COUNT_MASK;

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 17/29] target/arm: [tcg] Port to init_globals
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (15 preceding siblings ...)
  2017-06-28 13:21 ` [Qemu-devel] [PATCH v11 16/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-06-28 13:25 ` Lluís Vilanova
  2017-07-02  1:14   ` Richard Henderson
  2017-06-28 13:29 ` [Qemu-devel] [PATCH v11 18/29] target/arm: [tcg] Port to tb_start Lluís Vilanova
                   ` (11 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate.c |   21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 23a07fc2c6..fc28cd45f7 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11843,6 +11843,18 @@ static void arm_trblock_init_disas_context(DisasContextBase *dcbase,
     dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
 }
 
+static void arm_trblock_init_globals(DisasContextBase *dcbase, CPUState *cpu)
+{
+    cpu_F0s = tcg_temp_new_i32();
+    cpu_F1s = tcg_temp_new_i32();
+    cpu_F0d = tcg_temp_new_i64();
+    cpu_F1d = tcg_temp_new_i64();
+    cpu_V0 = cpu_F0d;
+    cpu_V1 = cpu_F1d;
+    /* FIXME: cpu_M0 can probably be the same as cpu_V0.  */
+    cpu_M0 = tcg_temp_new_i64();
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -11871,14 +11883,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     arm_trblock_init_disas_context(&dc->base, cpu);
 
 
-    cpu_F0s = tcg_temp_new_i32();
-    cpu_F1s = tcg_temp_new_i32();
-    cpu_F0d = tcg_temp_new_i64();
-    cpu_F1d = tcg_temp_new_i64();
-    cpu_V0 = cpu_F0d;
-    cpu_V1 = cpu_F1d;
-    /* FIXME: cpu_M0 can probably be the same as cpu_V0.  */
-    cpu_M0 = tcg_temp_new_i64();
+    arm_trblock_init_globals(&dc->base, cpu);
     next_page_start = (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 18/29] target/arm: [tcg] Port to tb_start
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (16 preceding siblings ...)
  2017-06-28 13:25 ` [Qemu-devel] [PATCH v11 17/29] target/arm: [tcg] Port to init_globals Lluís Vilanova
@ 2017-06-28 13:29 ` Lluís Vilanova
  2017-07-02  1:17   ` Richard Henderson
  2017-06-28 13:33 ` [Qemu-devel] [PATCH v11 19/29] target/arm: [tcg] Port to insn_start Lluís Vilanova
                   ` (10 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:29 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate.c |   82 ++++++++++++++++++++++++++----------------------
 1 file changed, 44 insertions(+), 38 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index fc28cd45f7..029c4d3550 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11855,6 +11855,49 @@ static void arm_trblock_init_globals(DisasContextBase *dcbase, CPUState *cpu)
     cpu_M0 = tcg_temp_new_i64();
 }
 
+static void arm_trblock_tb_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    /* A note on handling of the condexec (IT) bits:
+     *
+     * We want to avoid the overhead of having to write the updated condexec
+     * bits back to the CPUARMState for every instruction in an IT block. So:
+     * (1) if the condexec bits are not already zero then we write
+     * zero back into the CPUARMState now. This avoids complications trying
+     * to do it at the end of the block. (For example if we don't do this
+     * it's hard to identify whether we can safely skip writing condexec
+     * at the end of the TB, which we definitely want to do for the case
+     * where a TB doesn't do anything with the IT state at all.)
+     * (2) if we are going to leave the TB then we call gen_set_condexec()
+     * which will write the correct value into CPUARMState if zero is wrong.
+     * This is done both for leaving the TB at the end, and for leaving
+     * it because of an exception we know will happen, which is done in
+     * gen_exception_insn(). The latter is necessary because we need to
+     * leave the TB with the PC/IT state just prior to execution of the
+     * instruction which caused the exception.
+     * (3) if we leave the TB unexpectedly (eg a data abort on a load)
+     * then the CPUARMState will be wrong and we need to reset it.
+     * This is handled in the same way as restoration of the
+     * PC in these situations; we save the value of the condexec bits
+     * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
+     * then uses this to restore them after an exception.
+     *
+     * Note that there are no instructions which can read the condexec
+     * bits, and none which can write non-static values to them, so
+     * we don't need to care about whether CPUARMState is correct in the
+     * middle of a TB.
+     */
+
+    /* Reset the conditional execution bits immediately. This avoids
+       complications trying to do it at the end of the block.  */
+    if (dc->condexec_mask || dc->condexec_cond) {
+        TCGv_i32 tmp = tcg_temp_new_i32();
+        tcg_gen_movi_i32(tmp, 0);
+        store_cpu_field(tmp, condexec_bits);
+    }
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -11896,45 +11939,8 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     gen_tb_start(tb);
 
     tcg_clear_temp_count();
+    arm_trblock_tb_start(&dc->base, cpu);
 
-    /* A note on handling of the condexec (IT) bits:
-     *
-     * We want to avoid the overhead of having to write the updated condexec
-     * bits back to the CPUARMState for every instruction in an IT block. So:
-     * (1) if the condexec bits are not already zero then we write
-     * zero back into the CPUARMState now. This avoids complications trying
-     * to do it at the end of the block. (For example if we don't do this
-     * it's hard to identify whether we can safely skip writing condexec
-     * at the end of the TB, which we definitely want to do for the case
-     * where a TB doesn't do anything with the IT state at all.)
-     * (2) if we are going to leave the TB then we call gen_set_condexec()
-     * which will write the correct value into CPUARMState if zero is wrong.
-     * This is done both for leaving the TB at the end, and for leaving
-     * it because of an exception we know will happen, which is done in
-     * gen_exception_insn(). The latter is necessary because we need to
-     * leave the TB with the PC/IT state just prior to execution of the
-     * instruction which caused the exception.
-     * (3) if we leave the TB unexpectedly (eg a data abort on a load)
-     * then the CPUARMState will be wrong and we need to reset it.
-     * This is handled in the same way as restoration of the
-     * PC in these situations; we save the value of the condexec bits
-     * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
-     * then uses this to restore them after an exception.
-     *
-     * Note that there are no instructions which can read the condexec
-     * bits, and none which can write non-static values to them, so
-     * we don't need to care about whether CPUARMState is correct in the
-     * middle of a TB.
-     */
-
-    /* Reset the conditional execution bits immediately. This avoids
-       complications trying to do it at the end of the block.  */
-    if (dc->condexec_mask || dc->condexec_cond)
-      {
-        TCGv_i32 tmp = tcg_temp_new_i32();
-        tcg_gen_movi_i32(tmp, 0);
-        store_cpu_field(tmp, condexec_bits);
-      }
     do {
         dc->base.num_insns++;
         dc->insn_start_idx = tcg_op_buf_count();

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 19/29] target/arm: [tcg] Port to insn_start
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (17 preceding siblings ...)
  2017-06-28 13:29 ` [Qemu-devel] [PATCH v11 18/29] target/arm: [tcg] Port to tb_start Lluís Vilanova
@ 2017-06-28 13:33 ` Lluís Vilanova
  2017-07-02  1:18   ` Richard Henderson
  2017-06-28 13:37 ` [Qemu-devel] [PATCH v11 20/29] target/arm: [tcg, a64] " Lluís Vilanova
                   ` (9 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate.c |   34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 029c4d3550..c7e188b50e 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11898,6 +11898,26 @@ static void arm_trblock_tb_start(DisasContextBase *dcbase, CPUState *cpu)
     }
 }
 
+static void arm_trblock_insn_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    dc->insn_start_idx = tcg_op_buf_count();
+    tcg_gen_insn_start(dc->pc,
+                       (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
+                       0);
+
+#ifdef CONFIG_USER_ONLY
+    /* Intercept jump to the magic kernel page.  */
+    if (dc->pc >= 0xffff0000) {
+        /* We always get here via a jump, so know we are not in a
+           conditional execution block.  */
+        gen_exception_internal(EXCP_KERNEL_TRAP);
+        dc->base.is_jmp = DISAS_EXC;
+    }
+#endif
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -11943,21 +11963,11 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 
     do {
         dc->base.num_insns++;
-        dc->insn_start_idx = tcg_op_buf_count();
-        tcg_gen_insn_start(dc->pc,
-                           (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
-                           0);
+        arm_trblock_insn_start(&dc->base, cpu);
 
-#ifdef CONFIG_USER_ONLY
-        /* Intercept jump to the magic kernel page.  */
-        if (dc->pc >= 0xffff0000) {
-            /* We always get here via a jump, so know we are not in a
-               conditional execution block.  */
-            gen_exception_internal(EXCP_KERNEL_TRAP);
-            dc->base.is_jmp = DISAS_EXC;
+        if (unlikely(dc->base.is_jmp > DISAS_NEXT)) {
             break;
         }
-#endif
 
         if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
             CPUBreakpoint *bp;

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 20/29] target/arm: [tcg, a64] Port to insn_start
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (18 preceding siblings ...)
  2017-06-28 13:33 ` [Qemu-devel] [PATCH v11 19/29] target/arm: [tcg] Port to insn_start Lluís Vilanova
@ 2017-06-28 13:37 ` Lluís Vilanova
  2017-07-02  1:19   ` Richard Henderson
  2017-06-28 13:41 ` [Qemu-devel] [PATCH v11 21/29] target/arm: [tcg] Port to breakpoint_check Lluís Vilanova
                   ` (8 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:37 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate-a64.c |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 88624a726d..5784620642 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11247,6 +11247,14 @@ static void aarch64_trblock_init_disas_context(DisasContextBase *dcbase,
     init_tmp_a64_array(dc);
 }
 
+static void aarch64_trblock_insn_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    dc->insn_start_idx = tcg_op_buf_count();
+    tcg_gen_insn_start(dc->pc, 0, 0);
+}
+
 void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
                                TranslationBlock *tb)
 {
@@ -11278,8 +11286,7 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
 
     do {
         dc->base.num_insns++;
-        dc->insn_start_idx = tcg_op_buf_count();
-        tcg_gen_insn_start(dc->pc, 0, 0);
+        aarch64_trblock_insn_start(&dc->base, cs);
 
         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
             CPUBreakpoint *bp;

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 21/29] target/arm: [tcg] Port to breakpoint_check
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (19 preceding siblings ...)
  2017-06-28 13:37 ` [Qemu-devel] [PATCH v11 20/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-06-28 13:41 ` Lluís Vilanova
  2017-07-02  1:21   ` Richard Henderson
  2017-06-28 13:45 ` [Qemu-devel] [PATCH v11 22/29] target/arm: [tcg, a64] " Lluís Vilanova
                   ` (7 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:41 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate.c |   68 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 46 insertions(+), 22 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index c7e188b50e..790eaa2164 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11918,6 +11918,32 @@ static void arm_trblock_insn_start(DisasContextBase *dcbase, CPUState *cpu)
 #endif
 }
 
+static BreakpointCheckType arm_trblock_breakpoint_check(
+    DisasContextBase *dcbase, CPUState *cpu, const CPUBreakpoint *bp)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    if (bp->flags & BP_CPU) {
+        gen_set_condexec(dc);
+        gen_set_pc_im(dc, dc->pc);
+        gen_helper_check_breakpoints(cpu_env);
+        /* End the TB early; it's likely not going to be executed */
+        dc->base.is_jmp = DISAS_UPDATE;
+        return BC_HIT_INSN;
+    } else {
+        gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
+        /* 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.  */
+        /* TODO: Advance PC by correct instruction length to
+         * avoid disassembler error messages */
+        dc->pc += 2;
+        return BC_HIT_TB;
+    }
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -11965,36 +11991,34 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         dc->base.num_insns++;
         arm_trblock_insn_start(&dc->base, cpu);
 
-        if (unlikely(dc->base.is_jmp > DISAS_NEXT)) {
-            break;
-        }
-
         if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
             CPUBreakpoint *bp;
             QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
-                if (bp->pc == dc->pc) {
-                    if (bp->flags & BP_CPU) {
-                        gen_set_condexec(dc);
-                        gen_set_pc_im(dc, dc->pc);
-                        gen_helper_check_breakpoints(cpu_env);
-                        /* End the TB early; it's likely not going to be executed */
-                        dc->base.is_jmp = DISAS_UPDATE;
-                    } else {
-                        gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
-                        /* 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.  */
-                        /* TODO: Advance PC by correct instruction length to
-                         * avoid disassembler error messages */
-                        dc->pc += 2;
+                if (bp->pc == dc->base.pc_next) {
+                    BreakpointCheckType bp_check =
+                        arm_trblock_breakpoint_check(&dc->base, cpu, bp);
+                    switch (bp_check) {
+                    case BC_MISS:
+                        /* Target ignored this breakpoint, go to next */
+                        break;
+                    case BC_HIT_INSN:
+                        /* Hit, keep translating */
+                        /*
+                         * TODO: if we're never going to have more than one
+                         *       BP in a single address, we can simply use a
+                         *       bool here.
+                         */
+                        goto done_breakpoints;
+                    case BC_HIT_TB:
+                        /* Hit, end TB */
                         goto done_generating;
+                    default:
+                        g_assert_not_reached();
                     }
-                    break;
                 }
             }
         }
+    done_breakpoints:
 
         if (dc->base.num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 22/29] target/arm: [tcg, a64] Port to breakpoint_check
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (20 preceding siblings ...)
  2017-06-28 13:41 ` [Qemu-devel] [PATCH v11 21/29] target/arm: [tcg] Port to breakpoint_check Lluís Vilanova
@ 2017-06-28 13:45 ` Lluís Vilanova
  2017-07-02  1:22   ` Richard Henderson
  2017-06-28 13:49 ` [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn Lluís Vilanova
                   ` (6 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate-a64.c |   58 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 43 insertions(+), 15 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 5784620642..9c870f6d07 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11255,6 +11255,29 @@ static void aarch64_trblock_insn_start(DisasContextBase *dcbase, CPUState *cpu)
     tcg_gen_insn_start(dc->pc, 0, 0);
 }
 
+static BreakpointCheckType aarch64_trblock_breakpoint_check(
+    DisasContextBase *dcbase, CPUState *cpu, const CPUBreakpoint *bp)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    if (bp->flags & BP_CPU) {
+        gen_a64_set_pc_im(dc->pc);
+        gen_helper_check_breakpoints(cpu_env);
+        /* End the TB early; it likely won't be executed */
+        dc->base.is_jmp = DISAS_UPDATE;
+        return BC_HIT_INSN;
+    } else {
+        gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
+        /* 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 += 4;
+        return BC_HIT_TB;
+    }
+}
+
 void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
                                TranslationBlock *tb)
 {
@@ -11291,26 +11314,31 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
             CPUBreakpoint *bp;
             QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
-                if (bp->pc == dc->pc) {
-                    if (bp->flags & BP_CPU) {
-                        gen_a64_set_pc_im(dc->pc);
-                        gen_helper_check_breakpoints(cpu_env);
-                        /* End the TB early; it likely won't be executed */
-                        dc->base.is_jmp = DISAS_UPDATE;
-                    } else {
-                        gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
-                        /* The address covered by the breakpoint must be
-                           included in [dc->base.tb->pc, dc->base.tb->pc + dc->base.tb->size) in order
-                           to for it to be properly cleared -- thus we
-                           increment the PC here so that the logic setting
-                           dc->base.tb->size below does the right thing.  */
-                        dc->pc += 4;
+                if (bp->pc == dc->base.pc_next) {
+                    BreakpointCheckType bp_check =
+                        aarch64_trblock_breakpoint_check(&dc->base, cs, bp);
+                    switch (bp_check) {
+                    case BC_MISS:
+                        /* Target ignored this breakpoint, go to next */
+                        break;
+                    case BC_HIT_INSN:
+                        /* Hit, keep translating */
+                        /*
+                         * TODO: if we're never going to have more than one
+                         *       BP in a single address, we can simply use a
+                         *       bool here.
+                         */
+                        goto done_breakpoints;
+                    case BC_HIT_TB:
+                        /* Hit, end TB */
                         goto done_generating;
+                    default:
+                        g_assert_not_reached();
                     }
-                    break;
                 }
             }
         }
+    done_breakpoints:
 
         if (dc->base.num_insns == max_insns && (dc->base.tb->cflags & CF_LAST_IO)) {
             gen_io_start();

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (21 preceding siblings ...)
  2017-06-28 13:45 ` [Qemu-devel] [PATCH v11 22/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-06-28 13:49 ` Lluís Vilanova
  2017-07-02  1:34   ` Richard Henderson
  2017-06-28 13:53 ` [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] " Lluís Vilanova
                   ` (5 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate.c |  147 +++++++++++++++++++++++++++---------------------
 target/arm/translate.h |    4 +
 2 files changed, 88 insertions(+), 63 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 790eaa2164..7ab09a7e5f 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11841,6 +11841,9 @@ static void arm_trblock_init_disas_context(DisasContextBase *dcbase,
     dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(dc->base.tb->flags);
     dc->is_ldex = false;
     dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
+
+    dc->next_page_start =
+        (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
 }
 
 static void arm_trblock_init_globals(DisasContextBase *dcbase, CPUState *cpu)
@@ -11944,14 +11947,82 @@ static BreakpointCheckType arm_trblock_breakpoint_check(
     }
 }
 
+static target_ulong arm_trblock_translate_insn(DisasContextBase *dcbase,
+                                               CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    CPUARMState *env = cpu->env_ptr;
+
+    if (dc->ss_active && !dc->pstate_ss) {
+        /* Singlestep state is Active-pending.
+         * If we're in this state at the start of a TB then either
+         *  a) we just took an exception to an EL which is being debugged
+         *     and this is the first insn in the exception handler
+         *  b) debug exceptions were masked and we just unmasked them
+         *     without changing EL (eg by clearing PSTATE.D)
+         * In either case we're going to take a swstep exception in the
+         * "did not step an insn" case, and so the syndrome ISV and EX
+         * bits should be zero.
+         */
+        assert(dc->base.num_insns == 1);
+        gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
+                      default_exception_el(dc));
+        dc->base.is_jmp = DISAS_SKIP;
+        return dc->pc;
+    }
+
+    if (dc->thumb) {
+        disas_thumb_insn(env, dc);
+        if (dc->condexec_mask) {
+            dc->condexec_cond = (dc->condexec_cond & 0xe)
+                | ((dc->condexec_mask >> 4) & 1);
+            dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
+            if (dc->condexec_mask == 0) {
+                dc->condexec_cond = 0;
+            }
+        }
+    } else {
+        unsigned int insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
+        dc->pc += 4;
+        disas_arm_insn(dc, insn);
+    }
+
+    if (dc->condjmp && !dc->base.is_jmp) {
+        gen_set_label(dc->condlabel);
+        dc->condjmp = 0;
+    }
+
+
+    /* Translation stops when a conditional branch is encountered.
+     * Otherwise the subsequent code could get translated several times.
+     * Also stop translation when a page boundary is reached.  This
+     * ensures prefetch aborts occur at the right place.  */
+
+    if (is_singlestepping(dc)) {
+        dc->base.is_jmp = DISAS_SS;
+    } else if ((dc->pc >= dc->next_page_start) ||
+               ((dc->pc >= dc->next_page_start - 3) &&
+                insn_crosses_page(env, dc))) {
+        /* We want to stop the TB if the next insn starts in a new page,
+         * or if it spans between this page and the next. This means that
+         * if we're looking at the last halfword in the page we need to
+         * see if it's a 16-bit Thumb insn (which will fit in this TB)
+         * or a 32-bit Thumb insn (which won't).
+         * This is to avoid generating a silly TB with a single 16-bit insn
+         * in it at the end of this page (which would execute correctly
+         * but isn't very efficient).
+         */
+        return DISAS_PAGE_CROSS;
+    }
+
+    return dc->pc;
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
-    CPUARMState *env = cpu->env_ptr;
     DisasContext dc1, *dc = &dc1;
-    target_ulong next_page_start;
     int max_insns;
-    bool end_of_page;
 
     /* generate intermediate code */
 
@@ -11973,7 +12044,6 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 
 
     arm_trblock_init_globals(&dc->base, cpu);
-    next_page_start = (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
         max_insns = CF_COUNT_MASK;
@@ -12024,72 +12094,20 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             gen_io_start();
         }
 
-        if (dc->ss_active && !dc->pstate_ss) {
-            /* Singlestep state is Active-pending.
-             * If we're in this state at the start of a TB then either
-             *  a) we just took an exception to an EL which is being debugged
-             *     and this is the first insn in the exception handler
-             *  b) debug exceptions were masked and we just unmasked them
-             *     without changing EL (eg by clearing PSTATE.D)
-             * In either case we're going to take a swstep exception in the
-             * "did not step an insn" case, and so the syndrome ISV and EX
-             * bits should be zero.
-             */
-            assert(dc->base.num_insns == 1);
-            gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
-                          default_exception_el(dc));
-            goto done_generating;
-        }
-
-        if (dc->thumb) {
-            disas_thumb_insn(env, dc);
-            if (dc->condexec_mask) {
-                dc->condexec_cond = (dc->condexec_cond & 0xe)
-                                   | ((dc->condexec_mask >> 4) & 1);
-                dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
-                if (dc->condexec_mask == 0) {
-                    dc->condexec_cond = 0;
-                }
-            }
-        } else {
-            unsigned int insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
-            dc->pc += 4;
-            disas_arm_insn(dc, insn);
-        }
-
-        if (dc->condjmp && !dc->base.is_jmp) {
-            gen_set_label(dc->condlabel);
-            dc->condjmp = 0;
-        }
+        dc->base.pc_next = arm_trblock_translate_insn(&dc->base, cpu);
 
         if (tcg_check_temp_count()) {
             fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
                     dc->pc);
         }
 
-        /* Translation stops when a conditional branch is encountered.
-         * Otherwise the subsequent code could get translated several times.
-         * Also stop translation when a page boundary is reached.  This
-         * ensures prefetch aborts occur at the right place.  */
-
-        /* We want to stop the TB if the next insn starts in a new page,
-         * or if it spans between this page and the next. This means that
-         * if we're looking at the last halfword in the page we need to
-         * see if it's a 16-bit Thumb insn (which will fit in this TB)
-         * or a 32-bit Thumb insn (which won't).
-         * This is to avoid generating a silly TB with a single 16-bit insn
-         * in it at the end of this page (which would execute correctly
-         * but isn't very efficient).
-         */
-        end_of_page = (dc->pc >= next_page_start) ||
-            ((dc->pc >= next_page_start - 3) && insn_crosses_page(env, dc));
-
-    } while (!dc->base.is_jmp && !tcg_op_buf_full() &&
-             !is_singlestepping(dc) &&
-             !singlestep &&
-             !end_of_page &&
-             dc->base.num_insns < max_insns);
+        if (!dc->base.is_jmp && (tcg_op_buf_full() || singlestep ||
+                            dc->base.num_insns >= max_insns)) {
+            dc->base.is_jmp = DISAS_TOO_MANY;
+        }
+    } while (!dc->base.is_jmp);
 
+    if (dc->base.is_jmp != DISAS_SKIP) {
     if (tb->cflags & CF_LAST_IO) {
         if (dc->condjmp) {
             /* FIXME:  This can theoretically happen with self-modifying
@@ -12127,6 +12145,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
             break;
         case DISAS_NEXT:
+        case DISAS_TOO_MANY:
         case DISAS_UPDATE:
             gen_set_pc_im(dc, dc->pc);
             /* fall through */
@@ -12145,6 +12164,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
          */
         switch(dc->base.is_jmp) {
         case DISAS_NEXT:
+        case DISAS_TOO_MANY:
             gen_goto_tb(dc, 1, dc->pc);
             break;
         case DISAS_UPDATE:
@@ -12198,6 +12218,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             gen_goto_tb(dc, 1, dc->pc);
         }
     }
+    }
 
 done_generating:
     gen_tb_end(tb, dc->base.num_insns);
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 6fe40a344a..f830775540 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -9,6 +9,7 @@ typedef struct DisasContext {
     DisasContextBase base;
 
     target_ulong pc;
+    target_ulong next_page_start;
     uint32_t insn;
     /* Nonzero if this instruction has been conditionally skipped.  */
     int condjmp;
@@ -148,6 +149,9 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
  * as opposed to attempting to use lookup_and_goto_ptr.
  */
 #define DISAS_EXIT DISAS_TARGET_11
+#define DISAS_SS   DISAS_TARGET_12
+#define DISAS_PAGE_CROSS DISAS_TARGET_13
+#define DISAS_SKIP DISAS_TARGET_14
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] Port to translate_insn
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (22 preceding siblings ...)
  2017-06-28 13:49 ` [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn Lluís Vilanova
@ 2017-06-28 13:53 ` Lluís Vilanova
  2017-07-02  1:42   ` Richard Henderson
  2017-06-28 13:57 ` [Qemu-devel] [PATCH v11 25/29] target/arm: [tcg] Port to tb_stop Lluís Vilanova
                   ` (4 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:53 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate-a64.c |   74 +++++++++++++++++++++++++++-----------------
 1 file changed, 46 insertions(+), 28 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 9c870f6d07..586a01a2de 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11244,6 +11244,9 @@ static void aarch64_trblock_init_disas_context(DisasContextBase *dcbase,
     dc->is_ldex = false;
     dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
 
+    dc->next_page_start =
+        (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+
     init_tmp_a64_array(dc);
 }
 
@@ -11278,12 +11281,45 @@ static BreakpointCheckType aarch64_trblock_breakpoint_check(
     }
 }
 
+static target_ulong aarch64_trblock_translate_insn(DisasContextBase *dcbase,
+                                                   CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    CPUARMState *env = cpu->env_ptr;
+
+
+    if (dc->ss_active && !dc->pstate_ss) {
+        /* Singlestep state is Active-pending.
+         * If we're in this state at the start of a TB then either
+         *  a) we just took an exception to an EL which is being debugged
+         *     and this is the first insn in the exception handler
+         *  b) debug exceptions were masked and we just unmasked them
+         *     without changing EL (eg by clearing PSTATE.D)
+         * In either case we're going to take a swstep exception in the
+         * "did not step an insn" case, and so the syndrome ISV and EX
+         * bits should be zero.
+         */
+        assert(dc->base.num_insns == 1);
+        gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
+                      default_exception_el(dc));
+        dc->base.is_jmp = DISAS_EXC;
+    } else {
+        disas_a64_insn(env, dc);
+    }
+
+    if (dc->ss_active) {
+        dc->base.is_jmp = DISAS_SS;
+    } else if (dc->pc >= dc->next_page_start) {
+        dc->base.is_jmp = DISAS_PAGE_CROSS;
+    }
+
+    return dc->pc;
+}
+
 void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
                                TranslationBlock *tb)
 {
-    CPUARMState *env = cs->env_ptr;
     DisasContext *dc = container_of(dcbase, DisasContext, base);
-    target_ulong next_page_start;
     int max_insns;
 
     dc->base.tb = tb;
@@ -11294,7 +11330,6 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
     dc->base.singlestep_enabled = cs->singlestep_enabled;
     aarch64_trblock_init_disas_context(&dc->base, cs);
 
-    next_page_start = (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     max_insns = dc->base.tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
         max_insns = CF_COUNT_MASK;
@@ -11344,42 +11379,24 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
             gen_io_start();
         }
 
-        if (dc->ss_active && !dc->pstate_ss) {
-            /* Singlestep state is Active-pending.
-             * If we're in this state at the start of a TB then either
-             *  a) we just took an exception to an EL which is being debugged
-             *     and this is the first insn in the exception handler
-             *  b) debug exceptions were masked and we just unmasked them
-             *     without changing EL (eg by clearing PSTATE.D)
-             * In either case we're going to take a swstep exception in the
-             * "did not step an insn" case, and so the syndrome ISV and EX
-             * bits should be zero.
-             */
-            assert(dc->base.num_insns == 1);
-            gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
-                          default_exception_el(dc));
-            dc->base.is_jmp = DISAS_EXC;
-            break;
-        }
-
-        disas_a64_insn(env, dc);
+        dc->base.pc_next = aarch64_trblock_translate_insn(&dc->base, cs);
 
         if (tcg_check_temp_count()) {
             fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
                     dc->pc);
         }
 
+        if (!dc->base.is_jmp && (tcg_op_buf_full() || cs->singlestep_enabled ||
+                            singlestep || dc->base.num_insns >= max_insns)) {
+            dc->base.is_jmp = DISAS_TOO_MANY;
+        }
+
         /* Translation stops when a conditional branch is encountered.
          * Otherwise the subsequent code could get translated several times.
          * Also stop translation when a page boundary is reached.  This
          * ensures prefetch aborts occur at the right place.
          */
-    } while (!dc->base.is_jmp && !tcg_op_buf_full() &&
-             !cs->singlestep_enabled &&
-             !singlestep &&
-             !dc->ss_active &&
-             dc->pc < next_page_start &&
-             dc->base.num_insns < max_insns);
+    } while (!dc->base.is_jmp);
 
     if (dc->base.tb->cflags & CF_LAST_IO) {
         gen_io_end();
@@ -11404,6 +11421,7 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
     } else {
         switch (dc->base.is_jmp) {
         case DISAS_NEXT:
+        case DISAS_TOO_MANY:
             gen_goto_tb(dc, 1, dc->pc);
             break;
         default:

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 25/29] target/arm: [tcg] Port to tb_stop
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (23 preceding siblings ...)
  2017-06-28 13:53 ` [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-06-28 13:57 ` Lluís Vilanova
  2017-07-02  1:45   ` Richard Henderson
  2017-06-28 14:01 ` [Qemu-devel] [PATCH v11 26/29] target/arm: [tcg, a64] " Lluís Vilanova
                   ` (3 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 13:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate.c |  195 ++++++++++++++++++++++++++----------------------
 1 file changed, 104 insertions(+), 91 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 7ab09a7e5f..ef0b870a2f 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -12018,103 +12018,21 @@ static target_ulong arm_trblock_translate_insn(DisasContextBase *dcbase,
     return dc->pc;
 }
 
-/* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
+static void arm_trblock_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
 {
-    DisasContext dc1, *dc = &dc1;
-    int max_insns;
-
-    /* generate intermediate code */
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
 
-    /* The A64 decoder has its own top level loop, because it doesn't need
-     * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
-     */
-    if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
-        gen_intermediate_code_a64(&dc->base, cpu, tb);
+    if (dc->base.is_jmp == DISAS_SKIP) {
         return;
     }
 
-    dc->base.tb = tb;
-    dc->base.pc_first = dc->base.tb->pc;
-    dc->base.pc_next = dc->base.pc_first;
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.num_insns = 0;
-    dc->base.singlestep_enabled = cpu->singlestep_enabled;
-    arm_trblock_init_disas_context(&dc->base, cpu);
-
-
-    arm_trblock_init_globals(&dc->base, cpu);
-    max_insns = tb->cflags & CF_COUNT_MASK;
-    if (max_insns == 0) {
-        max_insns = CF_COUNT_MASK;
-    }
-    if (max_insns > TCG_MAX_INSNS) {
-        max_insns = TCG_MAX_INSNS;
+    if ((dc->base.tb->cflags & CF_LAST_IO) && dc->condjmp) {
+        /* FIXME: This can theoretically happen with self-modifying code. */
+        cpu_abort(cpu, "IO on conditional branch instruction");
     }
-
-    gen_tb_start(tb);
-
-    tcg_clear_temp_count();
-    arm_trblock_tb_start(&dc->base, cpu);
-
-    do {
-        dc->base.num_insns++;
-        arm_trblock_insn_start(&dc->base, cpu);
-
-        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
-            CPUBreakpoint *bp;
-            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
-                if (bp->pc == dc->base.pc_next) {
-                    BreakpointCheckType bp_check =
-                        arm_trblock_breakpoint_check(&dc->base, cpu, bp);
-                    switch (bp_check) {
-                    case BC_MISS:
-                        /* Target ignored this breakpoint, go to next */
-                        break;
-                    case BC_HIT_INSN:
-                        /* Hit, keep translating */
-                        /*
-                         * TODO: if we're never going to have more than one
-                         *       BP in a single address, we can simply use a
-                         *       bool here.
-                         */
-                        goto done_breakpoints;
-                    case BC_HIT_TB:
-                        /* Hit, end TB */
-                        goto done_generating;
-                    default:
-                        g_assert_not_reached();
-                    }
-                }
-            }
-        }
-    done_breakpoints:
-
-        if (dc->base.num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
-        }
-
-        dc->base.pc_next = arm_trblock_translate_insn(&dc->base, cpu);
-
-        if (tcg_check_temp_count()) {
-            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
-                    dc->pc);
-        }
-
-        if (!dc->base.is_jmp && (tcg_op_buf_full() || singlestep ||
-                            dc->base.num_insns >= max_insns)) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-        }
-    } while (!dc->base.is_jmp);
-
-    if (dc->base.is_jmp != DISAS_SKIP) {
-    if (tb->cflags & CF_LAST_IO) {
-        if (dc->condjmp) {
-            /* FIXME:  This can theoretically happen with self-modifying
-               code.  */
-            cpu_abort(cpu, "IO on conditional branch instruction");
-        }
-        gen_io_end();
+    if (dc->base.tb->cflags & CF_LAST_IO && dc->condjmp) {
+        /* FIXME: This can theoretically happen with self-modifying code. */
+        cpu_abort(cpu, "IO on conditional branch instruction");
     }
 
     /* At this stage dc->condjmp will only be set when the skipped
@@ -12218,6 +12136,101 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             gen_goto_tb(dc, 1, dc->pc);
         }
     }
+}
+
+/* generate intermediate code for basic block 'tb'.  */
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
+{
+    DisasContext dc1, *dc = &dc1;
+    int max_insns;
+
+    /* generate intermediate code */
+
+    /* The A64 decoder has its own top level loop, because it doesn't need
+     * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
+     */
+    if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
+        gen_intermediate_code_a64(&dc->base, cpu, tb);
+        return;
+    }
+
+    dc->base.tb = tb;
+    dc->base.pc_first = dc->base.tb->pc;
+    dc->base.pc_next = dc->base.pc_first;
+    dc->base.is_jmp = DISAS_NEXT;
+    dc->base.num_insns = 0;
+    dc->base.singlestep_enabled = cpu->singlestep_enabled;
+    arm_trblock_init_disas_context(&dc->base, cpu);
+
+
+    arm_trblock_init_globals(&dc->base, cpu);
+    max_insns = tb->cflags & CF_COUNT_MASK;
+    if (max_insns == 0) {
+        max_insns = CF_COUNT_MASK;
+    }
+    if (max_insns > TCG_MAX_INSNS) {
+        max_insns = TCG_MAX_INSNS;
+    }
+
+    gen_tb_start(tb);
+
+    tcg_clear_temp_count();
+    arm_trblock_tb_start(&dc->base, cpu);
+
+    do {
+        dc->base.num_insns++;
+        arm_trblock_insn_start(&dc->base, cpu);
+
+        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
+            CPUBreakpoint *bp;
+            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
+                if (bp->pc == dc->base.pc_next) {
+                    BreakpointCheckType bp_check =
+                        arm_trblock_breakpoint_check(&dc->base, cpu, bp);
+                    switch (bp_check) {
+                    case BC_MISS:
+                        /* Target ignored this breakpoint, go to next */
+                        break;
+                    case BC_HIT_INSN:
+                        /* Hit, keep translating */
+                        /*
+                         * TODO: if we're never going to have more than one
+                         *       BP in a single address, we can simply use a
+                         *       bool here.
+                         */
+                        goto done_breakpoints;
+                    case BC_HIT_TB:
+                        /* Hit, end TB */
+                        goto done_generating;
+                    default:
+                        g_assert_not_reached();
+                    }
+                }
+            }
+        }
+    done_breakpoints:
+
+        if (dc->base.num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+
+        dc->base.pc_next = arm_trblock_translate_insn(&dc->base, cpu);
+
+        if (tcg_check_temp_count()) {
+            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
+                    dc->pc);
+        }
+
+        if (!dc->base.is_jmp && (tcg_op_buf_full() || singlestep ||
+                            dc->base.num_insns >= max_insns)) {
+            dc->base.is_jmp = DISAS_TOO_MANY;
+        }
+    } while (!dc->base.is_jmp);
+
+    arm_trblock_tb_stop(&dc->base, cpu);
+
+    if (dc->base.tb->cflags & CF_LAST_IO) {
+        gen_io_end();
     }
 
 done_generating:

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 26/29] target/arm: [tcg, a64] Port to tb_stop
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (24 preceding siblings ...)
  2017-06-28 13:57 ` [Qemu-devel] [PATCH v11 25/29] target/arm: [tcg] Port to tb_stop Lluís Vilanova
@ 2017-06-28 14:01 ` Lluís Vilanova
  2017-07-02  1:48   ` Richard Henderson
  2017-06-28 14:05 ` [Qemu-devel] [PATCH v11 27/29] target/arm: [tcg] Port to disas_log Lluís Vilanova
                   ` (2 subsequent siblings)
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 14:01 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate-a64.c |  123 +++++++++++++++++++++++---------------------
 1 file changed, 65 insertions(+), 58 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 586a01a2de..c57f475dc0 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11316,6 +11316,69 @@ static target_ulong aarch64_trblock_translate_insn(DisasContextBase *dcbase,
     return dc->pc;
 }
 
+static void aarch64_trblock_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    if (unlikely(dc->base.singlestep_enabled || dc->ss_active)
+        && dc->base.is_jmp != DISAS_EXC) {
+        /* Note that this means single stepping WFI doesn't halt the CPU.
+         * For conditional branch insns this is harmless unreachable code as
+         * gen_goto_tb() has already handled emitting the debug exception
+         * (and thus a tb-jump is not possible when singlestepping).
+         */
+        assert(dc->base.is_jmp != DISAS_TB_JUMP);
+        if (dc->base.is_jmp != DISAS_JUMP) {
+            gen_a64_set_pc_im(dc->pc);
+        }
+        if (dc->base.singlestep_enabled) {
+            gen_exception_internal(EXCP_DEBUG);
+        } else {
+            gen_step_complete_exception(dc);
+        }
+    } else {
+        switch (dc->base.is_jmp) {
+        case DISAS_NEXT:
+        case DISAS_TOO_MANY:
+            gen_goto_tb(dc, 1, dc->pc);
+            break;
+        default:
+        case DISAS_UPDATE:
+            gen_a64_set_pc_im(dc->pc);
+            /* fall through */
+        case DISAS_JUMP:
+            tcg_gen_lookup_and_goto_ptr(cpu_pc);
+            break;
+        case DISAS_EXIT:
+            tcg_gen_exit_tb(0);
+            break;
+        case DISAS_TB_JUMP:
+        case DISAS_EXC:
+        case DISAS_SWI:
+            break;
+        case DISAS_WFE:
+            gen_a64_set_pc_im(dc->pc);
+            gen_helper_wfe(cpu_env);
+            break;
+        case DISAS_YIELD:
+            gen_a64_set_pc_im(dc->pc);
+            gen_helper_yield(cpu_env);
+            break;
+        case DISAS_WFI:
+            /* This is a special case because we don't want to just halt the CPU
+             * if trying to debug across a WFI.
+             */
+            gen_a64_set_pc_im(dc->pc);
+            gen_helper_wfi(cpu_env);
+            /* The helper doesn't necessarily throw an exception, but we
+             * must go back to the main loop to check for interrupts anyway.
+             */
+            tcg_gen_exit_tb(0);
+            break;
+        }
+    }
+}
+
 void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
                                TranslationBlock *tb)
 {
@@ -11398,68 +11461,12 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
          */
     } while (!dc->base.is_jmp);
 
+    aarch64_trblock_tb_stop(&dc->base, cs);
+
     if (dc->base.tb->cflags & CF_LAST_IO) {
         gen_io_end();
     }
 
-    if (unlikely(cs->singlestep_enabled || dc->ss_active)
-        && dc->base.is_jmp != DISAS_EXC) {
-        /* Note that this means single stepping WFI doesn't halt the CPU.
-         * For conditional branch insns this is harmless unreachable code as
-         * gen_goto_tb() has already handled emitting the debug exception
-         * (and thus a tb-jump is not possible when singlestepping).
-         */
-        assert(dc->base.is_jmp != DISAS_TB_JUMP);
-        if (dc->base.is_jmp != DISAS_JUMP) {
-            gen_a64_set_pc_im(dc->pc);
-        }
-        if (cs->singlestep_enabled) {
-            gen_exception_internal(EXCP_DEBUG);
-        } else {
-            gen_step_complete_exception(dc);
-        }
-    } else {
-        switch (dc->base.is_jmp) {
-        case DISAS_NEXT:
-        case DISAS_TOO_MANY:
-            gen_goto_tb(dc, 1, dc->pc);
-            break;
-        default:
-        case DISAS_UPDATE:
-            gen_a64_set_pc_im(dc->pc);
-            /* fall through */
-        case DISAS_JUMP:
-            tcg_gen_lookup_and_goto_ptr(cpu_pc);
-            break;
-        case DISAS_EXIT:
-            tcg_gen_exit_tb(0);
-            break;
-        case DISAS_TB_JUMP:
-        case DISAS_EXC:
-        case DISAS_SWI:
-            break;
-        case DISAS_WFE:
-            gen_a64_set_pc_im(dc->pc);
-            gen_helper_wfe(cpu_env);
-            break;
-        case DISAS_YIELD:
-            gen_a64_set_pc_im(dc->pc);
-            gen_helper_yield(cpu_env);
-            break;
-        case DISAS_WFI:
-            /* This is a special case because we don't want to just halt the CPU
-             * if trying to debug across a WFI.
-             */
-            gen_a64_set_pc_im(dc->pc);
-            gen_helper_wfi(cpu_env);
-            /* The helper doesn't necessarily throw an exception, but we
-             * must go back to the main loop to check for interrupts anyway.
-             */
-            tcg_gen_exit_tb(0);
-            break;
-        }
-    }
-
 done_generating:
     gen_tb_end(tb, dc->base.num_insns);
 

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 27/29] target/arm: [tcg] Port to disas_log
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (25 preceding siblings ...)
  2017-06-28 14:01 ` [Qemu-devel] [PATCH v11 26/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-06-28 14:05 ` Lluís Vilanova
  2017-07-02  1:49   ` Richard Henderson
  2017-06-28 14:09 ` [Qemu-devel] [PATCH v11 28/29] target/arm: [tcg, a64] " Lluís Vilanova
  2017-06-28 14:13 ` [Qemu-devel] [PATCH v11 29/29] target/arm: [tcg] Port to generic translation framework Lluís Vilanova
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 14:05 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate.c |   13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index ef0b870a2f..30dacee139 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -12138,6 +12138,15 @@ static void arm_trblock_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
     }
 }
 
+static void arm_trblock_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
+    log_target_disas(cpu, dc->base.pc_first, dc->pc - dc->base.pc_first,
+                     dc->thumb | (dc->sctlr_b << 1));
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -12241,9 +12250,7 @@ done_generating:
         qemu_log_in_addr_range(dc->base.pc_first)) {
         qemu_log_lock();
         qemu_log("----------------\n");
-        qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
-        log_target_disas(cpu, dc->base.pc_first, dc->pc - dc->base.pc_first,
-                         dc->thumb | (dc->sctlr_b << 1));
+        arm_trblock_disas_log(&dc->base, cpu);
         qemu_log("\n");
         qemu_log_unlock();
     }

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 28/29] target/arm: [tcg, a64] Port to disas_log
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (26 preceding siblings ...)
  2017-06-28 14:05 ` [Qemu-devel] [PATCH v11 27/29] target/arm: [tcg] Port to disas_log Lluís Vilanova
@ 2017-06-28 14:09 ` Lluís Vilanova
  2017-07-02  1:50   ` Richard Henderson
  2017-06-28 14:13 ` [Qemu-devel] [PATCH v11 29/29] target/arm: [tcg] Port to generic translation framework Lluís Vilanova
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 14:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate-a64.c |   14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index c57f475dc0..cc8bbb2b44 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11379,6 +11379,16 @@ static void aarch64_trblock_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
     }
 }
 
+static void aarch64_trblock_disas_log(const DisasContextBase *dcbase,
+                                      CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
+    log_target_disas(cpu, dc->base.pc_first, dc->pc - dc->base.pc_first,
+                     4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
+}
+
 void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
                                TranslationBlock *tb)
 {
@@ -11475,9 +11485,7 @@ done_generating:
         qemu_log_in_addr_range(dc->base.pc_first)) {
         qemu_log_lock();
         qemu_log("----------------\n");
-        qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
-        log_target_disas(cs, dc->base.pc_first, dc->pc - dc->base.pc_first,
-                         4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
+        aarch64_trblock_disas_log(&dc->base, cs);
         qemu_log("\n");
         qemu_log_unlock();
     }

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH v11 29/29] target/arm: [tcg] Port to generic translation framework
  2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (27 preceding siblings ...)
  2017-06-28 14:09 ` [Qemu-devel] [PATCH v11 28/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-06-28 14:13 ` Lluís Vilanova
  2017-07-02  1:54   ` Richard Henderson
  28 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-06-28 14:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: Emilio G. Cota, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell, open list:ARM

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target/arm/translate-a64.c |  125 +++++++-------------------------------------
 target/arm/translate.c     |  124 +++++++-------------------------------------
 target/arm/translate.h     |    8 ---
 3 files changed, 42 insertions(+), 215 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index cc8bbb2b44..84d32ca547 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11250,6 +11250,14 @@ static void aarch64_trblock_init_disas_context(DisasContextBase *dcbase,
     init_tmp_a64_array(dc);
 }
 
+static void aarch64_trblock_init_globals(DisasContextBase *db, CPUState *cpu)
+{
+}
+
+static void aarch64_trblock_tb_start(DisasContextBase *db, CPUState *cpu)
+{
+}
+
 static void aarch64_trblock_insn_start(DisasContextBase *dcbase, CPUState *cpu)
 {
     DisasContext *dc = container_of(dcbase, DisasContext, base);
@@ -11377,6 +11385,9 @@ static void aarch64_trblock_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
             break;
         }
     }
+
+    /* Functions above can change dc->pc, so re-align db->pc_next */
+    dc->base.pc_next = dc->pc;
 }
 
 static void aarch64_trblock_disas_log(const DisasContextBase *dcbase,
@@ -11389,107 +11400,13 @@ static void aarch64_trblock_disas_log(const DisasContextBase *dcbase,
                      4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
 }
 
-void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
-                               TranslationBlock *tb)
-{
-    DisasContext *dc = container_of(dcbase, DisasContext, base);
-    int max_insns;
-
-    dc->base.tb = tb;
-    dc->base.pc_first = dc->base.tb->pc;
-    dc->base.pc_next = dc->base.pc_first;
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.num_insns = 0;
-    dc->base.singlestep_enabled = cs->singlestep_enabled;
-    aarch64_trblock_init_disas_context(&dc->base, cs);
-
-    max_insns = dc->base.tb->cflags & CF_COUNT_MASK;
-    if (max_insns == 0) {
-        max_insns = CF_COUNT_MASK;
-    }
-    if (max_insns > TCG_MAX_INSNS) {
-        max_insns = TCG_MAX_INSNS;
-    }
-
-    gen_tb_start(tb);
-
-    tcg_clear_temp_count();
-
-    do {
-        dc->base.num_insns++;
-        aarch64_trblock_insn_start(&dc->base, cs);
-
-        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
-            CPUBreakpoint *bp;
-            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
-                if (bp->pc == dc->base.pc_next) {
-                    BreakpointCheckType bp_check =
-                        aarch64_trblock_breakpoint_check(&dc->base, cs, bp);
-                    switch (bp_check) {
-                    case BC_MISS:
-                        /* Target ignored this breakpoint, go to next */
-                        break;
-                    case BC_HIT_INSN:
-                        /* Hit, keep translating */
-                        /*
-                         * TODO: if we're never going to have more than one
-                         *       BP in a single address, we can simply use a
-                         *       bool here.
-                         */
-                        goto done_breakpoints;
-                    case BC_HIT_TB:
-                        /* Hit, end TB */
-                        goto done_generating;
-                    default:
-                        g_assert_not_reached();
-                    }
-                }
-            }
-        }
-    done_breakpoints:
-
-        if (dc->base.num_insns == max_insns && (dc->base.tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
-        }
-
-        dc->base.pc_next = aarch64_trblock_translate_insn(&dc->base, cs);
-
-        if (tcg_check_temp_count()) {
-            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
-                    dc->pc);
-        }
-
-        if (!dc->base.is_jmp && (tcg_op_buf_full() || cs->singlestep_enabled ||
-                            singlestep || dc->base.num_insns >= max_insns)) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-        }
-
-        /* Translation stops when a conditional branch is encountered.
-         * Otherwise the subsequent code could get translated several times.
-         * Also stop translation when a page boundary is reached.  This
-         * ensures prefetch aborts occur at the right place.
-         */
-    } while (!dc->base.is_jmp);
-
-    aarch64_trblock_tb_stop(&dc->base, cs);
-
-    if (dc->base.tb->cflags & CF_LAST_IO) {
-        gen_io_end();
-    }
-
-done_generating:
-    gen_tb_end(tb, dc->base.num_insns);
-
-#ifdef DEBUG_DISAS
-    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
-        qemu_log_in_addr_range(dc->base.pc_first)) {
-        qemu_log_lock();
-        qemu_log("----------------\n");
-        aarch64_trblock_disas_log(&dc->base, cs);
-        qemu_log("\n");
-        qemu_log_unlock();
-    }
-#endif
-    dc->base.tb->size = dc->pc - dc->base.pc_first;
-    dc->base.tb->icount = dc->base.num_insns;
-}
+const TranslatorOps aarch64_translator_ops = {
+    .init_disas_context = aarch64_trblock_init_disas_context,
+    .init_globals = aarch64_trblock_init_globals,
+    .tb_start = aarch64_trblock_tb_start,
+    .insn_start = aarch64_trblock_insn_start,
+    .breakpoint_check = aarch64_trblock_breakpoint_check,
+    .translate_insn = aarch64_trblock_translate_insn,
+    .tb_stop = aarch64_trblock_tb_stop,
+    .disas_log = aarch64_trblock_disas_log,
+};
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 30dacee139..323cbac672 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -12136,6 +12136,9 @@ static void arm_trblock_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
             gen_goto_tb(dc, 1, dc->pc);
         }
     }
+
+    /* Functions above can change dc->pc, so re-align db->pc_next */
+    dc->base.pc_next = dc->pc;
 }
 
 static void arm_trblock_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
@@ -12147,116 +12150,29 @@ static void arm_trblock_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
                      dc->thumb | (dc->sctlr_b << 1));
 }
 
+static const TranslatorOps arm_translator_ops = {
+    .init_disas_context = arm_trblock_init_disas_context,
+    .init_globals = arm_trblock_init_globals,
+    .tb_start = arm_trblock_tb_start,
+    .insn_start = arm_trblock_insn_start,
+    .breakpoint_check = arm_trblock_breakpoint_check,
+    .translate_insn = arm_trblock_translate_insn,
+    .tb_stop = arm_trblock_tb_stop,
+    .disas_log = arm_trblock_disas_log,
+};
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
     DisasContext dc1, *dc = &dc1;
-    int max_insns;
-
-    /* generate intermediate code */
-
-    /* The A64 decoder has its own top level loop, because it doesn't need
-     * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
-     */
-    if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
-        gen_intermediate_code_a64(&dc->base, cpu, tb);
-        return;
-    }
-
-    dc->base.tb = tb;
-    dc->base.pc_first = dc->base.tb->pc;
-    dc->base.pc_next = dc->base.pc_first;
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.num_insns = 0;
-    dc->base.singlestep_enabled = cpu->singlestep_enabled;
-    arm_trblock_init_disas_context(&dc->base, cpu);
-
 
-    arm_trblock_init_globals(&dc->base, cpu);
-    max_insns = tb->cflags & CF_COUNT_MASK;
-    if (max_insns == 0) {
-        max_insns = CF_COUNT_MASK;
-    }
-    if (max_insns > TCG_MAX_INSNS) {
-        max_insns = TCG_MAX_INSNS;
-    }
-
-    gen_tb_start(tb);
-
-    tcg_clear_temp_count();
-    arm_trblock_tb_start(&dc->base, cpu);
-
-    do {
-        dc->base.num_insns++;
-        arm_trblock_insn_start(&dc->base, cpu);
-
-        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
-            CPUBreakpoint *bp;
-            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
-                if (bp->pc == dc->base.pc_next) {
-                    BreakpointCheckType bp_check =
-                        arm_trblock_breakpoint_check(&dc->base, cpu, bp);
-                    switch (bp_check) {
-                    case BC_MISS:
-                        /* Target ignored this breakpoint, go to next */
-                        break;
-                    case BC_HIT_INSN:
-                        /* Hit, keep translating */
-                        /*
-                         * TODO: if we're never going to have more than one
-                         *       BP in a single address, we can simply use a
-                         *       bool here.
-                         */
-                        goto done_breakpoints;
-                    case BC_HIT_TB:
-                        /* Hit, end TB */
-                        goto done_generating;
-                    default:
-                        g_assert_not_reached();
-                    }
-                }
-            }
-        }
-    done_breakpoints:
-
-        if (dc->base.num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
-        }
-
-        dc->base.pc_next = arm_trblock_translate_insn(&dc->base, cpu);
-
-        if (tcg_check_temp_count()) {
-            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
-                    dc->pc);
-        }
-
-        if (!dc->base.is_jmp && (tcg_op_buf_full() || singlestep ||
-                            dc->base.num_insns >= max_insns)) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-        }
-    } while (!dc->base.is_jmp);
-
-    arm_trblock_tb_stop(&dc->base, cpu);
-
-    if (dc->base.tb->cflags & CF_LAST_IO) {
-        gen_io_end();
-    }
-
-done_generating:
-    gen_tb_end(tb, dc->base.num_insns);
-
-#ifdef DEBUG_DISAS
-    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
-        qemu_log_in_addr_range(dc->base.pc_first)) {
-        qemu_log_lock();
-        qemu_log("----------------\n");
-        arm_trblock_disas_log(&dc->base, cpu);
-        qemu_log("\n");
-        qemu_log_unlock();
-    }
+    translate_block(
+#ifdef TARGET_AARCH64
+        ARM_TBFLAG_AARCH64_STATE(tb->flags) ?
+        &aarch64_translator_ops :
 #endif
-    tb->size = dc->pc - dc->base.pc_first;
-    tb->icount = dc->base.num_insns;
+        &arm_translator_ops,
+        &dc->base, cpu, tb);
 }
 
 static const char *cpu_mode_names[16] = {
diff --git a/target/arm/translate.h b/target/arm/translate.h
index f830775540..f0912ecc96 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -155,21 +155,15 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);
-void gen_intermediate_code_a64(DisasContextBase *db, CPUState *cpu,
-                               TranslationBlock *tb);
 void gen_a64_set_pc_im(uint64_t val);
 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
                             fprintf_function cpu_fprintf, int flags);
+extern const TranslatorOps aarch64_translator_ops;
 #else
 static inline void a64_translate_init(void)
 {
 }
 
-static inline void gen_intermediate_code_a64(DisasContextBase *db, CPUState *cpu,
-                                             TranslationBlock *tb)
-{
-}
-
 static inline void gen_a64_set_pc_im(uint64_t val)
 {
 }

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 01/29] Pass generic CPUState to gen_intermediate_code()
  2017-06-28 12:20 ` [Qemu-devel] [PATCH v11 01/29] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
@ 2017-06-29 22:52   ` Emilio G. Cota
  2017-06-30 18:46     ` Richard Henderson
  2017-07-01 22:44   ` Richard Henderson
  1 sibling, 1 reply; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-29 22:52 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell,
	Edgar E. Iglesias, Eduardo Habkost, Michael Walle,
	Laurent Vivier, Aurelien Jarno, Yongbok Kim, Anthony Green,
	Chris Wulff, Marek Vasut, Stafford Horne, David Gibson,
	Alexander Graf, Mark Cave-Ayland, Artyom Tarasenko,
	Bastian Koppelmann, Guan Xuetao, Max Filippov, open list:ARM,
	open list:PowerPC

On Wed, Jun 28, 2017 at 15:20:42 +0300, Lluís Vilanova wrote:
> Needed to implement a target-agnostic gen_intermediate_code() in the
> future.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
> Reviewed-by: Richard Henderson <rth@twiddle.net>
> ---
(snip)
> -void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
> +void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
>  {
> -    AlphaCPU *cpu = alpha_env_get_cpu(env);
> -    CPUState *cs = CPU(cpu);
> +    CPUAlphaState *env = cpu->env_ptr;

I'd keep the original variable names, i.e. cs for CPUState in this case,
just like you did for a64:

> -void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
> +void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
>  {
> -    CPUState *cs = CPU(cpu);
> -    CPUARMState *env = &cpu->env;
> +    CPUARMState *env = cs->env_ptr;
> +    ARMCPU *cpu = arm_env_get_cpu(env);

This will keep the diff size to a minimum.

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 02/29] cpu-exec: Avoid global variables in icount-related functions
  2017-06-28 12:24 ` [Qemu-devel] [PATCH v11 02/29] cpu-exec: Avoid global variables in icount-related functions Lluís Vilanova
@ 2017-06-29 22:56   ` Emilio G. Cota
  0 siblings, 0 replies; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-29 22:56 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini

On Wed, Jun 28, 2017 at 15:24:44 +0300, Lluís Vilanova wrote:
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
(snip)
> @@ -62,14 +62,14 @@ static void gen_tb_end(TranslationBlock *tb, int num_insns)
>  static inline void gen_io_start(void)
>  {
>      TCGv_i32 tmp = tcg_const_i32(1);
> -    tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
> +    tcg_gen_st_i32(tmp, tcg_ctx.tcg_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
>      tcg_temp_free_i32(tmp);
>  }
>  
>  static inline void gen_io_end(void)
>  {
>      TCGv_i32 tmp = tcg_const_i32(0);
> -    tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
> +    tcg_gen_st_i32(tmp, tcg_ctx.tcg_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
>      tcg_temp_free_i32(tmp);

If you break these long lines as in this patch, you'll avoid a merge
conflict with it (it's been queued):
  [PATCH v2 2/2] gen-icount: use tcg_ctx.tcg_env instead of cpu_env
  https://patchwork.kernel.org/patch/9793381/

Or just pick up that patch verbatim.

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 03/29] target: [tcg] Use a generic enum for DISAS_ values
  2017-06-28 12:28 ` [Qemu-devel] [PATCH v11 03/29] target: [tcg] Use a generic enum for DISAS_ values Lluís Vilanova
@ 2017-06-29 23:09   ` Emilio G. Cota
  2017-07-01 22:48   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-29 23:09 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Peter Maydell,
	Edgar E. Iglesias, Eduardo Habkost, Michael Walle,
	Laurent Vivier, Chris Wulff, Marek Vasut, Stafford Horne,
	Alexander Graf, Guan Xuetao, Max Filippov, open list:ARM

On Wed, Jun 28, 2017 at 15:28:46 +0300, Lluís Vilanova wrote:
> Used later. An enum makes expected values explicit and bounds the value space of
> switches.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>

Reviewed-by: Emilio G. Cota <cota@braap.org>

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 05/29] target/i386: [tcg] Port to DisasContextBase
  2017-06-28 12:36 ` [Qemu-devel] [PATCH v11 05/29] target/i386: [tcg] Port to DisasContextBase Lluís Vilanova
@ 2017-06-29 23:33   ` Emilio G. Cota
  2017-07-01 23:39   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-29 23:33 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

On Wed, Jun 28, 2017 at 15:36:50 +0300, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>

Reviewed-by: Emilio G. Cota <cota@braap.org>

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 06/29] target/i386: [tcg] Refactor init_disas_context
  2017-06-28 12:40 ` [Qemu-devel] [PATCH v11 06/29] target/i386: [tcg] Refactor init_disas_context Lluís Vilanova
@ 2017-06-29 23:51   ` Emilio G. Cota
  2017-07-07  7:41     ` Lluís Vilanova
  2017-07-01 23:50   ` Richard Henderson
  1 sibling, 1 reply; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-29 23:51 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

On Wed, Jun 28, 2017 at 15:40:52 +0300, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
>  target/i386/translate.c |   43 ++++++++++++++++++++++++-------------------
>  1 file changed, 24 insertions(+), 19 deletions(-)
> 
> diff --git a/target/i386/translate.c b/target/i386/translate.c
> index 8cf2485e2c..04453ce48a 100644
> --- a/target/i386/translate.c
> +++ b/target/i386/translate.c
> @@ -8379,20 +8379,12 @@ void tcg_x86_init(void)
>      }
>  }
>  
> -/* generate intermediate code for basic block 'tb'.  */
> -void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
> +static void i386_trblock_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)

Or just i386_tr_init_(..) -- this brings the line under 80 characters.

>  {
> +    DisasContext *dc = container_of(dcbase, DisasContext, base);
>      CPUX86State *env = cpu->env_ptr;
> -    DisasContext dc1, *dc = &dc1;
> -    uint32_t flags;
> -    target_ulong cs_base;
> -    int num_insns;
> -    int max_insns;
> -
> -    /* generate intermediate code */
> -    dc->base.pc_first = tb->pc;
> -    cs_base = tb->cs_base;
> -    flags = tb->flags;
> +    uint32_t flags = dc->base.tb->flags;
> +    target_ulong cs_base = dc->base.tb->cs_base;
>  
>      dc->pe = (flags >> HF_PE_SHIFT) & 1;
>      dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
> @@ -8403,11 +8395,9 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
>      dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
>      dc->iopl = (flags >> IOPL_SHIFT) & 3;
>      dc->tf = (flags >> TF_SHIFT) & 1;
> -    dc->base.singlestep_enabled = cpu->singlestep_enabled;
>      dc->cc_op = CC_OP_DYNAMIC;
>      dc->cc_op_dirty = false;
>      dc->cs_base = cs_base;
> -    dc->base.tb = tb;
>      dc->popl_esp_hack = 0;
>      /* select memory access functions */
>      dc->mem_index = 0;
> @@ -8425,7 +8415,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
>      dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
>  #endif
>      dc->flags = flags;
> -    dc->jmp_opt = !(dc->tf || cpu->singlestep_enabled ||
> +    dc->jmp_opt = !(dc->tf || dc->base.singlestep_enabled ||

Why this change and not leaving cpu->singlestep_enabled?

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework
  2017-06-28 12:32 ` [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework Lluís Vilanova
@ 2017-06-30  0:02   ` Emilio G. Cota
  2017-07-01 22:57     ` Richard Henderson
  2017-06-30  1:18   ` Emilio G. Cota
  2017-07-01 23:37   ` Richard Henderson
  2 siblings, 1 reply; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-30  0:02 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini

On Wed, Jun 28, 2017 at 15:32:48 +0300, Lluís Vilanova wrote:
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
>  accel/tcg/Makefile.objs   |    1 
>  accel/tcg/translator.c    |  153 +++++++++++++++++++++++++++++++++++++++++++++
>  include/exec/gen-icount.h |    2 -
>  include/exec/translator.h |  104 +++++++++++++++++++++++++++++++
(snip)
> +/**
> + * BreakpointCheckType:
> + * @BC_MISS: No hit
> + * @BC_HIT_INSN: Hit, but continue translating TB
> + * @BC_HIT_TB: Hit, stop translating TB
> + *
> + * How to react to a breakpoint. A hit means no more breakpoints will be checked
> + * for the current instruction.
> + *
> + * Not all breakpoints associated to an address are necessarily raised by
> + * targets (e.g., due to conditions encoded in their flags), so tey can decide
s/tey/they/

> + * that a breakpoint missed the address (@BP_MISS).
> + */
> +typedef enum BreakpointCheckType {
> +    BC_MISS,
> +    BC_HIT_INSN,
> +    BC_HIT_TB,
> +} BreakpointCheckType;
> +
>  /**
>   * DisasJumpType:
>   * @DISAS_NEXT: Next instruction in program order.
> @@ -33,6 +65,78 @@ typedef enum DisasJumpType {
>      DISAS_TARGET_9,
>      DISAS_TARGET_10,
>      DISAS_TARGET_11,
> +    DISAS_TARGET_12,
> +    DISAS_TARGET_13,
> +    DISAS_TARGET_14,
>  } DisasJumpType;
>  
> +/**
> + * DisasContextBase:
> + * @tb: Translation block for this disassembly.
> + * @pc_first: Address of first guest instruction in this TB.
> + * @pc_next: Address of next guest instruction in this TB (current during
> + *           disassembly).
> + * @is_jmp: What instruction to disassemble next.
> + * @num_insns: Number of translated instructions (including current).
> + * @singlestep_enabled: "Hardware" single stepping enabled.
> + *
> + * Architecture-agnostic disassembly context.
> + */
> +typedef struct DisasContextBase {
> +    TranslationBlock *tb;
> +    target_ulong pc_first;
> +    target_ulong pc_next;
> +    DisasJumpType is_jmp;
> +    unsigned int num_insns;
> +    bool singlestep_enabled;
> +} DisasContextBase;
> +
> +/**
> + * TranslatorOps:
> + * @init_disas_context: Initialize a DisasContext struct (DisasContextBase has
> + *                      already been initialized).
> + * @init_globals: Initialize global variables.
> + * @tb_start: Start translating a new TB.
> + * @insn_start: Start translating a new instruction.
> + * @breakpoint_check: Check if a breakpoint did hit. When called, the breakpoint
> + *                    has already been checked to match the PC.
> + * @disas_insn: Disassemble one instruction an return the PC for the next

s/disas_insn/translate_insn/
s/an return/and return/

> + *              one. Can set db->is_jmp to DJ_TARGET or above to stop

s/DJ_TARGET/DISAS_TARGET/

> + *              translation.
> + * @tb_stop: Stop translating a TB.
> + * @disas_flags: Get flags argument for log_target_disas().

s/disas_flags/disas_log/

> + *
> + * Target-specific operations for the generic translator loop.
> + */
> +typedef struct TranslatorOps {
> +    void (*init_disas_context)(DisasContextBase *db, CPUState *cpu);
> +    void (*init_globals)(DisasContextBase *db, CPUState *cpu);
> +    void (*tb_start)(DisasContextBase *db, CPUState *cpu);
> +    void (*insn_start)(DisasContextBase *db, CPUState *cpu);
> +    BreakpointCheckType (*breakpoint_check)(DisasContextBase *db, CPUState *cpu,
> +                                            const CPUBreakpoint *bp);
> +    target_ulong (*translate_insn)(DisasContextBase *db, CPUState *cpu);
> +    void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
> +    void (*disas_log)(const DisasContextBase *db, CPUState *cpu);
> +} TranslatorOps;
> +
> +/**
> + * translate_block:
> + * @ops: Target-specific operations.
> + * @db: Disassembly context.
> + * @cpu: Target vCPU.
> + * @tb: Translation block.
> + *
> + * Generic translator loop.
> + *
> + * Translation will stop in the following cases (in order):
> + * - When set by #TranslatorOps::insn_start.
> + * - When set by #TranslatorOps::translate_insn.
> + * - When the TCG operation buffer is full.
> + * - When single-stepping is enabled (system-wide or on the current vCPU).
> + * - When too many instructions have been translated.
> + */
> +void translate_block(const TranslatorOps *ops, DisasContextBase *db,
> +                     CPUState *cpu, TranslationBlock *tb);

I'd rather avoid "block" here. Some alternatives:

- tb_translate()
- translate_tb()
- translate()
- translator_gen()
- translator_loop()

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 07/29] target/i386: [tcg] Refactor init_globals
  2017-06-28 12:44 ` [Qemu-devel] [PATCH v11 07/29] target/i386: [tcg] Refactor init_globals Lluís Vilanova
@ 2017-06-30  0:06   ` Emilio G. Cota
  2017-07-02  0:25   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-30  0:06 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

On Wed, Jun 28, 2017 at 15:44:54 +0300, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
>  target/i386/translate.c |   29 +++++++++++++++++------------
>  1 file changed, 17 insertions(+), 12 deletions(-)
> 
> diff --git a/target/i386/translate.c b/target/i386/translate.c
> index 04453ce48a..d015ea73fa 100644
> --- a/target/i386/translate.c
> +++ b/target/i386/translate.c
> @@ -8435,6 +8435,22 @@ static void i386_trblock_init_disas_context(DisasContextBase *dcbase, CPUState *
>  #endif
>  }
>  
> +static void i386_trblock_init_globals(DisasContextBase *dcbase, CPUState *cpu)

I'd do the s/trblock/tr/ conversion to all other patches. But I won't
mention it again :)

Reviewed-by: Emilio G. Cota <cota@braap.org>

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 08/29] target/i386: [tcg] Refactor insn_start
  2017-06-28 12:48 ` [Qemu-devel] [PATCH v11 08/29] target/i386: [tcg] Refactor insn_start Lluís Vilanova
@ 2017-06-30  0:08   ` Emilio G. Cota
  2017-07-02  0:26   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-30  0:08 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

On Wed, Jun 28, 2017 at 15:48:56 +0300, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>

Reviewed-by: Emilio G. Cota <cota@braap.org>

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 09/29] target/i386: [tcg] Refactor breakpoint_check
  2017-06-28 12:52 ` [Qemu-devel] [PATCH v11 09/29] target/i386: [tcg] Refactor breakpoint_check Lluís Vilanova
@ 2017-06-30  0:24   ` Emilio G. Cota
  2017-07-02  0:28   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-30  0:24 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

On Wed, Jun 28, 2017 at 15:52:58 +0300, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
>  target/i386/translate.c |   59 ++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 48 insertions(+), 11 deletions(-)
> 
> diff --git a/target/i386/translate.c b/target/i386/translate.c
> index ad57be2928..3eee348de7 100644
> --- a/target/i386/translate.c
> +++ b/target/i386/translate.c
> @@ -18,6 +18,7 @@
>   */
>  #include "qemu/osdep.h"
>  
> +#include "qemu/error-report.h"

I can't find why this one is included here.

>  #include "qemu/host-utils.h"
>  #include "cpu.h"
>  #include "disas/disas.h"
> @@ -8458,6 +8459,25 @@ static void i386_trblock_insn_start(DisasContextBase *dcbase, CPUState *cpu)
>      tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
>  }
>  
> +static BreakpointCheckType i386_trblock_breakpoint_check(
> +    DisasContextBase *dcbase, CPUState *cpu, const CPUBreakpoint *bp)
> +{
> +    DisasContext *dc = container_of(dcbase, DisasContext, base);
> +    /* If RF is set, suppress an internally generated breakpoint.  */
> +    int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
> +    if (bp->flags & flags) {
> +        gen_debug(dc, dc->base.pc_next - dc->cs_base);
> +        /* 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 += 1;
> +        return BC_HIT_TB;
> +    } else {
> +        return BC_MISS;
> +    }
> +}
> +
>  /* generate intermediate code for basic block 'tb'.  */
>  void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
>  {
> @@ -8490,18 +8510,35 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
>          i386_trblock_insn_start(&dc->base, cpu);
>          num_insns++;
>  
> -        /* If RF is set, suppress an internally generated breakpoint.  */
> -        if (unlikely(cpu_breakpoint_test(cpu, dc->base.pc_next,
> -                                         tb->flags & HF_RF_MASK
> -                                         ? BP_GDB : BP_ANY))) {
> -            gen_debug(dc, dc->base.pc_next - dc->cs_base);
> -            /* 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 += 1;
> -            goto done_generating;
> +        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
> +            CPUBreakpoint *bp;
> +            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
> +                if (bp->pc == dc->base.pc_next) {
> +                    BreakpointCheckType bp_check =
> +                        i386_trblock_breakpoint_check(&dc->base, cpu, bp);
> +                    switch (bp_check) {
> +                    case BC_MISS:
> +                        /* Target ignored this breakpoint, go to next */
> +                        break;
> +                    case BC_HIT_INSN:
> +                        /* Hit, keep translating */
> +                        /*
> +                         * TODO: if we're never going to have more than one
> +                         *       BP in a single address, we can simply use a
> +                         *       bool here.
> +                         */
> +                        goto done_breakpoints;

BC_HIT_INSN is not needed here, but I see what you're doing.

Reviewed-by: Emilio G. Cota <cota@braap.org>

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 10/29] target/i386: [tcg] Refactor translate_insn
  2017-06-28 12:57 ` [Qemu-devel] [PATCH v11 10/29] target/i386: [tcg] Refactor translate_insn Lluís Vilanova
@ 2017-06-30  0:41   ` Emilio G. Cota
  2017-07-07  9:25     ` Lluís Vilanova
  2017-07-02  0:41   ` Richard Henderson
  1 sibling, 1 reply; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-30  0:41 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

On Wed, Jun 28, 2017 at 15:57:00 +0300, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
>  target/i386/translate.c |   72 +++++++++++++++++++++++++++++++----------------
>  1 file changed, 48 insertions(+), 24 deletions(-)
> 
> diff --git a/target/i386/translate.c b/target/i386/translate.c
> index 3eee348de7..da4b409d97 100644
> --- a/target/i386/translate.c
> +++ b/target/i386/translate.c
> @@ -4420,15 +4420,17 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
>  
>  /* convert one instruction. s->base.is_jmp is set if the translation must
>     be stopped. Return the next pc value */
> -static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
> -                               target_ulong pc_start)
> +static target_ulong disas_insn(DisasContextBase *dcbase, CPUState *cpu)
>  {
> +    DisasContext *s = container_of(dcbase, DisasContext, base);
> +    CPUX86State *env = cpu->env_ptr;

Minor nit: you can pass dc (*s) here directly, no need for container_of

(snip)
> +static target_ulong i386_trblock_translate_insn(DisasContextBase *dcbase,
> +                                                CPUState *cpu)
> +{
> +    DisasContext *dc = container_of(dcbase, DisasContext, base);
> +    target_ulong pc_next = disas_insn(&dc->base, cpu);
> +
> +    if (dc->base.is_jmp) {
> +        return pc_next;
> +    }
> +
> +    if (dc->tf || (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
> +        /* if single step mode, we generate only one instruction and
> +           generate an exception */
> +        /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
> +           the flag and abort the translation to give the irqs a
> +           change to be happen */

I know you just moved lines around, but while at it, s/change to be/chance to/

Other than that,

Reviewed-by: Emilio G. Cota <cota@braap.org>

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 11/29] target/i386: [tcg] Refactor tb_stop
  2017-06-28 13:01 ` [Qemu-devel] [PATCH v11 11/29] target/i386: [tcg] Refactor tb_stop Lluís Vilanova
@ 2017-06-30  0:47   ` Emilio G. Cota
  2017-07-02  0:47   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-30  0:47 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

On Wed, Jun 28, 2017 at 16:01:02 +0300, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>

Reviewed-by: Emilio G. Cota <cota@braap.org>

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 12/29] target/i386: [tcg] Refactor disas_log
  2017-06-28 13:05 ` [Qemu-devel] [PATCH v11 12/29] target/i386: [tcg] Refactor disas_log Lluís Vilanova
@ 2017-06-30  0:50   ` Emilio G. Cota
  2017-07-02  0:49   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-30  0:50 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

On Wed, Jun 28, 2017 at 16:05:04 +0300, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>

Reviewed-by: Emilio G. Cota <cota@braap.org>

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 13/29] target/i386: [tcg] Port to generic translation framework
  2017-06-28 13:09 ` [Qemu-devel] [PATCH v11 13/29] target/i386: [tcg] Port to generic translation framework Lluís Vilanova
@ 2017-06-30  1:11   ` Emilio G. Cota
  2017-07-07 10:27     ` Lluís Vilanova
  2017-07-07 10:29     ` Lluís Vilanova
  2017-07-02  0:52   ` Richard Henderson
  1 sibling, 2 replies; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-30  1:11 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini, Eduardo Habkost

On Wed, Jun 28, 2017 at 16:09:06 +0300, Lluís Vilanova wrote:
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---

Reviewed-by: Emilio G. Cota <cota@braap.org>
Tested-by: Emilio G. Cota <cota@braap.org>

BTW have you tested icount mode?

Minor nits below.

>  target/i386/translate.c |  120 +++++++----------------------------------------
>  1 file changed, 18 insertions(+), 102 deletions(-)
> 
> diff --git a/target/i386/translate.c b/target/i386/translate.c
> index 3950fe95a4..295be26a95 100644
> --- a/target/i386/translate.c
> +++ b/target/i386/translate.c
(snip)
> @@ -8544,111 +8548,23 @@ static void i386_trblock_disas_log(const DisasContextBase *dcbase,
>  
>  }
>  
> +static const TranslatorOps i386_trblock_ops = {
> +    .init_disas_context = i386_trblock_init_disas_context,
> +    .init_globals = i386_trblock_init_globals,
> +    .tb_start = i386_trblock_tb_start,
> +    .insn_start = i386_trblock_insn_start,
> +    .breakpoint_check = i386_trblock_breakpoint_check,
> +    .translate_insn = i386_trblock_translate_insn,
> +    .tb_stop = i386_trblock_tb_stop,
> +    .disas_log = i386_trblock_disas_log,
> +};

I like hard tabs here, which make things visually easier, e.g.:

> +static const TranslatorOps i386_trblock_ops = {
> +    .init_disas_context	= i386_trblock_init_disas_context,
> +    .init_globals		= i386_trblock_init_globals,

Don't know whether checkpatch likes it, but I do, and I see some
examples in the code base.

>  /* generate intermediate code for basic block 'tb'.  */
>  void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
>  {
(snip)
> +    DisasContext dc1;
>  
> -    tb->size = dc->base.pc_next - dc->base.pc_first;
> -    tb->icount = num_insns;
> +    translate_block(&i386_trblock_ops, &dc1.base, cpu, tb);
>  }

I'd just call it dc, then.

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework
  2017-06-28 12:32 ` [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework Lluís Vilanova
  2017-06-30  0:02   ` Emilio G. Cota
@ 2017-06-30  1:18   ` Emilio G. Cota
  2017-07-01 23:37   ` Richard Henderson
  2 siblings, 0 replies; 100+ messages in thread
From: Emilio G. Cota @ 2017-06-30  1:18 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson,
	Peter Crosthwaite, Paolo Bonzini

On Wed, Jun 28, 2017 at 15:32:48 +0300, Lluís Vilanova wrote:
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
(snip)
>  /**
>   * DisasJumpType:
>   * @DISAS_NEXT: Next instruction in program order.
> @@ -33,6 +65,78 @@ typedef enum DisasJumpType {
>      DISAS_TARGET_9,
>      DISAS_TARGET_10,
>      DISAS_TARGET_11,
> +    DISAS_TARGET_12,
> +    DISAS_TARGET_13,
> +    DISAS_TARGET_14,
>  } DisasJumpType;

These belong in patch 3.

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 01/29] Pass generic CPUState to gen_intermediate_code()
  2017-06-29 22:52   ` Emilio G. Cota
@ 2017-06-30 18:46     ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-06-30 18:46 UTC (permalink / raw)
  To: Emilio G. Cota, Lluís Vilanova
  Cc: qemu-devel, Alex Bennée, Peter Crosthwaite, Paolo Bonzini,
	Peter Maydell, Edgar E. Iglesias, Eduardo Habkost, Michael Walle,
	Laurent Vivier, Aurelien Jarno, Yongbok Kim, Anthony Green,
	Chris Wulff, Marek Vasut, Stafford Horne, David Gibson,
	Alexander Graf, Mark Cave-Ayland, Artyom Tarasenko,
	Bastian Koppelmann, Guan Xuetao, Max Filippov, open list:ARM,
	open list:PowerPC

On 06/29/2017 03:52 PM, Emilio G. Cota wrote:
> On Wed, Jun 28, 2017 at 15:20:42 +0300, Lluís Vilanova wrote:
>> Needed to implement a target-agnostic gen_intermediate_code() in the
>> future.
>>
>> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
>> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
>> Reviewed-by: Richard Henderson <rth@twiddle.net>
>> ---
> (snip)
>> -void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
>> +void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
>>   {
>> -    AlphaCPU *cpu = alpha_env_get_cpu(env);
>> -    CPUState *cs = CPU(cpu);
>> +    CPUAlphaState *env = cpu->env_ptr;
> 
> I'd keep the original variable names, i.e. cs for CPUState in this case,
> just like you did for a64:
> 
>> -void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
>> +void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
>>   {
>> -    CPUState *cs = CPU(cpu);
>> -    CPUARMState *env = &cpu->env;
>> +    CPUARMState *env = cs->env_ptr;
>> +    ARMCPU *cpu = arm_env_get_cpu(env);
> 
> This will keep the diff size to a minimum.

I asked for the same thing many revisions ago.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 01/29] Pass generic CPUState to gen_intermediate_code()
  2017-06-28 12:20 ` [Qemu-devel] [PATCH v11 01/29] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
  2017-06-29 22:52   ` Emilio G. Cota
@ 2017-07-01 22:44   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-01 22:44 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Anthony Green, Mark Cave-Ayland, Max Filippov,
	Edgar E. Iglesias, Guan Xuetao, Marek Vasut, Alexander Graf,
	Emilio G. Cota, Artyom Tarasenko, Eduardo Habkost, open list:ARM,
	Yongbok Kim, Stafford Horne, Alex Bennée, David Gibson,
	Peter Crosthwaite, Bastian Koppelmann, Chris Wulff,
	Laurent Vivier, Michael Walle, open list:PowerPC, Paolo Bonzini,
	Aurelien Jarno

On 06/28/2017 05:20 AM, Lluís Vilanova wrote:
> -void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb);
> +void gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);

Ought to change the argument name too.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 03/29] target: [tcg] Use a generic enum for DISAS_ values
  2017-06-28 12:28 ` [Qemu-devel] [PATCH v11 03/29] target: [tcg] Use a generic enum for DISAS_ values Lluís Vilanova
  2017-06-29 23:09   ` Emilio G. Cota
@ 2017-07-01 22:48   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-01 22:48 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Marek Vasut, Peter Maydell, Eduardo Habkost, Peter Crosthwaite,
	Chris Wulff, Laurent Vivier, Alexander Graf, Max Filippov,
	Michael Walle, Emilio G. Cota, open list:ARM, Edgar E. Iglesias,
	Paolo Bonzini, Stafford Horne, Guan Xuetao, Alex Bennée

On 06/28/2017 05:28 AM, Lluís Vilanova wrote:
> Used later. An enum makes expected values explicit and bounds the value space of
> switches.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   include/exec/exec-all.h       |    6 ------
>   include/exec/translator.h     |   38 ++++++++++++++++++++++++++++++++++++++
>   target/arm/translate.h        |   26 ++++++++++++++++----------
>   target/cris/translate.c       |    7 ++++++-
>   target/i386/translate.c       |    4 ++++
>   target/lm32/translate.c       |    6 ++++++
>   target/m68k/translate.c       |    7 ++++++-
>   target/microblaze/translate.c |    6 ++++++
>   target/nios2/translate.c      |    6 ++++++
>   target/openrisc/translate.c   |    6 ++++++
>   target/s390x/translate.c      |    3 ++-
>   target/unicore32/translate.c  |    7 ++++++-
>   target/xtensa/translate.c     |    4 ++++
>   13 files changed, 106 insertions(+), 20 deletions(-)
>   create mode 100644 include/exec/translator.h

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework
  2017-06-30  0:02   ` Emilio G. Cota
@ 2017-07-01 22:57     ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-01 22:57 UTC (permalink / raw)
  To: Emilio G. Cota, Lluís Vilanova
  Cc: Paolo Bonzini, Peter Crosthwaite, Alex Bennée, qemu-devel

On 06/29/2017 05:02 PM, Emilio G. Cota wrote:
>> +void translate_block(const TranslatorOps *ops, DisasContextBase *db,
>> +                     CPUState *cpu, TranslationBlock *tb);
> I'd rather avoid "block" here. Some alternatives:
> 
> - tb_translate()
> - translate_tb()
> - translate()
> - translator_gen()
> - translator_loop()

I like translator_loop.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework
  2017-06-28 12:32 ` [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework Lluís Vilanova
  2017-06-30  0:02   ` Emilio G. Cota
  2017-06-30  1:18   ` Emilio G. Cota
@ 2017-07-01 23:37   ` Richard Henderson
  2017-07-04 18:59     ` Lluís Vilanova
  2 siblings, 1 reply; 100+ messages in thread
From: Richard Henderson @ 2017-07-01 23:37 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Paolo Bonzini, Peter Crosthwaite, Emilio G. Cota, Alex Bennée

On 06/28/2017 05:32 AM, Lluís Vilanova wrote:
> +    void (*init_disas_context)(DisasContextBase *db, CPUState *cpu);
> +    void (*init_globals)(DisasContextBase *db, CPUState *cpu);
> +    void (*tb_start)(DisasContextBase *db, CPUState *cpu);
> +    void (*insn_start)(DisasContextBase *db, CPUState *cpu);
> +    BreakpointCheckType (*breakpoint_check)(DisasContextBase *db, CPUState *cpu,
> +                                            const CPUBreakpoint *bp);
> +    target_ulong (*translate_insn)(DisasContextBase *db, CPUState *cpu);
> +    void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
> +    void (*disas_log)(const DisasContextBase *db, CPUState *cpu);

Any reason not to stuff the cpu pointer into the DisasContextBase instead of 
passing it around separately?

Otherwise,

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 05/29] target/i386: [tcg] Port to DisasContextBase
  2017-06-28 12:36 ` [Qemu-devel] [PATCH v11 05/29] target/i386: [tcg] Port to DisasContextBase Lluís Vilanova
  2017-06-29 23:33   ` Emilio G. Cota
@ 2017-07-01 23:39   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-01 23:39 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Eduardo Habkost, Peter Crosthwaite, Emilio G. Cota,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 05:36 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/i386/translate.c |  142 +++++++++++++++++++++++------------------------
>   1 file changed, 70 insertions(+), 72 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 06/29] target/i386: [tcg] Refactor init_disas_context
  2017-06-28 12:40 ` [Qemu-devel] [PATCH v11 06/29] target/i386: [tcg] Refactor init_disas_context Lluís Vilanova
  2017-06-29 23:51   ` Emilio G. Cota
@ 2017-07-01 23:50   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-01 23:50 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Eduardo Habkost, Peter Crosthwaite, Emilio G. Cota,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 05:40 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/i386/translate.c |   43 ++++++++++++++++++++++++-------------------
>   1 file changed, 24 insertions(+), 19 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 07/29] target/i386: [tcg] Refactor init_globals
  2017-06-28 12:44 ` [Qemu-devel] [PATCH v11 07/29] target/i386: [tcg] Refactor init_globals Lluís Vilanova
  2017-06-30  0:06   ` Emilio G. Cota
@ 2017-07-02  0:25   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  0:25 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Eduardo Habkost, Peter Crosthwaite, Emilio G. Cota,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 05:44 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/i386/translate.c |   29 +++++++++++++++++------------
>   1 file changed, 17 insertions(+), 12 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 08/29] target/i386: [tcg] Refactor insn_start
  2017-06-28 12:48 ` [Qemu-devel] [PATCH v11 08/29] target/i386: [tcg] Refactor insn_start Lluís Vilanova
  2017-06-30  0:08   ` Emilio G. Cota
@ 2017-07-02  0:26   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  0:26 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Eduardo Habkost, Peter Crosthwaite, Emilio G. Cota,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 05:48 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/i386/translate.c |    9 ++++++++-
>   1 file changed, 8 insertions(+), 1 deletion(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 09/29] target/i386: [tcg] Refactor breakpoint_check
  2017-06-28 12:52 ` [Qemu-devel] [PATCH v11 09/29] target/i386: [tcg] Refactor breakpoint_check Lluís Vilanova
  2017-06-30  0:24   ` Emilio G. Cota
@ 2017-07-02  0:28   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  0:28 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Eduardo Habkost, Peter Crosthwaite, Emilio G. Cota,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 05:52 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/i386/translate.c |   59 ++++++++++++++++++++++++++++++++++++++---------
>   1 file changed, 48 insertions(+), 11 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 10/29] target/i386: [tcg] Refactor translate_insn
  2017-06-28 12:57 ` [Qemu-devel] [PATCH v11 10/29] target/i386: [tcg] Refactor translate_insn Lluís Vilanova
  2017-06-30  0:41   ` Emilio G. Cota
@ 2017-07-02  0:41   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  0:41 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Eduardo Habkost, Peter Crosthwaite, Emilio G. Cota,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 05:57 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/i386/translate.c |   72 +++++++++++++++++++++++++++++++----------------
>   1 file changed, 48 insertions(+), 24 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 11/29] target/i386: [tcg] Refactor tb_stop
  2017-06-28 13:01 ` [Qemu-devel] [PATCH v11 11/29] target/i386: [tcg] Refactor tb_stop Lluís Vilanova
  2017-06-30  0:47   ` Emilio G. Cota
@ 2017-07-02  0:47   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  0:47 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Eduardo Habkost, Peter Crosthwaite, Emilio G. Cota,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:01 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/i386/translate.c |   26 ++++++++++++++------------
>   1 file changed, 14 insertions(+), 12 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 12/29] target/i386: [tcg] Refactor disas_log
  2017-06-28 13:05 ` [Qemu-devel] [PATCH v11 12/29] target/i386: [tcg] Refactor disas_log Lluís Vilanova
  2017-06-30  0:50   ` Emilio G. Cota
@ 2017-07-02  0:49   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  0:49 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Eduardo Habkost, Peter Crosthwaite, Emilio G. Cota,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:05 AM, Lluís Vilanova wrote:
> +#ifdef TARGET_X86_64
> +    if (dc->code64)
> +        disas_flags = 2;
> +    else
> +#endif
> +        disas_flags = !dc->code32;

Even though this is code movement, missing braces.

Otherwise,

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 13/29] target/i386: [tcg] Port to generic translation framework
  2017-06-28 13:09 ` [Qemu-devel] [PATCH v11 13/29] target/i386: [tcg] Port to generic translation framework Lluís Vilanova
  2017-06-30  1:11   ` Emilio G. Cota
@ 2017-07-02  0:52   ` Richard Henderson
  1 sibling, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  0:52 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Eduardo Habkost, Peter Crosthwaite, Emilio G. Cota,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:09 AM, Lluís Vilanova wrote:
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/i386/translate.c |  120 +++++++----------------------------------------
>   1 file changed, 18 insertions(+), 102 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 14/29] target/arm: [tcg] Port to DisasContextBase
  2017-06-28 13:13 ` [Qemu-devel] [PATCH v11 14/29] target/arm: [tcg] Port to DisasContextBase Lluís Vilanova
@ 2017-07-02  1:00   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:00 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:13 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/arm/translate-a64.c |  119 ++++++++++++++++++++++----------------------
>   target/arm/translate.c     |  114 +++++++++++++++++++++---------------------
>   target/arm/translate.h     |   11 ++--
>   3 files changed, 121 insertions(+), 123 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 15/29] target/arm: [tcg] Port to init_disas_context
  2017-06-28 13:17 ` [Qemu-devel] [PATCH v11 15/29] target/arm: [tcg] Port to init_disas_context Lluís Vilanova
@ 2017-07-02  1:04   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:04 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:17 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/arm/translate.c |   85 +++++++++++++++++++++++++++---------------------
>   1 file changed, 47 insertions(+), 38 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 16/29] target/arm: [tcg, a64] Port to init_disas_context
  2017-06-28 13:21 ` [Qemu-devel] [PATCH v11 16/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-07-02  1:13   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:13 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:21 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/arm/translate-a64.c |   36 ++++++++++++++++++++++--------------
>   1 file changed, 22 insertions(+), 14 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 17/29] target/arm: [tcg] Port to init_globals
  2017-06-28 13:25 ` [Qemu-devel] [PATCH v11 17/29] target/arm: [tcg] Port to init_globals Lluís Vilanova
@ 2017-07-02  1:14   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:14 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:25 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/arm/translate.c |   21 +++++++++++++--------
>   1 file changed, 13 insertions(+), 8 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 18/29] target/arm: [tcg] Port to tb_start
  2017-06-28 13:29 ` [Qemu-devel] [PATCH v11 18/29] target/arm: [tcg] Port to tb_start Lluís Vilanova
@ 2017-07-02  1:17   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:17 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:29 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/arm/translate.c |   82 ++++++++++++++++++++++++++----------------------
>   1 file changed, 44 insertions(+), 38 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 19/29] target/arm: [tcg] Port to insn_start
  2017-06-28 13:33 ` [Qemu-devel] [PATCH v11 19/29] target/arm: [tcg] Port to insn_start Lluís Vilanova
@ 2017-07-02  1:18   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:18 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:33 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/arm/translate.c |   34 ++++++++++++++++++++++------------
>   1 file changed, 22 insertions(+), 12 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 20/29] target/arm: [tcg, a64] Port to insn_start
  2017-06-28 13:37 ` [Qemu-devel] [PATCH v11 20/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-07-02  1:19   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:19 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:37 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/arm/translate-a64.c |   11 +++++++++--
>   1 file changed, 9 insertions(+), 2 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 21/29] target/arm: [tcg] Port to breakpoint_check
  2017-06-28 13:41 ` [Qemu-devel] [PATCH v11 21/29] target/arm: [tcg] Port to breakpoint_check Lluís Vilanova
@ 2017-07-02  1:21   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:21 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:41 AM, Lluís Vilanova wrote:
> -        if (unlikely(dc->base.is_jmp > DISAS_NEXT)) {
> -            break;
> -        }
> -

Surely this doesn't go away til the final conversion.

Otherwise,

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 22/29] target/arm: [tcg, a64] Port to breakpoint_check
  2017-06-28 13:45 ` [Qemu-devel] [PATCH v11 22/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-07-02  1:22   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:22 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:45 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/arm/translate-a64.c |   58 +++++++++++++++++++++++++++++++++-----------
>   1 file changed, 43 insertions(+), 15 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn
  2017-06-28 13:49 ` [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn Lluís Vilanova
@ 2017-07-02  1:34   ` Richard Henderson
  2017-07-07 11:13     ` Lluís Vilanova
  0 siblings, 1 reply; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:34 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:49 AM, Lluís Vilanova wrote:
> +        /* We want to stop the TB if the next insn starts in a new page,
> +         * or if it spans between this page and the next. This means that
> +         * if we're looking at the last halfword in the page we need to
> +         * see if it's a 16-bit Thumb insn (which will fit in this TB)
> +         * or a 32-bit Thumb insn (which won't).
> +         * This is to avoid generating a silly TB with a single 16-bit insn
> +         * in it at the end of this page (which would execute correctly
> +         * but isn't very efficient).
> +         */
> +        return DISAS_PAGE_CROSS;

Any reason to introduce a new name as opposed to TOO_MANY?  As far as I can 
tell they're the same....


> +    if (dc->ss_active && !dc->pstate_ss) {
> +        /* Singlestep state is Active-pending.
> +         * If we're in this state at the start of a TB then either
> +         *  a) we just took an exception to an EL which is being debugged
> +         *     and this is the first insn in the exception handler
> +         *  b) debug exceptions were masked and we just unmasked them
> +         *     without changing EL (eg by clearing PSTATE.D)
> +         * In either case we're going to take a swstep exception in the
> +         * "did not step an insn" case, and so the syndrome ISV and EX
> +         * bits should be zero.
> +         */
> +        assert(dc->base.num_insns == 1);
> +        gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
> +                      default_exception_el(dc));
> +        dc->base.is_jmp = DISAS_SKIP;

This is surely DISAS_EXC -- see gen_step_complete_exception.
Why introduce a new name?


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] Port to translate_insn
  2017-06-28 13:53 ` [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-07-02  1:42   ` Richard Henderson
  2017-07-07 11:18     ` Lluís Vilanova
  0 siblings, 1 reply; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:42 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:53 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
>   target/arm/translate-a64.c |   74 +++++++++++++++++++++++++++-----------------
>   1 file changed, 46 insertions(+), 28 deletions(-)
> 
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 9c870f6d07..586a01a2de 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -11244,6 +11244,9 @@ static void aarch64_trblock_init_disas_context(DisasContextBase *dcbase,
>       dc->is_ldex = false;
>       dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
>   
> +    dc->next_page_start =
> +        (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;

I think a better solution for a fixed-length ISA is to adjust max_insns. 
Perhaps the init_disas_context hook should be able to modify it?

And, while I'm thinking of it -- why is the init_globals hook separate? 
There's nothing in between the two hook calls, and the more modern target front 
ends won't need it.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 25/29] target/arm: [tcg] Port to tb_stop
  2017-06-28 13:57 ` [Qemu-devel] [PATCH v11 25/29] target/arm: [tcg] Port to tb_stop Lluís Vilanova
@ 2017-07-02  1:45   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:45 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 06:57 AM, Lluís Vilanova wrote:
> -    if (max_insns > TCG_MAX_INSNS) {
> -        max_insns = TCG_MAX_INSNS;
> +    if ((dc->base.tb->cflags & CF_LAST_IO) && dc->condjmp) {
> +        /* FIXME: This can theoretically happen with self-modifying code. */
> +        cpu_abort(cpu, "IO on conditional branch instruction");
>       }
...
> -        gen_io_end();
> +    if (dc->base.tb->cflags & CF_LAST_IO && dc->condjmp) {
> +        /* FIXME: This can theoretically happen with self-modifying code. */
> +        cpu_abort(cpu, "IO on conditional branch instruction");

Two copies of this code... sequentially, apparently?


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 26/29] target/arm: [tcg, a64] Port to tb_stop
  2017-06-28 14:01 ` [Qemu-devel] [PATCH v11 26/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-07-02  1:48   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:48 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 07:01 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/arm/translate-a64.c |  123 +++++++++++++++++++++++---------------------
>   1 file changed, 65 insertions(+), 58 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 27/29] target/arm: [tcg] Port to disas_log
  2017-06-28 14:05 ` [Qemu-devel] [PATCH v11 27/29] target/arm: [tcg] Port to disas_log Lluís Vilanova
@ 2017-07-02  1:49   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:49 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 07:05 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/arm/translate.c |   13 ++++++++++---
>   1 file changed, 10 insertions(+), 3 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 28/29] target/arm: [tcg, a64] Port to disas_log
  2017-06-28 14:09 ` [Qemu-devel] [PATCH v11 28/29] target/arm: [tcg, a64] " Lluís Vilanova
@ 2017-07-02  1:50   ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:50 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 07:09 AM, Lluís Vilanova wrote:
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova<vilanova@ac.upc.edu>
> ---
>   target/arm/translate-a64.c |   14 +++++++++++---
>   1 file changed, 11 insertions(+), 3 deletions(-)

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 29/29] target/arm: [tcg] Port to generic translation framework
  2017-06-28 14:13 ` [Qemu-devel] [PATCH v11 29/29] target/arm: [tcg] Port to generic translation framework Lluís Vilanova
@ 2017-07-02  1:54   ` Richard Henderson
  2017-07-07 11:26     ` Lluís Vilanova
  0 siblings, 1 reply; 100+ messages in thread
From: Richard Henderson @ 2017-07-02  1:54 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, Emilio G. Cota, open list:ARM,
	Paolo Bonzini, Alex Bennée

On 06/28/2017 07:13 AM, Lluís Vilanova wrote:
> @@ -11377,6 +11385,9 @@ static void aarch64_trblock_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
>               break;
>           }
>       }
> +
> +    /* Functions above can change dc->pc, so re-align db->pc_next */
> +    dc->base.pc_next = dc->pc;
>   }
>   
>   static void aarch64_trblock_disas_log(const DisasContextBase *dcbase,

Surely this belonged in a previous patch.


>      DisasContext dc1, *dc = &dc1;

Drop the dc1 thing.

> +    translate_block(
> +#ifdef TARGET_AARCH64
> +        ARM_TBFLAG_AARCH64_STATE(tb->flags) ?
> +        &aarch64_translator_ops :
>  #endif
> +        &arm_translator_ops,

It would be nicer to avoid the ifdef within the parameter list.
Maybe pull the ops pointer computation to a separate statement.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework
  2017-07-01 23:37   ` Richard Henderson
@ 2017-07-04 18:59     ` Lluís Vilanova
  2017-07-04 19:14       ` Peter Maydell
  0 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-04 18:59 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Paolo Bonzini, Peter Crosthwaite, Emilio G. Cota,
	Alex Bennée

Richard Henderson writes:

> On 06/28/2017 05:32 AM, Lluís Vilanova wrote:
>> +    void (*init_disas_context)(DisasContextBase *db, CPUState *cpu);
>> +    void (*init_globals)(DisasContextBase *db, CPUState *cpu);
>> +    void (*tb_start)(DisasContextBase *db, CPUState *cpu);
>> +    void (*insn_start)(DisasContextBase *db, CPUState *cpu);
>> +    BreakpointCheckType (*breakpoint_check)(DisasContextBase *db, CPUState *cpu,
>> +                                            const CPUBreakpoint *bp);
>> +    target_ulong (*translate_insn)(DisasContextBase *db, CPUState *cpu);
>> +    void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
>> +    void (*disas_log)(const DisasContextBase *db, CPUState *cpu);

> Any reason not to stuff the cpu pointer into the DisasContextBase instead of
> passing it around separately?

None, really. I'll move it from DisasContext (in targets where it's present)
into DisasContextBase, and use that one everywhere.


> Otherwise,

> Reviewed-by: Richard Henderson <rth@twiddle.net>


Thanks,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework
  2017-07-04 18:59     ` Lluís Vilanova
@ 2017-07-04 19:14       ` Peter Maydell
  2017-07-04 22:31         ` Richard Henderson
  0 siblings, 1 reply; 100+ messages in thread
From: Peter Maydell @ 2017-07-04 19:14 UTC (permalink / raw)
  To: Richard Henderson, QEMU Developers, Paolo Bonzini,
	Peter Crosthwaite, Emilio G. Cota, Alex Bennée

On 4 July 2017 at 19:59, Lluís Vilanova <vilanova@ac.upc.edu> wrote:
> Richard Henderson writes:
>
>> On 06/28/2017 05:32 AM, Lluís Vilanova wrote:
>>> +    void (*init_disas_context)(DisasContextBase *db, CPUState *cpu);
>>> +    void (*init_globals)(DisasContextBase *db, CPUState *cpu);
>>> +    void (*tb_start)(DisasContextBase *db, CPUState *cpu);
>>> +    void (*insn_start)(DisasContextBase *db, CPUState *cpu);
>>> +    BreakpointCheckType (*breakpoint_check)(DisasContextBase *db, CPUState *cpu,
>>> +                                            const CPUBreakpoint *bp);
>>> +    target_ulong (*translate_insn)(DisasContextBase *db, CPUState *cpu);
>>> +    void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
>>> +    void (*disas_log)(const DisasContextBase *db, CPUState *cpu);
>
>> Any reason not to stuff the cpu pointer into the DisasContextBase instead of
>> passing it around separately?
>
> None, really. I'll move it from DisasContext (in targets where it's present)
> into DisasContextBase, and use that one everywhere.

I kind of like not having CPUState* in DisasContext, because
it enforces the rule that you can't read from fields of
it inside the target translate.c code without jumping through
a hoop (ie copying the info from CPUState->foo to
DisasContext->foo). That then acts as a useful flag in code
review (or when writing the code) to confirm that foo really
is constant for the life of the simulation (or to recommend
using a TB flag instead).

thanks
-- PMM

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework
  2017-07-04 19:14       ` Peter Maydell
@ 2017-07-04 22:31         ` Richard Henderson
  2017-07-04 22:34           ` Peter Maydell
  0 siblings, 1 reply; 100+ messages in thread
From: Richard Henderson @ 2017-07-04 22:31 UTC (permalink / raw)
  To: Peter Maydell, QEMU Developers, Paolo Bonzini, Peter Crosthwaite,
	Emilio G. Cota, Alex Bennée

On 07/04/2017 09:14 AM, Peter Maydell wrote:
> On 4 July 2017 at 19:59, Lluís Vilanova <vilanova@ac.upc.edu> wrote:
>> Richard Henderson writes:
>>> Any reason not to stuff the cpu pointer into the DisasContextBase instead of
>>> passing it around separately?
>>
>> None, really. I'll move it from DisasContext (in targets where it's present)
>> into DisasContextBase, and use that one everywhere.
> 
> I kind of like not having CPUState* in DisasContext, because
> it enforces the rule that you can't read from fields of
> it inside the target translate.c code without jumping through
> a hoop (ie copying the info from CPUState->foo to
> DisasContext->foo). That then acts as a useful flag in code
> review (or when writing the code) to confirm that foo really
> is constant for the life of the simulation (or to recommend
> using a TB flag instead).

I don't see how the spelling "cpu" vs "dc->cpu" really affects that.

More practically, I don't see that "cpu" will actually be used by most of those 
hooks.  But because of things like cpu->some_target_feature, it's kind of hard 
to predict.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework
  2017-07-04 22:31         ` Richard Henderson
@ 2017-07-04 22:34           ` Peter Maydell
  0 siblings, 0 replies; 100+ messages in thread
From: Peter Maydell @ 2017-07-04 22:34 UTC (permalink / raw)
  To: Richard Henderson
  Cc: QEMU Developers, Paolo Bonzini, Peter Crosthwaite,
	Emilio G. Cota, Alex Bennée

On 4 July 2017 at 23:31, Richard Henderson <rth@twiddle.net> wrote:
> On 07/04/2017 09:14 AM, Peter Maydell wrote:
>> I kind of like not having CPUState* in DisasContext, because
>> it enforces the rule that you can't read from fields of
>> it inside the target translate.c code without jumping through
>> a hoop (ie copying the info from CPUState->foo to
>> DisasContext->foo). That then acts as a useful flag in code
>> review (or when writing the code) to confirm that foo really
>> is constant for the life of the simulation (or to recommend
>> using a TB flag instead).
>
>
> I don't see how the spelling "cpu" vs "dc->cpu" really affects that.

If you put it in dc->cpu then everywhere that gets the dc gets
the cpu, unavoidably (which is why I'm suggesting it would
be nicer not to do that). If you don't put it in dc then you
can structure your translate code so that pretty much all of
it gets the dc but not the cpu. target/arm/translate-a64.c
does this, for instance.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 06/29] target/i386: [tcg] Refactor init_disas_context
  2017-06-29 23:51   ` Emilio G. Cota
@ 2017-07-07  7:41     ` Lluís Vilanova
  0 siblings, 0 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-07  7:41 UTC (permalink / raw)
  To: Emilio G. Cota
  Cc: Eduardo Habkost, Peter Crosthwaite, qemu-devel, Paolo Bonzini,
	Alex Bennée, Richard Henderson

Emilio G Cota writes:

> On Wed, Jun 28, 2017 at 15:40:52 +0300, Lluís Vilanova wrote:
[,,,]
>> @@ -8425,7 +8415,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
>>      dc-> code64 = (flags >> HF_CS64_SHIFT) & 1;
>> #endif
>>      dc-> flags = flags;
>> -    dc->jmp_opt = !(dc->tf || cpu->singlestep_enabled ||
>> +    dc->jmp_opt = !(dc->tf || dc->base.singlestep_enabled ||

> Why this change and not leaving cpu->singlestep_enabled?

The single-stepping info is initialized by the generic code into dc->base, and
so I wanted to keep a bit more code consistency by unifying its use (on places I
touched). In fact, using dc->base ensures translation will be consistent even if
in the future cpu->singlestep_enabled is allowed to change.


Cheers,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 10/29] target/i386: [tcg] Refactor translate_insn
  2017-06-30  0:41   ` Emilio G. Cota
@ 2017-07-07  9:25     ` Lluís Vilanova
  2017-07-07 15:18       ` Richard Henderson
  0 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-07  9:25 UTC (permalink / raw)
  To: Emilio G. Cota
  Cc: Eduardo Habkost, Peter Crosthwaite, qemu-devel, Paolo Bonzini,
	Alex Bennée, Richard Henderson

Emilio G Cota writes:

> On Wed, Jun 28, 2017 at 15:57:00 +0300, Lluís Vilanova wrote:
>> Incrementally paves the way towards using the generic instruction translation
>> loop.
>> 
>> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
>> ---
>> target/i386/translate.c |   72 +++++++++++++++++++++++++++++++----------------
>> 1 file changed, 48 insertions(+), 24 deletions(-)
>> 
>> diff --git a/target/i386/translate.c b/target/i386/translate.c
>> index 3eee348de7..da4b409d97 100644
>> --- a/target/i386/translate.c
>> +++ b/target/i386/translate.c
>> @@ -4420,15 +4420,17 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
>> 
>> /* convert one instruction. s->base.is_jmp is set if the translation must
>> be stopped. Return the next pc value */
>> -static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
>> -                               target_ulong pc_start)
>> +static target_ulong disas_insn(DisasContextBase *dcbase, CPUState *cpu)
>> {
>> +    DisasContext *s = container_of(dcbase, DisasContext, base);
>> +    CPUX86State *env = cpu->env_ptr;

> Minor nit: you can pass dc (*s) here directly, no need for container_of
[...]

I prefer not to so that the code will work in the future (i.e., not assuming the
location of base inside disascontext).


Thanks,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 13/29] target/i386: [tcg] Port to generic translation framework
  2017-06-30  1:11   ` Emilio G. Cota
@ 2017-07-07 10:27     ` Lluís Vilanova
  2017-07-07 10:29     ` Lluís Vilanova
  1 sibling, 0 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-07 10:27 UTC (permalink / raw)
  To: Emilio G. Cota
  Cc: Eduardo Habkost, Peter Crosthwaite, qemu-devel, Paolo Bonzini,
	Alex Bennée, Richard Henderson

Emilio G Cota writes:

> On Wed, Jun 28, 2017 at 16:09:06 +0300, Lluís Vilanova wrote:
[...]
>> diff --git a/target/i386/translate.c b/target/i386/translate.c
>> index 3950fe95a4..295be26a95 100644
>> --- a/target/i386/translate.c
>> +++ b/target/i386/translate.c
> (snip)
>> @@ -8544,111 +8548,23 @@ static void i386_trblock_disas_log(const DisasContextBase *dcbase,
>> 
>> }
>> 
>> +static const TranslatorOps i386_trblock_ops = {
>> +    .init_disas_context = i386_trblock_init_disas_context,
>> +    .init_globals = i386_trblock_init_globals,
>> +    .tb_start = i386_trblock_tb_start,
>> +    .insn_start = i386_trblock_insn_start,
>> +    .breakpoint_check = i386_trblock_breakpoint_check,
>> +    .translate_insn = i386_trblock_translate_insn,
>> +    .tb_stop = i386_trblock_tb_stop,
>> +    .disas_log = i386_trblock_disas_log,
>> +};

> I like hard tabs here, which make things visually easier, e.g.:

>> +static const TranslatorOps i386_trblock_ops = {
>> +    .init_disas_context	= i386_trblock_init_disas_context,
>> +    .init_globals		= i386_trblock_init_globals,

> Don't know whether checkpatch likes it, but I do, and I see some
> examples in the code base.

According to the guidelines, not tabs should be used (and I'm assuming
checkpatch looks for that). The best I can do is to space-align these.


Thanks,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 13/29] target/i386: [tcg] Port to generic translation framework
  2017-06-30  1:11   ` Emilio G. Cota
  2017-07-07 10:27     ` Lluís Vilanova
@ 2017-07-07 10:29     ` Lluís Vilanova
  1 sibling, 0 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-07 10:29 UTC (permalink / raw)
  To: Emilio G. Cota
  Cc: Eduardo Habkost, Peter Crosthwaite, qemu-devel, Paolo Bonzini,
	Alex Bennée, Richard Henderson

Emilio G Cota writes:

> On Wed, Jun 28, 2017 at 16:09:06 +0300, Lluís Vilanova wrote:
>> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
>> ---

> Reviewed-by: Emilio G. Cota <cota@braap.org>
> Tested-by: Emilio G. Cota <cota@braap.org>

> BTW have you tested icount mode?

Yes. Regular, -singlestep and -icount 1.

Thanks,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn
  2017-07-02  1:34   ` Richard Henderson
@ 2017-07-07 11:13     ` Lluís Vilanova
  2017-07-07 15:26       ` Richard Henderson
  0 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-07 11:13 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

Richard Henderson writes:

> On 06/28/2017 06:49 AM, Lluís Vilanova wrote:
>> +        /* We want to stop the TB if the next insn starts in a new page,
>> +         * or if it spans between this page and the next. This means that
>> +         * if we're looking at the last halfword in the page we need to
>> +         * see if it's a 16-bit Thumb insn (which will fit in this TB)
>> +         * or a 32-bit Thumb insn (which won't).
>> +         * This is to avoid generating a silly TB with a single 16-bit insn
>> +         * in it at the end of this page (which would execute correctly
>> +         * but isn't very efficient).
>> +         */
>> +        return DISAS_PAGE_CROSS;

> Any reason to introduce a new name as opposed to TOO_MANY?  As far as I can tell
> they're the same....

Yes, DISAS_SS and DISAS_PAGE_CROSS turned out to be remnants of previous series.


>> +    if (dc->ss_active && !dc->pstate_ss) {
>> +        /* Singlestep state is Active-pending.
>> +         * If we're in this state at the start of a TB then either
>> +         *  a) we just took an exception to an EL which is being debugged
>> +         *     and this is the first insn in the exception handler
>> +         *  b) debug exceptions were masked and we just unmasked them
>> +         *     without changing EL (eg by clearing PSTATE.D)
>> +         * In either case we're going to take a swstep exception in the
>> +         * "did not step an insn" case, and so the syndrome ISV and EX
>> +         * bits should be zero.
>> +         */
>> +        assert(dc->base.num_insns == 1);
>> +        gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
>> +                      default_exception_el(dc));
>> +        dc->base.is_jmp = DISAS_SKIP;

> This is surely DISAS_EXC -- see gen_step_complete_exception.
> Why introduce a new name?

The original code goes straight to done_generating here, and that's the purpose
of DISAS_SKIP (skip the code executed between the end of the loop and the
done_generating label).


Thanks,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] Port to translate_insn
  2017-07-02  1:42   ` Richard Henderson
@ 2017-07-07 11:18     ` Lluís Vilanova
  2017-07-07 15:46       ` Richard Henderson
  0 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-07 11:18 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

Richard Henderson writes:

> On 06/28/2017 06:53 AM, Lluís Vilanova wrote:
>> Incrementally paves the way towards using the generic instruction translation
>> loop.
>> 
>> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
>> ---
>> target/arm/translate-a64.c |   74 +++++++++++++++++++++++++++-----------------
>> 1 file changed, 46 insertions(+), 28 deletions(-)
>> 
>> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
>> index 9c870f6d07..586a01a2de 100644
>> --- a/target/arm/translate-a64.c
>> +++ b/target/arm/translate-a64.c
>> @@ -11244,6 +11244,9 @@ static void aarch64_trblock_init_disas_context(DisasContextBase *dcbase,
dc-> is_ldex = false;
dc-> ss_same_el = (arm_debug_target_el(env) == dc->current_el);
>> +    dc->next_page_start =
>> +        (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;

> I think a better solution for a fixed-length ISA is to adjust max_insns. Perhaps
> the init_disas_context hook should be able to modify it?

ARM has the thumb instructions, so it really isn't a fixed-length ISA.


> And, while I'm thinking of it -- why is the init_globals hook separate? There's
> nothing in between the two hook calls, and the more modern target front ends
> won't need it.

You mean merging init_disas_context and init_globals? I wanted to keep
semantically different code on separate hooks, but I can pull the init_globals
code into init_disas_context (hoping that as targets get modernized, they won't
initialize any global there).


Thanks,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 29/29] target/arm: [tcg] Port to generic translation framework
  2017-07-02  1:54   ` Richard Henderson
@ 2017-07-07 11:26     ` Lluís Vilanova
  0 siblings, 0 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-07 11:26 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

Richard Henderson writes:

> On 06/28/2017 07:13 AM, Lluís Vilanova wrote:
>> @@ -11377,6 +11385,9 @@ static void aarch64_trblock_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
>> break;
>> }
>> }
>> +
>> +    /* Functions above can change dc->pc, so re-align db->pc_next */
>> +    dc->base.pc_next = dc->pc;
>> }
>> static void aarch64_trblock_disas_log(const DisasContextBase *dcbase,

> Surely this belonged in a previous patch.

No, there's pieces of the previous loop that used dc->pc (calculation of
tb->size at the end), and the generic one only has dc->base.pc_next now.


Thanks,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 10/29] target/i386: [tcg] Refactor translate_insn
  2017-07-07  9:25     ` Lluís Vilanova
@ 2017-07-07 15:18       ` Richard Henderson
  2017-07-07 17:05         ` Lluís Vilanova
  0 siblings, 1 reply; 100+ messages in thread
From: Richard Henderson @ 2017-07-07 15:18 UTC (permalink / raw)
  To: Emilio G. Cota, Eduardo Habkost, Peter Crosthwaite, qemu-devel,
	Paolo Bonzini, Alex Bennée

On 07/06/2017 11:25 PM, Lluís Vilanova wrote:
>>> /* convert one instruction. s->base.is_jmp is set if the translation must
>>> be stopped. Return the next pc value */
>>> -static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
>>> -                               target_ulong pc_start)
>>> +static target_ulong disas_insn(DisasContextBase *dcbase, CPUState *cpu)
>>> {
>>> +    DisasContext *s = container_of(dcbase, DisasContext, base);
>>> +    CPUX86State *env = cpu->env_ptr;
> 
>> Minor nit: you can pass dc (*s) here directly, no need for container_of
> [...]
> 
> I prefer not to so that the code will work in the future (i.e., not assuming the
> location of base inside disascontext).

There's clearly a misunderstanding here.

Emilio is saying that disas_insn is not a hook and private to the front-end. 
Therefore the argument to the function should be "DisasContet *s" and not 
"DisasContextBase *dcbase".

And I agree.  Passing DisasContext should be preferred where possible.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn
  2017-07-07 11:13     ` Lluís Vilanova
@ 2017-07-07 15:26       ` Richard Henderson
  2017-07-07 17:18         ` Lluís Vilanova
  2017-07-07 17:33         ` Peter Maydell
  0 siblings, 2 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-07 15:26 UTC (permalink / raw)
  To: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

On 07/07/2017 01:13 AM, Lluís Vilanova wrote:
>>> +    if (dc->ss_active && !dc->pstate_ss) {
>>> +        /* Singlestep state is Active-pending.
>>> +         * If we're in this state at the start of a TB then either
>>> +         *  a) we just took an exception to an EL which is being debugged
>>> +         *     and this is the first insn in the exception handler
>>> +         *  b) debug exceptions were masked and we just unmasked them
>>> +         *     without changing EL (eg by clearing PSTATE.D)
>>> +         * In either case we're going to take a swstep exception in the
>>> +         * "did not step an insn" case, and so the syndrome ISV and EX
>>> +         * bits should be zero.
>>> +         */
>>> +        assert(dc->base.num_insns == 1);
>>> +        gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
>>> +                      default_exception_el(dc));
>>> +        dc->base.is_jmp = DISAS_SKIP;
> 
>> This is surely DISAS_EXC -- see gen_step_complete_exception.
>> Why introduce a new name?
> 
> The original code goes straight to done_generating here, and that's the purpose
> of DISAS_SKIP (skip the code executed between the end of the loop and the
> done_generating label).

That is the purpose of DISAS_EXC too.  We've called a noreturn helper to raise 
an exception and all following code is unreached.  If there *was* any code 
being emitted afterward, that is arguably a bug.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] Port to translate_insn
  2017-07-07 11:18     ` Lluís Vilanova
@ 2017-07-07 15:46       ` Richard Henderson
  2017-07-07 16:19         ` Emilio G. Cota
  2017-07-07 17:32         ` Lluís Vilanova
  0 siblings, 2 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-07 15:46 UTC (permalink / raw)
  To: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

On 07/07/2017 01:18 AM, Lluís Vilanova wrote:
>>> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
>>> index 9c870f6d07..586a01a2de 100644
>>> --- a/target/arm/translate-a64.c
>>> +++ b/target/arm/translate-a64.c
>>> @@ -11244,6 +11244,9 @@ static void aarch64_trblock_init_disas_context(DisasContextBase *dcbase,
> dc-> is_ldex = false;
> dc-> ss_same_el = (arm_debug_target_el(env) == dc->current_el);
>>> +    dc->next_page_start =
>>> +        (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
> 
>> I think a better solution for a fixed-length ISA is to adjust max_insns. Perhaps
>> the init_disas_context hook should be able to modify it?
> 
> ARM has the thumb instructions, so it really isn't a fixed-length ISA.

 From the filename above we're talking about AArch64 here.
Whcih is most definitely a fixed-width ISA.


That said, even for AArch32 we know by the TB flags whether or not we're going 
to be generating arm or thumb code.  I think that these hooks will allow arm 
and thumb mode to finally be split apart cleanly, instead of the tangle that 
they are now.

I see arm's gen_intermediate_code eventually looking like

   const TranslatorOps *ops = &arm_translator_ops;
   if (ARM_TBFLAG_THUMB(tb->flags)) {
     ops = &thumb_translator_ops;
   }
#ifdef TARGET_AARCH64
   if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
     ops = &aarch64_translator_ops;
   }
#endif
   translator_loop(ops, &dc.base, cpu, tb);

There would certainly be some amount of shared code, but it would also allow 
quite a few of the existing dc->thumb checks to be eliminated.


>> And, while I'm thinking of it -- why is the init_globals hook separate? There's
>> nothing in between the two hook calls, and the more modern target front ends
>> won't need it.
> 
> You mean merging init_disas_context and init_globals? I wanted to keep
> semantically different code on separate hooks, but I can pull the init_globals
> code into init_disas_context (hoping that as targets get modernized, they won't
> initialize any global there).

I suppose you can leave the two hooks separate for now.  It doesn't hurt, and 
it's kind of a reminder of things that need cleaning up.

I do wonder if we should provide a generic empty hook, so that a target that 
does not need a particular hook need not define an empty function.  It could 
just put e.g. "translator_noop" into the structure.  Ok, maybe a better name 
than that...


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] Port to translate_insn
  2017-07-07 15:46       ` Richard Henderson
@ 2017-07-07 16:19         ` Emilio G. Cota
  2017-07-07 17:33           ` Lluís Vilanova
  2017-07-07 17:32         ` Lluís Vilanova
  1 sibling, 1 reply; 100+ messages in thread
From: Emilio G. Cota @ 2017-07-07 16:19 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Peter Maydell, Peter Crosthwaite, open list:ARM,
	Paolo Bonzini, Alex Bennée

On Fri, Jul 07, 2017 at 05:46:19 -1000, Richard Henderson wrote:
> I do wonder if we should provide a generic empty hook, so that a target that
> does not need a particular hook need not define an empty function.  It could
> just put e.g. "translator_noop" into the structure.  Ok, maybe a better name
> than that...

NULL would serve that purpose well. The subsequent "if (hook)" branch
would be essentially free because it'd be trivially predicted.

		E.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 10/29] target/i386: [tcg] Refactor translate_insn
  2017-07-07 15:18       ` Richard Henderson
@ 2017-07-07 17:05         ` Lluís Vilanova
  0 siblings, 0 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-07 17:05 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Emilio G. Cota, Eduardo Habkost, Peter Crosthwaite, qemu-devel,
	Paolo Bonzini, Alex Bennée

Richard Henderson writes:

> On 07/06/2017 11:25 PM, Lluís Vilanova wrote:
>>>> /* convert one instruction. s->base.is_jmp is set if the translation must
>>>> be stopped. Return the next pc value */
>>>> -static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
>>>> -                               target_ulong pc_start)
>>>> +static target_ulong disas_insn(DisasContextBase *dcbase, CPUState *cpu)
>>>> {
>>>> +    DisasContext *s = container_of(dcbase, DisasContext, base);
>>>> +    CPUX86State *env = cpu->env_ptr;
>> 
>>> Minor nit: you can pass dc (*s) here directly, no need for container_of
>> [...]
>> 
>> I prefer not to so that the code will work in the future (i.e., not assuming the
>> location of base inside disascontext).

> There's clearly a misunderstanding here.

> Emilio is saying that disas_insn is not a hook and private to the
> front-end. Therefore the argument to the function should be "DisasContet *s" and
> not "DisasContextBase *dcbase".

> And I agree.  Passing DisasContext should be preferred where possible.

Woooops, my bad! :)


Thanks,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn
  2017-07-07 15:26       ` Richard Henderson
@ 2017-07-07 17:18         ` Lluís Vilanova
  2017-07-07 17:38           ` Richard Henderson
  2017-07-07 17:33         ` Peter Maydell
  1 sibling, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-07 17:18 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

Richard Henderson writes:

> On 07/07/2017 01:13 AM, Lluís Vilanova wrote:
>>>> +    if (dc->ss_active && !dc->pstate_ss) {
>>>> +        /* Singlestep state is Active-pending.
>>>> +         * If we're in this state at the start of a TB then either
>>>> +         *  a) we just took an exception to an EL which is being debugged
>>>> +         *     and this is the first insn in the exception handler
>>>> +         *  b) debug exceptions were masked and we just unmasked them
>>>> +         *     without changing EL (eg by clearing PSTATE.D)
>>>> +         * In either case we're going to take a swstep exception in the
>>>> +         * "did not step an insn" case, and so the syndrome ISV and EX
>>>> +         * bits should be zero.
>>>> +         */
>>>> +        assert(dc->base.num_insns == 1);
>>>> +        gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
>>>> +                      default_exception_el(dc));
>>>> +        dc->base.is_jmp = DISAS_SKIP;
>> 
>>> This is surely DISAS_EXC -- see gen_step_complete_exception.
>>> Why introduce a new name?
>> 
>> The original code goes straight to done_generating here, and that's the purpose
>> of DISAS_SKIP (skip the code executed between the end of the loop and the
>> done_generating label).

> That is the purpose of DISAS_EXC too.  We've called a noreturn helper to raise
> an exception and all following code is unreached.  If there *was* any code being
> emitted afterward, that is arguably a bug.

There was no code being generated after this specific case, but I haven't
checked if DISAS_EXC is set in any other place that is not immediately followed
by a "goto done_generating".

Does this mean DISAS_EXC should be on the generic code and do a "goto
done_generating" whenever it is found? And if so, what are the correct places to
check for this? After ops->insn_start, ops->translate_insn, ops->tb_stop?


Thanks,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] Port to translate_insn
  2017-07-07 15:46       ` Richard Henderson
  2017-07-07 16:19         ` Emilio G. Cota
@ 2017-07-07 17:32         ` Lluís Vilanova
  2017-07-07 17:41           ` Richard Henderson
  1 sibling, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-07 17:32 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

Richard Henderson writes:

> On 07/07/2017 01:18 AM, Lluís Vilanova wrote:
>>>> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
>>>> index 9c870f6d07..586a01a2de 100644
>>>> --- a/target/arm/translate-a64.c
>>>> +++ b/target/arm/translate-a64.c
>>>> @@ -11244,6 +11244,9 @@ static void aarch64_trblock_init_disas_context(DisasContextBase *dcbase,
dc-> is_ldex = false;
dc-> ss_same_el = (arm_debug_target_el(env) == dc->current_el);
>>>> +    dc->next_page_start =
>>>> +        (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
>> 
>>> I think a better solution for a fixed-length ISA is to adjust max_insns. Perhaps
>>> the init_disas_context hook should be able to modify it?
>> 
>> ARM has the thumb instructions, so it really isn't a fixed-length ISA.

> From the filename above we're talking about AArch64 here.
> Whcih is most definitely a fixed-width ISA.


> That said, even for AArch32 we know by the TB flags whether or not we're going
> to be generating arm or thumb code.  I think that these hooks will allow arm and
> thumb mode to finally be split apart cleanly, instead of the tangle that they
> are now.

> I see arm's gen_intermediate_code eventually looking like

>   const TranslatorOps *ops = &arm_translator_ops;
>   if (ARM_TBFLAG_THUMB(tb->flags)) {
>     ops = &thumb_translator_ops;
>   }
> #ifdef TARGET_AARCH64
>   if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
>     ops = &aarch64_translator_ops;
>   }
> #endif
>   translator_loop(ops, &dc.base, cpu, tb);

> There would certainly be some amount of shared code, but it would also allow
> quite a few of the existing dc->thumb checks to be eliminated.

Does this really need to be addressed on this series?


>>> And, while I'm thinking of it -- why is the init_globals hook separate? There's
>>> nothing in between the two hook calls, and the more modern target front ends
>>> won't need it.
>> 
>> You mean merging init_disas_context and init_globals? I wanted to keep
>> semantically different code on separate hooks, but I can pull the init_globals
>> code into init_disas_context (hoping that as targets get modernized, they won't
>> initialize any global there).

> I suppose you can leave the two hooks separate for now.  It doesn't hurt, and
> it's kind of a reminder of things that need cleaning up.

Well, I've sent a (too rushed) v12 that features the merge. Since I'll have to
send a v13, I can split them again if you want.


> I do wonder if we should provide a generic empty hook, so that a target that
> does not need a particular hook need not define an empty function.  It could
> just put e.g. "translator_noop" into the structure.  Ok, maybe a better name
> than that...

I'm not really sure it's worth the effort. The original version trated NULLs as
a "skip this operation" (as Emilio suggests to revive), but after discussing the
approach it was decided that defining an empty function was not too much effort,
so that's what I went for.

I can restore the NULL approach or add a default empty hook implementation
(translator_ignored_op?) if there's a strong feeling to change it.


Cheers,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn
  2017-07-07 15:26       ` Richard Henderson
  2017-07-07 17:18         ` Lluís Vilanova
@ 2017-07-07 17:33         ` Peter Maydell
  2017-07-07 17:48           ` Richard Henderson
  1 sibling, 1 reply; 100+ messages in thread
From: Peter Maydell @ 2017-07-07 17:33 UTC (permalink / raw)
  To: Richard Henderson
  Cc: QEMU Developers, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

On 7 July 2017 at 16:26, Richard Henderson <rth@twiddle.net> wrote:
> That is the purpose of DISAS_EXC too.  We've called a noreturn helper to
> raise an exception and all following code is unreached.  If there *was* any
> code being emitted afterward, that is arguably a bug.

One exception to that is a conditionally executed
exception generating exception -- there will in that
case be a following label for the condfail case to branch
to and the code for the condfail path.

The distinction in the case that this code fragment is touching
is that the cases handled in current master via 'goto
done_generating' and in Lluis' patch as
DISAS_SKIP are the "this insn is going to generate an
exception without even thinking about conditional
exception" (ie breakpoints, singlestep); DISAS_EXC
is for "the instruction itself generates an exception,
so don't bother with emitting too much unreachable
code to update the PC etc, but we still need to handle
the usual end-of-insn condfail path".

We do a few things in the DISAS_EXC codepath
(like calling gen_set_condexec()) which strictly speaking
are pointless but which it didn't seem worth trying to
avoid just to avoid generating a few extra bytes in the
generated code in a not-terribly-likely case.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] Port to translate_insn
  2017-07-07 16:19         ` Emilio G. Cota
@ 2017-07-07 17:33           ` Lluís Vilanova
  0 siblings, 0 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-07 17:33 UTC (permalink / raw)
  To: Emilio G. Cota
  Cc: Richard Henderson, Peter Maydell, Peter Crosthwaite, qemu-devel,
	open list:ARM, Paolo Bonzini, Alex Bennée

Emilio G Cota writes:

> On Fri, Jul 07, 2017 at 05:46:19 -1000, Richard Henderson wrote:
>> I do wonder if we should provide a generic empty hook, so that a target that
>> does not need a particular hook need not define an empty function.  It could
>> just put e.g. "translator_noop" into the structure.  Ok, maybe a better name
>> than that...

> NULL would serve that purpose well. The subsequent "if (hook)" branch
> would be essentially free because it'd be trivially predicted.

Someone (Richard? can't remember exactly) already objected to using NULL.


Cheers,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn
  2017-07-07 17:18         ` Lluís Vilanova
@ 2017-07-07 17:38           ` Richard Henderson
  2017-07-10 13:47             ` Lluís Vilanova
  0 siblings, 1 reply; 100+ messages in thread
From: Richard Henderson @ 2017-07-07 17:38 UTC (permalink / raw)
  To: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

On 07/07/2017 07:18 AM, Lluís Vilanova wrote:
> There was no code being generated after this specific case, but I haven't
> checked if DISAS_EXC is set in any other place that is not immediately followed
> by a "goto done_generating".

Typically we haven't actually done a goto, but simply exit the loop and emit 
nothing within the final cleanup (tb_stop?).

> Does this mean DISAS_EXC should be on the generic code and do a "goto
> done_generating" whenever it is found? And if so, what are the correct places to
> check for this? After ops->insn_start, ops->translate_insn, ops->tb_stop?

Yes, this should be handled generically, since all targets need it.

That said, I would prefer a better name like DISAS_NORETURN, which does not 
imply that an actual exception has been raised, but explicitly says that all 
following code is dead.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] Port to translate_insn
  2017-07-07 17:32         ` Lluís Vilanova
@ 2017-07-07 17:41           ` Richard Henderson
  2017-07-11 15:56             ` Lluís Vilanova
  0 siblings, 1 reply; 100+ messages in thread
From: Richard Henderson @ 2017-07-07 17:41 UTC (permalink / raw)
  To: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

On 07/07/2017 07:32 AM, Lluís Vilanova wrote:
>> That said, even for AArch32 we know by the TB flags whether or not we're going
>> to be generating arm or thumb code.  I think that these hooks will allow arm and
>> thumb mode to finally be split apart cleanly, instead of the tangle that they
>> are now.
>> 
>> I see arm's gen_intermediate_code eventually looking like
>> 
>>    const TranslatorOps *ops = &arm_translator_ops;
>>    if (ARM_TBFLAG_THUMB(tb->flags)) {
>>      ops = &thumb_translator_ops;
>>    }
>> #ifdef TARGET_AARCH64
>>    if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
>>      ops = &aarch64_translator_ops;
>>    }
>> #endif
>>    translator_loop(ops, &dc.base, cpu, tb);
> 
>> There would certainly be some amount of shared code, but it would also allow
>> quite a few of the existing dc->thumb checks to be eliminated.
> 
> Does this really need to be addressed on this series?

No.  It is quite a tangle and it'll take some time to rectify.

>> I suppose you can leave the two hooks separate for now.  It doesn't hurt, and
>> it's kind of a reminder of things that need cleaning up.
> 
> Well, I've sent a (too rushed) v12 that features the merge. Since I'll have to
> send a v13, I can split them again if you want.

Don't go to any extra trouble if no one else has any strong feelings.

> I can restore the NULL approach or add a default empty hook implementation
> (translator_ignored_op?) if there's a strong feeling to change it.

Ok, we can work that out.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn
  2017-07-07 17:33         ` Peter Maydell
@ 2017-07-07 17:48           ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-07 17:48 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

On 07/07/2017 07:33 AM, Peter Maydell wrote:
> On 7 July 2017 at 16:26, Richard Henderson <rth@twiddle.net> wrote:
>> That is the purpose of DISAS_EXC too.  We've called a noreturn helper to
>> raise an exception and all following code is unreached.  If there *was* any
>> code being emitted afterward, that is arguably a bug.
> 
> One exception to that is a conditionally executed
> exception generating exception -- there will in that
> case be a following label for the condfail case to branch
> to and the code for the condfail path.
> 
> The distinction in the case that this code fragment is touching
> is that the cases handled in current master via 'goto
> done_generating' and in Lluis' patch as
> DISAS_SKIP are the "this insn is going to generate an
> exception without even thinking about conditional
> exception" (ie breakpoints, singlestep); DISAS_EXC
> is for "the instruction itself generates an exception,
> so don't bother with emitting too much unreachable
> code to update the PC etc, but we still need to handle
> the usual end-of-insn condfail path".

Ok.

LLuis, this implies that the DISAS_NORETURN that I talked about elsewhere 
should be the thing handled generically, but that target/arm still needs a 
target-specific define for DISAS_EXC so that the conditional execution handler 
can make the distinction.

> We do a few things in the DISAS_EXC codepath
> (like calling gen_set_condexec()) which strictly speaking
> are pointless but which it didn't seem worth trying to
> avoid just to avoid generating a few extra bytes in the
> generated code in a not-terribly-likely case.

Yeah.  We'd probably be better off just adding dead-code removal to TCG. 
Something that used to be difficult but would now be trivial to do.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn
  2017-07-07 17:38           ` Richard Henderson
@ 2017-07-10 13:47             ` Lluís Vilanova
  2017-07-10 15:28               ` Richard Henderson
  0 siblings, 1 reply; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-10 13:47 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

Richard Henderson writes:

> On 07/07/2017 07:18 AM, Lluís Vilanova wrote:
>> There was no code being generated after this specific case, but I haven't
>> checked if DISAS_EXC is set in any other place that is not immediately followed
>> by a "goto done_generating".

> Typically we haven't actually done a goto, but simply exit the loop and emit
> nothing within the final cleanup (tb_stop?).

The case handled by DISAS_SKIP ignores tb_stop() (the target code can simply
return when DISAS_EXC is found instead of DISAS_SKIP) *and* gen_io_end(); this
last one is never omitted when DISAS_EXC is found now, and theoretically
DISAS_EXC can be set by any target-specific hook. Thus my question if the
generic call to gen_io_end() should check for DISAS_EXC too (I have no idea if
it would be an error to call it with DISAS_EXC set, or whether it makes sense to
for a target to set it so that gen_io_start() is called but gen_io_end() is then
skipped by a DISAS_EXC set in ops->translate_insn()).


>> Does this mean DISAS_EXC should be on the generic code and do a "goto
>> done_generating" whenever it is found? And if so, what are the correct places to
>> check for this? After ops->insn_start, ops->translate_insn, ops->tb_stop?

> Yes, this should be handled generically, since all targets need it.

> That said, I would prefer a better name like DISAS_NORETURN, which does not
> imply that an actual exception has been raised, but explicitly says that all
> following code is dead.

I can use that name.

And in fact, generalizing DISAS_NORETURN will allow dropping the enum result of
breakpoint_check(), and instead simply return a bool (whether a breakpoint did
hit). Targets can then set DISAS_NORETURN and return true instead of returning
BC_HIT_TB (simply returning true is equivalent to the previous BC_HIT_INSN).


Cheers,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn
  2017-07-10 13:47             ` Lluís Vilanova
@ 2017-07-10 15:28               ` Richard Henderson
  0 siblings, 0 replies; 100+ messages in thread
From: Richard Henderson @ 2017-07-10 15:28 UTC (permalink / raw)
  To: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

On 07/10/2017 03:47 AM, Lluís Vilanova wrote:
> Richard Henderson writes:
> 
>> On 07/07/2017 07:18 AM, Lluís Vilanova wrote:
>>> There was no code being generated after this specific case, but I haven't
>>> checked if DISAS_EXC is set in any other place that is not immediately followed
>>> by a "goto done_generating".
> 
>> Typically we haven't actually done a goto, but simply exit the loop and emit
>> nothing within the final cleanup (tb_stop?).
> 
> The case handled by DISAS_SKIP ignores tb_stop() (the target code can simply
> return when DISAS_EXC is found instead of DISAS_SKIP) *and* gen_io_end(); this
> last one is never omitted when DISAS_EXC is found now, and theoretically
> DISAS_EXC can be set by any target-specific hook. Thus my question if the
> generic call to gen_io_end() should check for DISAS_EXC too (I have no idea if
> it would be an error to call it with DISAS_EXC set, or whether it makes sense to
> for a target to set it so that gen_io_start() is called but gen_io_end() is then
> skipped by a DISAS_EXC set in ops->translate_insn()).

It is not an error to call gen_io_start when gen_io_end isn't called (or isn't 
reached).  There are many ways that can happen.

The reason that arm does the goto after the gen_exception for single-stepping 
was simply convenience.  Nothing would have gone wrong if it had used

	dc->is_jmp = DISAS_EXC;
	break;

instead.


r~

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] Port to translate_insn
  2017-07-07 17:41           ` Richard Henderson
@ 2017-07-11 15:56             ` Lluís Vilanova
  0 siblings, 0 replies; 100+ messages in thread
From: Lluís Vilanova @ 2017-07-11 15:56 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Peter Maydell, Peter Crosthwaite, Emilio G. Cota,
	open list:ARM, Paolo Bonzini, Alex Bennée

Richard Henderson writes:

> On 07/07/2017 07:32 AM, Lluís Vilanova wrote:
[...]
>> I can restore the NULL approach or add a default empty hook implementation
>> (translator_ignored_op?) if there's a strong feeling to change it.

> Ok, we can work that out.

I'm not sure what you mean. Leave as-is (targets must define all hooks), ignore
NULLs as before, add a default empty implementation for each hook?


Cheers,
  Lluis

^ permalink raw reply	[flat|nested] 100+ messages in thread

end of thread, other threads:[~2017-07-11 15:57 UTC | newest]

Thread overview: 100+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-28 12:16 [Qemu-devel] [PATCH v11 00/29] translate: [tcg] Generic translation framework Lluís Vilanova
2017-06-28 12:20 ` [Qemu-devel] [PATCH v11 01/29] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
2017-06-29 22:52   ` Emilio G. Cota
2017-06-30 18:46     ` Richard Henderson
2017-07-01 22:44   ` Richard Henderson
2017-06-28 12:24 ` [Qemu-devel] [PATCH v11 02/29] cpu-exec: Avoid global variables in icount-related functions Lluís Vilanova
2017-06-29 22:56   ` Emilio G. Cota
2017-06-28 12:28 ` [Qemu-devel] [PATCH v11 03/29] target: [tcg] Use a generic enum for DISAS_ values Lluís Vilanova
2017-06-29 23:09   ` Emilio G. Cota
2017-07-01 22:48   ` Richard Henderson
2017-06-28 12:32 ` [Qemu-devel] [PATCH v11 04/29] target: [tcg] Add generic translation framework Lluís Vilanova
2017-06-30  0:02   ` Emilio G. Cota
2017-07-01 22:57     ` Richard Henderson
2017-06-30  1:18   ` Emilio G. Cota
2017-07-01 23:37   ` Richard Henderson
2017-07-04 18:59     ` Lluís Vilanova
2017-07-04 19:14       ` Peter Maydell
2017-07-04 22:31         ` Richard Henderson
2017-07-04 22:34           ` Peter Maydell
2017-06-28 12:36 ` [Qemu-devel] [PATCH v11 05/29] target/i386: [tcg] Port to DisasContextBase Lluís Vilanova
2017-06-29 23:33   ` Emilio G. Cota
2017-07-01 23:39   ` Richard Henderson
2017-06-28 12:40 ` [Qemu-devel] [PATCH v11 06/29] target/i386: [tcg] Refactor init_disas_context Lluís Vilanova
2017-06-29 23:51   ` Emilio G. Cota
2017-07-07  7:41     ` Lluís Vilanova
2017-07-01 23:50   ` Richard Henderson
2017-06-28 12:44 ` [Qemu-devel] [PATCH v11 07/29] target/i386: [tcg] Refactor init_globals Lluís Vilanova
2017-06-30  0:06   ` Emilio G. Cota
2017-07-02  0:25   ` Richard Henderson
2017-06-28 12:48 ` [Qemu-devel] [PATCH v11 08/29] target/i386: [tcg] Refactor insn_start Lluís Vilanova
2017-06-30  0:08   ` Emilio G. Cota
2017-07-02  0:26   ` Richard Henderson
2017-06-28 12:52 ` [Qemu-devel] [PATCH v11 09/29] target/i386: [tcg] Refactor breakpoint_check Lluís Vilanova
2017-06-30  0:24   ` Emilio G. Cota
2017-07-02  0:28   ` Richard Henderson
2017-06-28 12:57 ` [Qemu-devel] [PATCH v11 10/29] target/i386: [tcg] Refactor translate_insn Lluís Vilanova
2017-06-30  0:41   ` Emilio G. Cota
2017-07-07  9:25     ` Lluís Vilanova
2017-07-07 15:18       ` Richard Henderson
2017-07-07 17:05         ` Lluís Vilanova
2017-07-02  0:41   ` Richard Henderson
2017-06-28 13:01 ` [Qemu-devel] [PATCH v11 11/29] target/i386: [tcg] Refactor tb_stop Lluís Vilanova
2017-06-30  0:47   ` Emilio G. Cota
2017-07-02  0:47   ` Richard Henderson
2017-06-28 13:05 ` [Qemu-devel] [PATCH v11 12/29] target/i386: [tcg] Refactor disas_log Lluís Vilanova
2017-06-30  0:50   ` Emilio G. Cota
2017-07-02  0:49   ` Richard Henderson
2017-06-28 13:09 ` [Qemu-devel] [PATCH v11 13/29] target/i386: [tcg] Port to generic translation framework Lluís Vilanova
2017-06-30  1:11   ` Emilio G. Cota
2017-07-07 10:27     ` Lluís Vilanova
2017-07-07 10:29     ` Lluís Vilanova
2017-07-02  0:52   ` Richard Henderson
2017-06-28 13:13 ` [Qemu-devel] [PATCH v11 14/29] target/arm: [tcg] Port to DisasContextBase Lluís Vilanova
2017-07-02  1:00   ` Richard Henderson
2017-06-28 13:17 ` [Qemu-devel] [PATCH v11 15/29] target/arm: [tcg] Port to init_disas_context Lluís Vilanova
2017-07-02  1:04   ` Richard Henderson
2017-06-28 13:21 ` [Qemu-devel] [PATCH v11 16/29] target/arm: [tcg, a64] " Lluís Vilanova
2017-07-02  1:13   ` Richard Henderson
2017-06-28 13:25 ` [Qemu-devel] [PATCH v11 17/29] target/arm: [tcg] Port to init_globals Lluís Vilanova
2017-07-02  1:14   ` Richard Henderson
2017-06-28 13:29 ` [Qemu-devel] [PATCH v11 18/29] target/arm: [tcg] Port to tb_start Lluís Vilanova
2017-07-02  1:17   ` Richard Henderson
2017-06-28 13:33 ` [Qemu-devel] [PATCH v11 19/29] target/arm: [tcg] Port to insn_start Lluís Vilanova
2017-07-02  1:18   ` Richard Henderson
2017-06-28 13:37 ` [Qemu-devel] [PATCH v11 20/29] target/arm: [tcg, a64] " Lluís Vilanova
2017-07-02  1:19   ` Richard Henderson
2017-06-28 13:41 ` [Qemu-devel] [PATCH v11 21/29] target/arm: [tcg] Port to breakpoint_check Lluís Vilanova
2017-07-02  1:21   ` Richard Henderson
2017-06-28 13:45 ` [Qemu-devel] [PATCH v11 22/29] target/arm: [tcg, a64] " Lluís Vilanova
2017-07-02  1:22   ` Richard Henderson
2017-06-28 13:49 ` [Qemu-devel] [PATCH v11 23/29] target/arm: [tcg] Port to translate_insn Lluís Vilanova
2017-07-02  1:34   ` Richard Henderson
2017-07-07 11:13     ` Lluís Vilanova
2017-07-07 15:26       ` Richard Henderson
2017-07-07 17:18         ` Lluís Vilanova
2017-07-07 17:38           ` Richard Henderson
2017-07-10 13:47             ` Lluís Vilanova
2017-07-10 15:28               ` Richard Henderson
2017-07-07 17:33         ` Peter Maydell
2017-07-07 17:48           ` Richard Henderson
2017-06-28 13:53 ` [Qemu-devel] [PATCH v11 24/29] target/arm: [tcg, a64] " Lluís Vilanova
2017-07-02  1:42   ` Richard Henderson
2017-07-07 11:18     ` Lluís Vilanova
2017-07-07 15:46       ` Richard Henderson
2017-07-07 16:19         ` Emilio G. Cota
2017-07-07 17:33           ` Lluís Vilanova
2017-07-07 17:32         ` Lluís Vilanova
2017-07-07 17:41           ` Richard Henderson
2017-07-11 15:56             ` Lluís Vilanova
2017-06-28 13:57 ` [Qemu-devel] [PATCH v11 25/29] target/arm: [tcg] Port to tb_stop Lluís Vilanova
2017-07-02  1:45   ` Richard Henderson
2017-06-28 14:01 ` [Qemu-devel] [PATCH v11 26/29] target/arm: [tcg, a64] " Lluís Vilanova
2017-07-02  1:48   ` Richard Henderson
2017-06-28 14:05 ` [Qemu-devel] [PATCH v11 27/29] target/arm: [tcg] Port to disas_log Lluís Vilanova
2017-07-02  1:49   ` Richard Henderson
2017-06-28 14:09 ` [Qemu-devel] [PATCH v11 28/29] target/arm: [tcg, a64] " Lluís Vilanova
2017-07-02  1:50   ` Richard Henderson
2017-06-28 14:13 ` [Qemu-devel] [PATCH v11 29/29] target/arm: [tcg] Port to generic translation framework Lluís Vilanova
2017-07-02  1:54   ` Richard Henderson
2017-07-07 11:26     ` Lluís Vilanova

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.