All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework
@ 2017-06-25  8:43 Lluís Vilanova
  2017-06-25  8:47 ` [Qemu-devel] [PATCH v9 01/26] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
                   ` (26 more replies)
  0 siblings, 27 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  8:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 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 (26):
      Pass generic CPUState to gen_intermediate_code()
      queue: Add macro for incremental traversal
      cpu-exec: Avoid global variables in icount-related functions
      target: [tcg] Add generic translation framework
      target: [tcg] Redefine DISAS_* onto the generic translation framework (DJ_*)
      target: [tcg,i386] Port to DisasContextBase
      target: [tcg,i386] Refactor init_disas_context
      target: [tcg,i386] Refactor init_globals
      target: [tcg,i386] Refactor insn_start
      target: [tcg,i386] Refactor breakpoint_check
      target: [tcg,i386] Refactor disas_insn
      target: [tcg,i386] Refactor tb_stop
      target: [tcg,i386] Refactor disas_flags
      target: [tcg,i386] Replace DISAS_* with DJ_*
      target: [tcg,i386] Port to generic translation framework
      target: [tcg,arm] Replace DISAS_* with DJ_*
      target: [tcg,arm] Port to DisasContextBase
      target: [tcg,arm] Port to init_disas_context
      target: [tcg,arm] Port to init_globals
      target: [tcg,arm] Port to tb_start
      target: [tcg,arm] Port to insn_start
      target: [tcg,arm] Port to breakpoint_check
      target: [tcg,arm] Port to disas_insn
      target: [tcg,arm] Port to tb_stop
      target: [tcg,arm] Port to disas_flags
      target: [tcg,arm] Port to generic translation framework


 Makefile.target                |    1 
 include/exec/exec-all.h        |   13 +
 include/exec/gen-icount.h      |    8 -
 include/exec/translate-block.h |  125 ++++++++++
 include/qemu/queue.h           |   12 +
 include/qom/cpu.h              |   22 ++
 target/alpha/translate.c       |   25 +-
 target/arm/translate-a64.c     |  312 ++++++++++++-------------
 target/arm/translate.c         |  503 ++++++++++++++++++++++------------------
 target/arm/translate.h         |   38 ++-
 target/cris/translate.c        |   26 +-
 target/hppa/translate.c        |    6 
 target/i386/translate.c        |  353 +++++++++++++++-------------
 target/lm32/translate.c        |   36 +--
 target/m68k/translate.c        |   24 +-
 target/microblaze/translate.c  |   28 +-
 target/mips/translate.c        |   41 ++-
 target/moxie/translate.c       |   16 +
 target/nios2/translate.c       |    6 
 target/openrisc/translate.c    |   25 +-
 target/ppc/translate.c         |   21 +-
 target/ppc/translate_init.c    |   32 +--
 target/s390x/translate.c       |   22 +-
 target/sh4/translate.c         |   21 +-
 target/sparc/translate.c       |   17 +
 target/tilegx/translate.c      |    9 -
 target/tricore/translate.c     |   11 -
 target/unicore32/translate.c   |   26 +-
 target/xtensa/translate.c      |   39 ++-
 translate-all.c                |    2 
 translate-block.c              |  185 +++++++++++++++
 31 files changed, 1212 insertions(+), 793 deletions(-)
 create mode 100644 include/exec/translate-block.h
 create mode 100644 translate-block.c


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>

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

* [Qemu-devel] [PATCH v9 01/26] Pass generic CPUState to gen_intermediate_code()
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
@ 2017-06-25  8:47 ` Lluís Vilanova
  2017-06-26 10:04   ` [Qemu-devel] [PATCH] fixup! " Alex Bennée
  2017-06-26 17:50   ` [Qemu-devel] [PATCH v9 01/26] " Emilio G. Cota
  2017-06-25  8:51 ` [Qemu-devel] [PATCH v9 02/26] queue: Add macro for incremental traversal Lluís Vilanova
                   ` (25 subsequent siblings)
  26 siblings, 2 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  8:47 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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, 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>
---
 include/exec/exec-all.h       |    2 +-
 target/alpha/translate.c      |   11 +++++------
 target/arm/translate.c        |   20 ++++++++++----------
 target/cris/translate.c       |   17 ++++++++---------
 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/openrisc/translate.c   |   19 ++++++++++---------
 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 ++++++-------
 translate-all.c               |    2 +-
 20 files changed, 130 insertions(+), 142 deletions(-)

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 87ae10bcc9..1ec7637170 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 7c45ae360c..9b60680454 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -2900,10 +2900,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;
@@ -2918,7 +2917,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;
@@ -2961,7 +2960,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
@@ -3030,7 +3029,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.c b/target/arm/translate.c
index 0862f9e4aa..96272a9888 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;
@@ -11804,7 +11804,7 @@ void gen_intermediate_code(CPUARMState *env, 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(arm_cpu, tb);
         return;
     }
 
@@ -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/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/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 ad4d4efb8d..0a3372818c 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5039,10 +5039,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;
@@ -5059,7 +5058,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->fpcr = env->fpcr;
     dc->user = (env->sr & SR_S) == 0;
     dc->done_mac = 0;
@@ -5080,7 +5079,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
@@ -5098,14 +5097,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);
@@ -5138,7 +5137,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/openrisc/translate.c b/target/openrisc/translate.c
index e49518e893..aaac359d5b 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -1518,9 +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);
+    OpenRISCState *env = cpu->env_ptr;
+    OpenRISCCPU *or_cpu = openrisc_env_get_cpu(env);
     CPUState *cs = CPU(cpu);
     struct DisasContext ctx, *dc = &ctx;
     uint32_t pc_start;
@@ -1533,10 +1534,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 +1572,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 +1587,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 +1602,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 +1620,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 +1648,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 8c055b7bb7..684ae4ce2f 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -5708,10 +5708,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;
@@ -5730,7 +5729,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;
 
@@ -5749,7 +5748,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
@@ -5773,7 +5772,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;
         }
@@ -5823,7 +5822,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();
     }
diff --git a/translate-all.c b/translate-all.c
index b3ee876526..e5de5cace9 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1292,7 +1292,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);

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

* [Qemu-devel] [PATCH v9 02/26] queue: Add macro for incremental traversal
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
  2017-06-25  8:47 ` [Qemu-devel] [PATCH v9 01/26] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
@ 2017-06-25  8:51 ` Lluís Vilanova
  2017-06-25  8:55 ` [Qemu-devel] [PATCH v9 03/26] cpu-exec: Avoid global variables in icount-related functions Lluís Vilanova
                   ` (24 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  8:51 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Richard Henderson, Peter Crosthwaite, Paolo Bonzini

Adds macro QTAILQ_FOREACH_CONTINUE to support incremental list
traversal.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 include/qemu/queue.h |   12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/qemu/queue.h b/include/qemu/queue.h
index 35292c3155..eb2bf9cb1c 100644
--- a/include/qemu/queue.h
+++ b/include/qemu/queue.h
@@ -415,6 +415,18 @@ struct {                                                                \
                 (var);                                                  \
                 (var) = ((var)->field.tqe_next))
 
+/**
+ * QTAILQ_FOREACH_CONTINUE:
+ * @var: Variable to resume iteration from.
+ * @field: Field in @var holding a QTAILQ_ENTRY for this queue.
+ *
+ * Resumes iteration on a queue from the element in @var.
+ */
+#define QTAILQ_FOREACH_CONTINUE(var, field)                             \
+        for ((var) = ((var)->field.tqe_next);                           \
+                (var);                                                  \
+                (var) = ((var)->field.tqe_next))
+
 #define QTAILQ_FOREACH_SAFE(var, head, field, next_var)                 \
         for ((var) = ((head)->tqh_first);                               \
                 (var) && ((next_var) = ((var)->field.tqe_next), 1);     \

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

* [Qemu-devel] [PATCH v9 03/26] cpu-exec: Avoid global variables in icount-related functions
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
  2017-06-25  8:47 ` [Qemu-devel] [PATCH v9 01/26] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
  2017-06-25  8:51 ` [Qemu-devel] [PATCH v9 02/26] queue: Add macro for incremental traversal Lluís Vilanova
@ 2017-06-25  8:55 ` Lluís Vilanova
  2017-06-26 17:53   ` Emilio G. Cota
  2017-06-25  8:59 ` [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework Lluís Vilanova
                   ` (23 subsequent siblings)
  26 siblings, 1 reply; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  8:55 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 include/exec/gen-icount.h     |    6 +++--
 target/alpha/translate.c      |   14 ++++++------
 target/arm/translate-a64.c    |   10 ++++-----
 target/arm/translate.c        |   10 ++++-----
 target/cris/translate.c       |    6 +++--
 target/hppa/translate.c       |    6 +++--
 target/i386/translate.c       |   46 +++++++++++++++++++++--------------------
 target/lm32/translate.c       |   14 ++++++------
 target/m68k/translate.c       |    6 +++--
 target/microblaze/translate.c |    6 +++--
 target/mips/translate.c       |   26 ++++++++++++-----------
 target/moxie/translate.c      |    2 +-
 target/nios2/translate.c      |    6 +++--
 target/openrisc/translate.c   |    6 +++--
 target/ppc/translate.c        |    6 +++--
 target/ppc/translate_init.c   |   32 ++++++++++++++---------------
 target/s390x/translate.c      |    6 +++--
 target/sh4/translate.c        |    6 +++--
 target/sparc/translate.c      |    6 +++--
 target/tilegx/translate.c     |    2 +-
 target/tricore/translate.c    |    2 +-
 target/unicore32/translate.c  |    6 +++--
 target/xtensa/translate.c     |   26 ++++++++++++-----------
 23 files changed, 128 insertions(+), 128 deletions(-)

diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index 62d462e494..9b26c7da5f 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -8,7 +8,7 @@
 static int icount_start_insn_idx;
 static TCGLabel *exitreq_label;
 
-static inline void gen_tb_start(TranslationBlock *tb)
+static inline void gen_tb_start(TranslationBlock *tb, TCGv_env cpu_env)
 {
     TCGv_i32 count, imm;
 
@@ -59,14 +59,14 @@ static void gen_tb_end(TranslationBlock *tb, int num_insns)
     tcg_ctx.gen_op_buf[tcg_ctx.gen_op_buf[0].prev].next = 0;
 }
 
-static inline void gen_io_start(void)
+static inline void gen_io_start(TCGv_env cpu_env)
 {
     TCGv_i32 tmp = tcg_const_i32(1);
     tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
     tcg_temp_free_i32(tmp);
 }
 
-static inline void gen_io_end(void)
+static inline void gen_io_end(TCGv_env cpu_env)
 {
     TCGv_i32 tmp = tcg_const_i32(0);
     tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 9b60680454..fdc49109ad 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -1329,9 +1329,9 @@ static ExitStatus gen_mfpr(DisasContext *ctx, TCGv va, int regno)
         helper = gen_helper_get_vmtime;
     do_helper:
         if (use_icount) {
-            gen_io_start();
+            gen_io_start(cpu_env);
             helper(va);
-            gen_io_end();
+            gen_io_end(cpu_env);
             return EXIT_PC_STALE;
         } else {
             helper(va);
@@ -2379,9 +2379,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
             /* RPCC */
             va = dest_gpr(ctx, ra);
             if (ctx->tb->cflags & CF_USE_ICOUNT) {
-                gen_io_start();
+                gen_io_start(cpu_env);
                 gen_helper_load_pcc(va, cpu_env);
-                gen_io_end();
+                gen_io_end(cpu_env);
                 ret = EXIT_PC_STALE;
             } else {
                 gen_helper_load_pcc(va, cpu_env);
@@ -2955,7 +2955,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         pc_mask = ~TARGET_PAGE_MASK;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     do {
         tcg_gen_insn_start(ctx.pc);
         num_insns++;
@@ -2970,7 +2970,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
             break;
         }
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
         insn = cpu_ldl_code(env, ctx.pc);
 
@@ -2991,7 +2991,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
     } while (ret == NO_EXIT);
 
     if (tb->cflags & CF_LAST_IO) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 
     switch (ret) {
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 860e279658..43261e7939 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1558,7 +1558,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
     }
 
     if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
 
     tcg_rt = cpu_reg(s, rt);
@@ -1590,7 +1590,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
 
     if ((s->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_io_end(cpu_env);
         s->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,
@@ -11263,7 +11263,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
 
     tcg_clear_temp_count();
 
@@ -11297,7 +11297,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
         }
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         if (dc->ss_active && !dc->pstate_ss) {
@@ -11338,7 +11338,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
              num_insns < max_insns);
 
     if (tb->cflags & CF_LAST_IO) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 
     if (unlikely(cs->singlestep_enabled || dc->ss_active)
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 96272a9888..073562269b 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -7654,7 +7654,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
         }
 
         if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         if (isread) {
@@ -7746,7 +7746,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
 
         if ((s->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_io_end(cpu_env);
             gen_lookup_tb(s);
         } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
             /* We default to ending the TB on a coprocessor register write,
@@ -11881,7 +11881,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
 
     tcg_clear_temp_count();
 
@@ -11969,7 +11969,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         }
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         if (dc->ss_active && !dc->pstate_ss) {
@@ -12044,7 +12044,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
                code.  */
             cpu_abort(cpu, "IO on conditional branch instruction");
         }
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 
     /* At this stage dc->condjmp will only be set when the skipped
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 35931e7061..90424abe00 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -3144,7 +3144,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     do {
         tcg_gen_insn_start(dc->delayed_branch == 1
                            ? dc->ppc | 1 : dc->pc);
@@ -3167,7 +3167,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         LOG_DIS("%8.8x:\t", dc->pc);
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
         dc->clear_x = 1;
 
@@ -3240,7 +3240,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
     npc = dc->pc;
 
         if (tb->cflags & CF_LAST_IO)
-            gen_io_end();
+            gen_io_end(cpu_env);
     /* Force an update if the per-tb cpu state has changed.  */
     if (dc->is_jmp == DISAS_NEXT
         && (dc->cpustate_changed || !dc->flagx_known
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index e10abc5e04..ba154661fc 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -3773,7 +3773,7 @@ void gen_intermediate_code(CPUHPPAState *env, struct TranslationBlock *tb)
     }
 
     num_insns = 0;
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
 
     /* Seed the nullification status from PSW[N], as shown in TB->FLAGS.  */
     ctx.null_cond = cond_make_f();
@@ -3793,7 +3793,7 @@ void gen_intermediate_code(CPUHPPAState *env, struct TranslationBlock *tb)
             break;
         }
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         if (ctx.iaoq_f < TARGET_PAGE_SIZE) {
@@ -3869,7 +3869,7 @@ void gen_intermediate_code(CPUHPPAState *env, struct TranslationBlock *tb)
     } while (ret == NO_EXIT);
 
     if (tb->cflags & CF_LAST_IO) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 
     switch (ret) {
diff --git a/target/i386/translate.c b/target/i386/translate.c
index b94303ff10..9f42a5509d 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -1120,7 +1120,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) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_string_movl_A0_EDI(s);
     /* Note: we must do this dummy write first to be restartable in
@@ -1135,14 +1135,14 @@ static inline void gen_ins(DisasContext *s, TCGMemOp 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) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 }
 
 static inline void gen_outs(DisasContext *s, TCGMemOp ot)
 {
     if (s->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_string_movl_A0_ESI(s);
     gen_op_ld_v(s, ot, cpu_T0, cpu_A0);
@@ -1155,7 +1155,7 @@ static inline void gen_outs(DisasContext *s, TCGMemOp 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) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 }
 
@@ -6338,14 +6338,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         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) {
-            gen_io_start();
+            gen_io_start(cpu_env);
 	}
         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) {
-            gen_io_end();
+            gen_io_end(cpu_env);
             gen_jmp(s, s->pc - s->cs_base);
         }
         break;
@@ -6359,14 +6359,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
 
         if (s->tb->cflags & CF_USE_ICOUNT) {
-            gen_io_start();
+            gen_io_start(cpu_env);
 	}
         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) {
-            gen_io_end();
+            gen_io_end(cpu_env);
             gen_jmp(s, s->pc - s->cs_base);
         }
         break;
@@ -6377,14 +6377,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         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) {
-            gen_io_start();
+            gen_io_start(cpu_env);
 	}
         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) {
-            gen_io_end();
+            gen_io_end(cpu_env);
             gen_jmp(s, s->pc - s->cs_base);
         }
         break;
@@ -6397,14 +6397,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
 
         if (s->tb->cflags & CF_USE_ICOUNT) {
-            gen_io_start();
+            gen_io_start(cpu_env);
 	}
         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) {
-            gen_io_end();
+            gen_io_end(cpu_env);
             gen_jmp(s, s->pc - s->cs_base);
         }
         break;
@@ -7112,11 +7112,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) {
-            gen_io_start();
+            gen_io_start(cpu_env);
 	}
         gen_helper_rdtsc(cpu_env);
         if (s->tb->cflags & CF_USE_ICOUNT) {
-            gen_io_end();
+            gen_io_end(cpu_env);
             gen_jmp(s, s->pc - s->cs_base);
         }
         break;
@@ -7571,11 +7571,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) {
-                gen_io_start();
+                gen_io_start(cpu_env);
             }
             gen_helper_rdtscp(cpu_env);
             if (s->tb->cflags & CF_USE_ICOUNT) {
-                gen_io_end();
+                gen_io_end(cpu_env);
                 gen_jmp(s, s->pc - s->cs_base);
             }
             break;
@@ -7940,24 +7940,24 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_jmp_im(pc_start - s->cs_base);
                 if (b & 2) {
                     if (s->tb->cflags & CF_USE_ICOUNT) {
-                        gen_io_start();
+                        gen_io_start(cpu_env);
                     }
                     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) {
-                        gen_io_end();
+                        gen_io_end(cpu_env);
                     }
                     gen_jmp_im(s->pc - s->cs_base);
                     gen_eob(s);
                 } else {
                     if (s->tb->cflags & CF_USE_ICOUNT) {
-                        gen_io_start();
+                        gen_io_start(cpu_env);
                     }
                     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) {
-                        gen_io_end();
+                        gen_io_end(cpu_env);
                     }
                 }
                 break;
@@ -8468,7 +8468,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     for(;;) {
         tcg_gen_insn_start(pc_ptr, dc->cc_op);
         num_insns++;
@@ -8486,7 +8486,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             goto done_generating;
         }
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         pc_ptr = disas_insn(env, dc, pc_ptr);
@@ -8533,7 +8533,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         }
     }
     if (tb->cflags & CF_LAST_IO)
-        gen_io_end();
+        gen_io_end(cpu_env);
 done_generating:
     gen_tb_end(tb, num_insns);
 
diff --git a/target/lm32/translate.c b/target/lm32/translate.c
index 0ac34fc620..b635d4ea7a 100644
--- a/target/lm32/translate.c
+++ b/target/lm32/translate.c
@@ -875,24 +875,24 @@ static void dec_wcsr(DisasContext *dc)
     case CSR_IM:
         /* mark as an io operation because it could cause an interrupt */
         if (dc->tb->cflags & CF_USE_ICOUNT) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
         gen_helper_wcsr_im(cpu_env, cpu_R[dc->r1]);
         tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
         if (dc->tb->cflags & CF_USE_ICOUNT) {
-            gen_io_end();
+            gen_io_end(cpu_env);
         }
         dc->is_jmp = DISAS_UPDATE;
         break;
     case CSR_IP:
         /* mark as an io operation because it could cause an interrupt */
         if (dc->tb->cflags & CF_USE_ICOUNT) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
         gen_helper_wcsr_ip(cpu_env, cpu_R[dc->r1]);
         tcg_gen_movi_tl(cpu_pc, dc->pc + 4);
         if (dc->tb->cflags & CF_USE_ICOUNT) {
-            gen_io_end();
+            gen_io_end(cpu_env);
         }
         dc->is_jmp = DISAS_UPDATE;
         break;
@@ -1080,7 +1080,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     do {
         tcg_gen_insn_start(dc->pc);
         num_insns++;
@@ -1101,7 +1101,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         LOG_DIS("%8.8x:\t", dc->pc);
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         decode(dc, cpu_ldl_code(env, dc->pc));
@@ -1114,7 +1114,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
          && num_insns < max_insns);
 
     if (tb->cflags & CF_LAST_IO) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 
     if (unlikely(cpu->singlestep_enabled)) {
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 0a3372818c..5fac91aec5 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5072,7 +5072,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     do {
         pc_offset = dc->pc - pc_start;
         gen_throws_exception = NULL;
@@ -5091,7 +5091,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         }
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         dc->insn_pc = dc->pc;
@@ -5103,7 +5103,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
              num_insns < max_insns);
 
     if (tb->cflags & CF_LAST_IO)
-        gen_io_end();
+        gen_io_end(cpu_env);
     if (unlikely(cpu->singlestep_enabled)) {
         /* Make sure the pc is updated, and raise a debug exception.  */
         if (!dc->is_jmp) {
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index d5f499658d..7bcdc81413 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -1637,7 +1637,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     do
     {
         tcg_gen_insn_start(dc->pc);
@@ -1665,7 +1665,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         LOG_DIS("%8.8x:\t", dc->pc);
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         dc->clear_imm = 1;
@@ -1727,7 +1727,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
     }
 
     if (tb->cflags & CF_LAST_IO)
-        gen_io_end();
+        gen_io_end(cpu_env);
     /* 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)) {
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 1f9e02f426..1a14319e7a 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -5233,11 +5233,11 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 0:
             /* Mark as an IO operation because we read the time.  */
             if (ctx->tb->cflags & CF_USE_ICOUNT) {
-                gen_io_start();
+                gen_io_start(cpu_env);
 	    }
             gen_helper_mfc0_count(arg, cpu_env);
             if (ctx->tb->cflags & CF_USE_ICOUNT) {
-                gen_io_end();
+                gen_io_end(cpu_env);
             }
             /* Break the TB to be able to take timer interrupts immediately
                after reading count.  */
@@ -5637,7 +5637,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         check_insn(ctx, ISA_MIPS32);
 
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
 
     switch (reg) {
@@ -6286,7 +6286,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
 
     /* For simplicity assume that all writes can cause interrupts.  */
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         ctx->bstate = BS_STOP;
     }
     return;
@@ -6546,11 +6546,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         case 0:
             /* Mark as an IO operation because we read the time.  */
             if (ctx->tb->cflags & CF_USE_ICOUNT) {
-                gen_io_start();
+                gen_io_start(cpu_env);
             }
             gen_helper_mfc0_count(arg, cpu_env);
             if (ctx->tb->cflags & CF_USE_ICOUNT) {
-                gen_io_end();
+                gen_io_end(cpu_env);
             }
             /* Break the TB to be able to take timer interrupts immediately
                after reading count.  */
@@ -6937,7 +6937,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
         check_insn(ctx, ISA_MIPS64);
 
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
 
     switch (reg) {
@@ -7254,11 +7254,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
             /* Mark as an IO operation because we may trigger a software
                interrupt.  */
             if (ctx->tb->cflags & CF_USE_ICOUNT) {
-                gen_io_start();
+                gen_io_start(cpu_env);
             }
             gen_helper_mtc0_cause(cpu_env, arg);
             if (ctx->tb->cflags & CF_USE_ICOUNT) {
-                gen_io_end();
+                gen_io_end(cpu_env);
             }
             /* Stop translation as we may have triggered an intetrupt */
             ctx->bstate = BS_STOP;
@@ -7584,7 +7584,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
 
     /* For simplicity assume that all writes can cause interrupts.  */
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         ctx->bstate = BS_STOP;
     }
     return;
@@ -19935,7 +19935,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
     }
 
     LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     while (ctx.bstate == BS_NONE) {
         tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
         num_insns++;
@@ -19953,7 +19953,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         }
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
@@ -20014,7 +20014,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
             break;
     }
     if (tb->cflags & CF_LAST_IO) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
     if (cpu->singlestep_enabled && ctx.bstate != BS_BRANCH) {
         save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
diff --git a/target/moxie/translate.c b/target/moxie/translate.c
index 176063a1de..2bcf1f6856 100644
--- a/target/moxie/translate.c
+++ b/target/moxie/translate.c
@@ -846,7 +846,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     do {
         tcg_gen_insn_start(ctx.pc);
         num_insns++;
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 2f3c2e5dfb..b21fed869b 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -834,7 +834,7 @@ void gen_intermediate_code(CPUNios2State *env, TranslationBlock *tb)
         }
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     do {
         tcg_gen_insn_start(dc->pc);
         num_insns++;
@@ -850,7 +850,7 @@ void gen_intermediate_code(CPUNios2State *env, TranslationBlock *tb)
         }
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         /* Decode an instruction */
@@ -867,7 +867,7 @@ void gen_intermediate_code(CPUNios2State *env, TranslationBlock *tb)
              num_insns < max_insns);
 
     if (tb->cflags & CF_LAST_IO) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 
     /* Indicate where the next block should start */
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index aaac359d5b..6c555dfeeb 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -1557,7 +1557,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         qemu_log("IN: %s\n", lookup_symbol(pc_start));
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
 
     /* Allow the TCG optimizer to see that R0 == 0,
        when it's true, which is the common case.  */
@@ -1585,7 +1585,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         }
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
         disas_openrisc_insn(dc, or_cpu);
         dc->pc = dc->pc + 4;
@@ -1608,7 +1608,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
              && num_insns < max_insns);
 
     if (tb->cflags & CF_LAST_IO) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 
     if ((dc->tb_flags & TB_FLAGS_DFLAG ? 1 : 0) != (dc->delayed_branch != 0)) {
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 9a934117d8..b395241f01 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7282,7 +7282,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     tcg_clear_temp_count();
     /* Set env in case of segfault during code fetch */
     while (ctx.exception == POWERPC_EXCP_NONE && !tcg_op_buf_full()) {
@@ -7303,7 +7303,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
                   ctx.nip, ctx.mem_idx, (int)msr_ir);
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO))
-            gen_io_start();
+            gen_io_start(cpu_env);
         if (unlikely(need_byteswap(&ctx))) {
             ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
         } else {
@@ -7384,7 +7384,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         }
     }
     if (tb->cflags & CF_LAST_IO)
-        gen_io_end();
+        gen_io_end(cpu_env);
     if (ctx.exception == POWERPC_EXCP_NONE) {
         gen_goto_tb(&ctx, 0, ctx.nip);
     } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index 56a0ab22cf..d25c309415 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -175,11 +175,11 @@ static void spr_write_ureg(DisasContext *ctx, int sprn, int gprn)
 static void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
 {
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_load_decr(cpu_gpr[gprn], cpu_env);
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         gen_stop_exception(ctx);
     }
 }
@@ -187,11 +187,11 @@ static void spr_read_decr(DisasContext *ctx, int gprn, int sprn)
 static void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
 {
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_store_decr(cpu_env, cpu_gpr[gprn]);
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         gen_stop_exception(ctx);
     }
 }
@@ -202,11 +202,11 @@ static void spr_write_decr(DisasContext *ctx, int sprn, int gprn)
 static void spr_read_tbl(DisasContext *ctx, int gprn, int sprn)
 {
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_load_tbl(cpu_gpr[gprn], cpu_env);
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         gen_stop_exception(ctx);
     }
 }
@@ -214,11 +214,11 @@ static void spr_read_tbl(DisasContext *ctx, int gprn, int sprn)
 static void spr_read_tbu(DisasContext *ctx, int gprn, int sprn)
 {
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_load_tbu(cpu_gpr[gprn], cpu_env);
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         gen_stop_exception(ctx);
     }
 }
@@ -239,11 +239,11 @@ static void spr_read_atbu(DisasContext *ctx, int gprn, int sprn)
 static void spr_write_tbl(DisasContext *ctx, int sprn, int gprn)
 {
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_store_tbl(cpu_env, cpu_gpr[gprn]);
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         gen_stop_exception(ctx);
     }
 }
@@ -251,11 +251,11 @@ static void spr_write_tbl(DisasContext *ctx, int sprn, int gprn)
 static void spr_write_tbu(DisasContext *ctx, int sprn, int gprn)
 {
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_store_tbu(cpu_env, cpu_gpr[gprn]);
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         gen_stop_exception(ctx);
     }
 }
@@ -283,11 +283,11 @@ static void spr_read_purr(DisasContext *ctx, int gprn, int sprn)
 static void spr_read_hdecr(DisasContext *ctx, int gprn, int sprn)
 {
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_load_hdecr(cpu_gpr[gprn], cpu_env);
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         gen_stop_exception(ctx);
     }
 }
@@ -295,11 +295,11 @@ static void spr_read_hdecr(DisasContext *ctx, int gprn, int sprn)
 static void spr_write_hdecr(DisasContext *ctx, int sprn, int gprn)
 {
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_store_hdecr(cpu_env, cpu_gpr[gprn]);
     if (ctx->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         gen_stop_exception(ctx);
     }
 }
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 684ae4ce2f..14abb6e6b9 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -5742,7 +5742,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
 
     do {
         tcg_gen_insn_start(dc.pc, dc.cc_op);
@@ -5760,7 +5760,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         }
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         status = translate_one(env, &dc);
@@ -5779,7 +5779,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
     } while (status == NO_EXIT);
 
     if (tb->cflags & CF_LAST_IO) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 
     switch (status) {
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
index 6a797072d4..2558347d9a 100644
--- a/target/sh4/translate.c
+++ b/target/sh4/translate.c
@@ -1846,7 +1846,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     while (ctx.bstate == BS_NONE && !tcg_op_buf_full()) {
         tcg_gen_insn_start(ctx.pc, ctx.envflags);
         num_insns++;
@@ -1865,7 +1865,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
         }
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         ctx.opcode = cpu_lduw_code(env, ctx.pc);
@@ -1882,7 +1882,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
             break;
     }
     if (tb->cflags & CF_LAST_IO)
-        gen_io_end();
+        gen_io_end(cpu_env);
     if (cpu->singlestep_enabled) {
         gen_save_cpu_state(&ctx, true);
         gen_helper_debug(cpu_env);
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 90c43e4460..763d399419 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -5788,7 +5788,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock * tb)
         max_insns = TCG_MAX_INSNS;
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     do {
         if (dc->npc & JUMP_PC) {
             assert(dc->jump_pc[1] == dc->pc + 4);
@@ -5810,7 +5810,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock * tb)
         }
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         insn = cpu_ldl_code(env, dc->pc);
@@ -5837,7 +5837,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock * tb)
 
  exit_gen_loop:
     if (tb->cflags & CF_LAST_IO) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
     if (!dc->is_br) {
         if (dc->pc != DYNAMIC_PC &&
diff --git a/target/tilegx/translate.c b/target/tilegx/translate.c
index a86e9e9d22..2dbed6b19b 100644
--- a/target/tilegx/translate.c
+++ b/target/tilegx/translate.c
@@ -2402,7 +2402,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
     if (max_insns > TCG_MAX_INSNS) {
         max_insns = TCG_MAX_INSNS;
     }
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
 
     while (1) {
         tcg_gen_insn_start(dc->pc);
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
index 1930da2f2a..a4a8bb2272 100644
--- a/target/tricore/translate.c
+++ b/target/tricore/translate.c
@@ -8810,7 +8810,7 @@ void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
     ctx.mem_idx = cpu_mmu_index(env, false);
 
     tcg_clear_temp_count();
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     while (ctx.bstate == BS_NONE) {
         tcg_gen_insn_start(ctx.pc);
         num_insns++;
diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c
index 494ed58c10..a7878ffd81 100644
--- a/target/unicore32/translate.c
+++ b/target/unicore32/translate.c
@@ -1911,7 +1911,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     }
 #endif
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
     do {
         tcg_gen_insn_start(dc->pc);
         num_insns++;
@@ -1929,7 +1929,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         }
 
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         disas_uc32_insn(env, dc);
@@ -1959,7 +1959,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
                code.  */
             cpu_abort(cpu, "IO on conditional branch instruction");
         }
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 
     /* At this stage dc->condjmp will only be set when the skipped
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 63e4f25c08..63e9646d17 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -514,12 +514,12 @@ static bool gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access)
 static bool gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr)
 {
     if (dc->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_update_ccount(cpu_env);
     tcg_gen_mov_i32(d, cpu_SR[sr]);
     if (dc->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         return true;
     }
     return false;
@@ -699,11 +699,11 @@ static bool gen_wsr_cpenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 static void gen_check_interrupts(DisasContext *dc)
 {
     if (dc->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_check_interrupts(cpu_env);
     if (dc->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 }
 
@@ -757,11 +757,11 @@ static bool gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 static bool gen_wsr_ccount(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     if (dc->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_wsr_ccount(cpu_env, v);
     if (dc->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
         gen_jumpi_check_loop_end(dc, 0);
         return true;
     }
@@ -798,11 +798,11 @@ static bool gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
         tcg_gen_mov_i32(cpu_SR[sr], v);
         tcg_gen_andi_i32(cpu_SR[INTSET], cpu_SR[INTSET], ~int_bit);
         if (dc->tb->cflags & CF_USE_ICOUNT) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
         gen_helper_update_ccompare(cpu_env, tmp);
         if (dc->tb->cflags & CF_USE_ICOUNT) {
-            gen_io_end();
+            gen_io_end(cpu_env);
             gen_jumpi_check_loop_end(dc, 0);
             ret = true;
         }
@@ -897,11 +897,11 @@ static void gen_waiti(DisasContext *dc, uint32_t imm4)
     TCGv_i32 intlevel = tcg_const_i32(imm4);
 
     if (dc->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_start();
+        gen_io_start(cpu_env);
     }
     gen_helper_waiti(cpu_env, pc, intlevel);
     if (dc->tb->cflags & CF_USE_ICOUNT) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
     tcg_temp_free(pc);
     tcg_temp_free(intlevel);
@@ -3156,7 +3156,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         dc.next_icount = tcg_temp_local_new_i32();
     }
 
-    gen_tb_start(tb);
+    gen_tb_start(tb, cpu_env);
 
     if ((tb->cflags & CF_USE_ICOUNT) &&
         (tb->flags & XTENSA_TBFLAG_YIELD)) {
@@ -3191,7 +3191,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         }
 
         if (insn_count == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
+            gen_io_start(cpu_env);
         }
 
         if (dc.icount) {
@@ -3232,7 +3232,7 @@ done:
     }
 
     if (tb->cflags & CF_LAST_IO) {
-        gen_io_end();
+        gen_io_end(cpu_env);
     }
 
     if (dc.is_jmp == DISAS_NEXT) {

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

* [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (2 preceding siblings ...)
  2017-06-25  8:55 ` [Qemu-devel] [PATCH v9 03/26] cpu-exec: Avoid global variables in icount-related functions Lluís Vilanova
@ 2017-06-25  8:59 ` Lluís Vilanova
  2017-06-26 10:14   ` Alex Bennée
                     ` (3 more replies)
  2017-06-25  9:03 ` [Qemu-devel] [PATCH v9 05/26] target: [tcg] Redefine DISAS_* onto the generic translation framework (DJ_*) Lluís Vilanova
                   ` (22 subsequent siblings)
  26 siblings, 4 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  8:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Richard Henderson, Peter Crosthwaite, Paolo Bonzini

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile.target                |    1 
 include/exec/gen-icount.h      |    2 
 include/exec/translate-block.h |  125 +++++++++++++++++++++++++++
 include/qom/cpu.h              |   22 +++++
 translate-block.c              |  185 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 334 insertions(+), 1 deletion(-)
 create mode 100644 include/exec/translate-block.h
 create mode 100644 translate-block.c

diff --git a/Makefile.target b/Makefile.target
index ce8dfe44a8..253c6e7999 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -90,6 +90,7 @@ all: $(PROGS) stap
 # cpu emulator library
 obj-y = exec.o translate-all.o cpu-exec.o
 obj-y += translate-common.o
+obj-y += translate-block.o
 obj-y += cpu-exec-common.o
 obj-y += tcg/tcg.o tcg/tcg-op.o tcg/optimize.o
 obj-$(CONFIG_TCG_INTERPRETER) += tci.o
diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index 9b26c7da5f..f4ad61014b 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, TCGv_env cpu_env)
     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/translate-block.h b/include/exec/translate-block.h
new file mode 100644
index 0000000000..d14d23f2cb
--- /dev/null
+++ b/include/exec/translate-block.h
@@ -0,0 +1,125 @@
+/*
+ * 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__TRANSLATE_BLOCK_H
+#define EXEC__TRANSLATE_BLOCK_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:
+ * @DJ_NEXT: Next instruction in program order.
+ * @DJ_TOO_MANY: Too many instructions translated.
+ * @DJ_TARGET: Start of target-specific conditions.
+ *
+ * What instruction to disassemble next.
+ */
+typedef enum DisasJumpType {
+    DJ_NEXT,
+    DJ_TOO_MANY,
+    DJ_TARGET,
+} 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.
+ *
+ * All operations but disas_insn() are optional, and ignored when not set.
+ * A missing breakpoint_check() will ignore breakpoints. A missing disas_flags()
+ * will pass no flags.
+ */
+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 (*disas_insn)(DisasContextBase *db, CPUState *cpu);
+    void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
+    int (*disas_flags)(const DisasContextBase *db);
+} TranslatorOps;
+
+/**
+ * translate_block:
+ * @ops: Target-specific operations.
+ * @db:
+ * @cpu:
+ * @tb:
+ *
+ * Generic translator loop.
+ */
+void translate_block(const TranslatorOps *ops, DisasContextBase *db,
+                     CPUState *cpu, TCGv_env *tcg_cpu, TranslationBlock *tb);
+
+#endif  /* EXEC__TRANSLATE_BLOCK_H */
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 89ddb686fb..d46e8df756 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -982,6 +982,28 @@ static inline bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask)
     return false;
 }
 
+/* Get first breakpoint matching a PC */
+static inline CPUBreakpoint *cpu_breakpoint_get(CPUState *cpu, vaddr pc,
+                                                CPUBreakpoint *bp)
+{
+    if (likely(bp == NULL)) {
+        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
+                if (bp->pc == pc) {
+                    return bp;
+                }
+            }
+        }
+    } else {
+        QTAILQ_FOREACH_CONTINUE(bp, entry) {
+            if (bp->pc == pc) {
+                return bp;
+            }
+        }
+    }
+    return NULL;
+}
+
 int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
                           int flags, CPUWatchpoint **watchpoint);
 int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
diff --git a/translate-block.c b/translate-block.c
new file mode 100644
index 0000000000..1aac80560e
--- /dev/null
+++ b/translate-block.c
@@ -0,0 +1,185 @@
+/*
+ * 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/translate-block.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, TCGv_env *tcg_cpu, TranslationBlock *tb)
+{
+    int max_insns;
+
+    /* Sanity-check ops */
+    if (ops->disas_insn == NULL) {
+        error_report("Missing ops->disas_insn");
+        abort();
+    }
+
+    /* Initialize DisasContext */
+    db->tb = tb;
+    db->pc_first = tb->pc;
+    db->pc_next = db->pc_first;
+    db->is_jmp = DJ_NEXT;
+    db->num_insns = 0;
+    db->singlestep_enabled = cpu->singlestep_enabled;
+    if (ops->init_disas_context) {
+        ops->init_disas_context(db, cpu);
+    }
+
+    /* Initialize globals */
+    if (ops->init_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, *tcg_cpu);
+    if (ops->tb_start) {
+        ops->tb_start(db, cpu);
+    }
+
+    while (true) {
+        CPUBreakpoint *bp;
+
+        db->num_insns++;
+        if (ops->insn_start) {
+            ops->insn_start(db, cpu);
+        }
+
+        /* Early exit before breakpoint checks */
+        if (unlikely(db->is_jmp != DJ_NEXT)) {
+            break;
+        }
+
+        /* Pass breakpoint hits to target for further processing */
+        bp = NULL;
+        do {
+            bp = cpu_breakpoint_get(cpu, db->pc_next, bp);
+            if (unlikely(bp) && ops->breakpoint_check) {
+                BreakpointCheckType bp_check = ops->breakpoint_check(
+                    db, cpu, bp);
+                if (bp_check == 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.
+                     */
+                    break;
+                } else if (bp_check == BC_HIT_TB) {
+                    goto done_generating;
+                } else {
+                    error_report("Unexpected BreakpointCheckType %d", bp_check);
+                    abort();
+                }
+            }
+        } while (bp != NULL);
+
+        /* Accept I/O on last instruction */
+        if (db->num_insns == max_insns && (db->tb->cflags & CF_LAST_IO)) {
+            gen_io_start(*tcg_cpu);
+        }
+
+        /* Disassemble one instruction */
+        db->pc_next = ops->disas_insn(db, cpu);
+
+        /**************************************************/
+        /* Conditions to stop translation                 */
+        /**************************************************/
+
+        /* Target-specific conditions set by disassembly */
+        if (db->is_jmp != DJ_NEXT) {
+            break;
+        }
+
+        /* Too many instructions */
+        if (tcg_op_buf_full() || db->num_insns >= max_insns) {
+            db->is_jmp = DJ_TOO_MANY;
+            break;
+        }
+
+        /*
+         * Check if next instruction is on next page, which can cause an
+         * exception.
+         *
+         * NOTE: Target-specific code must check a single instruction does not
+         *       cross page boundaries; the first in the TB is always allowed to
+         *       cross pages (never goes through this check).
+         */
+        if ((db->pc_first & TARGET_PAGE_MASK)
+            != (db->pc_next & TARGET_PAGE_MASK)) {
+            db->is_jmp = DJ_TOO_MANY;
+            break;
+        }
+
+        translate_block_tcg_check(db);
+    }
+
+    if (ops->tb_stop) {
+        ops->tb_stop(db, cpu);
+    }
+
+    if (db->tb->cflags & CF_LAST_IO) {
+        gen_io_end(*tcg_cpu);
+    }
+
+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)) {
+        int flags;
+        if (ops->disas_flags) {
+            flags = ops->disas_flags(db);
+        } else {
+            flags = 0;
+        }
+        qemu_log_lock();
+        qemu_log("----------------\n");
+        qemu_log("IN: %s\n", lookup_symbol(db->pc_first));
+        log_target_disas(cpu, db->pc_first, db->pc_next - db->pc_first, flags);
+        qemu_log("\n");
+        qemu_log_unlock();
+    }
+#endif
+
+    db->tb->size = db->pc_next - db->pc_first;
+    db->tb->icount = db->num_insns;
+}

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

* [Qemu-devel] [PATCH v9 05/26] target: [tcg] Redefine DISAS_* onto the generic translation framework (DJ_*)
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (3 preceding siblings ...)
  2017-06-25  8:59 ` [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework Lluís Vilanova
@ 2017-06-25  9:03 ` Lluís Vilanova
  2017-06-26 11:28   ` [Qemu-devel] [PATCH] maybe fixup! " Alex Bennée
  2017-06-26 18:05   ` [Qemu-devel] [PATCH v9 05/26] " Emilio G. Cota
  2017-06-25  9:07 ` [Qemu-devel] [PATCH v9 06/26] target: [tcg, i386] Port to DisasContextBase Lluís Vilanova
                   ` (21 subsequent siblings)
  26 siblings, 2 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:03 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Richard Henderson, Peter Crosthwaite,
	Paolo Bonzini, Peter Maydell, Edgar E. Iglesias, Laurent Vivier,
	Alexander Graf, Guan Xuetao, open list:ARM

Temporarily redefine DISAS_* values based on DJ_TARGET. They should
disappear as targets get ported to the generic framework.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Acked-by: David Gibson <david@gibson.dropbear.id.au> (ppc)
Acked-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> (i386)
Acked-by: Laurent Vivier <laurent@vivier.eu> (m68k)
Reviewed-by: Alex Benée <alex.benee@linaro.org> (arm)
---
 include/exec/exec-all.h      |   11 +++++++----
 target/arm/translate.h       |   19 ++++++++++---------
 target/cris/translate.c      |    3 ++-
 target/m68k/translate.c      |    3 ++-
 target/s390x/translate.c     |    3 ++-
 target/unicore32/translate.c |    3 ++-
 6 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 1ec7637170..5d693cefd1 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -36,10 +36,13 @@ 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 */
+/* TODO: delete after all targets are transitioned to generic translation */
+#include "exec/translate-block.h"
+#define DISAS_NEXT    DJ_NEXT           /* next instruction can be analyzed */
+#define DISAS_JUMP    (DJ_TARGET + 0)   /* only pc was modified dynamically */
+#define DISAS_UPDATE  (DJ_TARGET + 1)   /* cpu state was modified dynamically */
+#define DISAS_TB_JUMP (DJ_TARGET + 2)   /* only pc was modified statically */
+#define DISAS_TARGET  (DJ_TARGET + 3)   /* base for target-specific values */
 
 #include "qemu/log.h"
 
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 15d383d9af..e42fdbe61c 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -120,29 +120,30 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
 }
 
 /* target-specific extra values for is_jmp */
+/* TODO: rename as DJ_* when transitioning this target to generic translation */
 /* 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 + 0)
+#define DISAS_SWI (DISAS_TARGET + 1)
 /* 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 + 2)
 /* WFE */
-#define DISAS_WFE 7
-#define DISAS_HVC 8
-#define DISAS_SMC 9
-#define DISAS_YIELD 10
+#define DISAS_WFE (DISAS_TARGET + 3)
+#define DISAS_HVC (DISAS_TARGET + 4)
+#define DISAS_SMC (DISAS_TARGET + 5)
+#define DISAS_YIELD (DISAS_TARGET + 6)
 /* 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 + 7)
 /* 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 + 8)
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 90424abe00..fca831cd6f 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -50,7 +50,8 @@
 #define BUG() (gen_BUG(dc, __FILE__, __LINE__))
 #define BUG_ON(x) ({if (x) BUG();})
 
-#define DISAS_SWI 5
+/* TODO: rename as DJ_* when transitioning this target to generic translation */
+#define DISAS_SWI (DISAS_TARGET + 0)
 
 /* Used by the decoder.  */
 #define EXTRACT_FIELD(src, start, end) \
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 5fac91aec5..e75e893056 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -190,7 +190,8 @@ static void do_writebacks(DisasContext *s)
     }
 }
 
-#define DISAS_JUMP_NEXT 4
+/* TODO: rename as DJ_* when transitioning this target to generic translation */
+#define DISAS_JUMP_NEXT (DISAS_TARGET + 0)
 
 #if defined(CONFIG_USER_ONLY)
 #define IS_USER(s) 1
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 14abb6e6b9..49eddb061b 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -76,7 +76,8 @@ typedef struct {
     } u;
 } DisasCompare;
 
-#define DISAS_EXCP 4
+/* TODO: rename as DJ_* when transitioning this target to generic translation */
+#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 a7878ffd81..8bc6db61bb 100644
--- a/target/unicore32/translate.c
+++ b/target/unicore32/translate.c
@@ -45,9 +45,10 @@ typedef struct DisasContext {
 #define IS_USER(s)      1
 #endif
 
+/* TODO: rename as DJ_* when transitioning this target to generic translation */
 /* 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 + 0)
 
 static TCGv_env cpu_env;
 static TCGv_i32 cpu_R[32];

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

* [Qemu-devel] [PATCH v9 06/26] target: [tcg, i386] Port to DisasContextBase
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (4 preceding siblings ...)
  2017-06-25  9:03 ` [Qemu-devel] [PATCH v9 05/26] target: [tcg] Redefine DISAS_* onto the generic translation framework (DJ_*) Lluís Vilanova
@ 2017-06-25  9:07 ` Lluís Vilanova
  2017-06-26 18:14   ` Emilio G. Cota
  2017-06-25  9:12 ` [Qemu-devel] [PATCH v9 07/26] target: [tcg, i386] Refactor init_disas_context Lluís Vilanova
                   ` (20 subsequent siblings)
  26 siblings, 1 reply; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |  164 ++++++++++++++++++++++++++---------------------
 1 file changed, 92 insertions(+), 72 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 9f42a5509d..5a801766e5 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -30,6 +30,7 @@
 
 #include "trace-tcg.h"
 #include "exec/log.h"
+#include "exec/translate-block.h"
 
 
 #define PREFIX_REPZ   0x01
@@ -95,6 +96,8 @@ static int x86_64_hregs;
 #endif
 
 typedef struct DisasContext {
+    DisasContextBase base;
+
     /* current insn context */
     int override; /* -1 if no override */
     int prefix;
@@ -102,8 +105,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 */
@@ -124,12 +125,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;
@@ -1119,7 +1118,9 @@ 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) {
+    DisasContextBase *b = &s->base;
+
+    if (b->tb->cflags & CF_USE_ICOUNT) {
         gen_io_start(cpu_env);
     }
     gen_string_movl_A0_EDI(s);
@@ -1134,14 +1135,16 @@ 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 (b->tb->cflags & CF_USE_ICOUNT) {
         gen_io_end(cpu_env);
     }
 }
 
 static inline void gen_outs(DisasContext *s, TCGMemOp ot)
 {
-    if (s->tb->cflags & CF_USE_ICOUNT) {
+    DisasContextBase *b = &s->base;
+
+    if (b->tb->cflags & CF_USE_ICOUNT) {
         gen_io_start(cpu_env);
     }
     gen_string_movl_A0_ESI(s);
@@ -1154,7 +1157,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 (b->tb->cflags & CF_USE_ICOUNT) {
         gen_io_end(cpu_env);
     }
 }
@@ -2137,7 +2140,9 @@ 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) ||
+    DisasContextBase *b = &s->base;
+
+    return (pc & TARGET_PAGE_MASK) == (b->tb->pc & TARGET_PAGE_MASK) ||
            (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
 #else
     return true;
@@ -2146,13 +2151,14 @@ static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
 
 static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
 {
+    DisasContextBase *b = &s->base;
     target_ulong pc = s->cs_base + eip;
 
     if (use_goto_tb(s, pc))  {
         /* 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)b->tb + tb_num);
     } else {
         /* jump to another page */
         gen_jmp_im(eip);
@@ -2173,7 +2179,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();
@@ -2236,6 +2242,8 @@ static inline void gen_op_movl_seg_T0_vm(int seg_reg)
    call this function with seg_reg == R_CS */
 static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
 {
+    DisasContextBase *b = &s->base;
+
     if (s->pe && !s->vm86) {
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
         gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
@@ -2244,11 +2252,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;
+            b->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;
+            b->is_jmp = DISAS_TB_JUMP;
     }
 }
 
@@ -2417,10 +2425,12 @@ static void gen_leave(DisasContext *s)
 
 static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
 {
+    DisasContextBase *b = &s->base;
+
     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;
+    b->is_jmp = DISAS_TB_JUMP;
 }
 
 /* Generate #UD for the current instruction.  The assumption here is that
@@ -2454,19 +2464,23 @@ static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
 static void gen_interrupt(DisasContext *s, int intno,
                           target_ulong cur_eip, target_ulong next_eip)
 {
+    DisasContextBase *b = &s->base;
+
     gen_update_cc_op(s);
     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;
+    b->is_jmp = DISAS_TB_JUMP;
 }
 
 static void gen_debug(DisasContext *s, target_ulong cur_eip)
 {
+    DisasContextBase *b = &s->base;
+
     gen_update_cc_op(s);
     gen_jmp_im(cur_eip);
     gen_helper_debug(cpu_env);
-    s->is_jmp = DISAS_TB_JUMP;
+    b->is_jmp = DISAS_TB_JUMP;
 }
 
 static void gen_set_hflag(DisasContext *s, uint32_t mask)
@@ -2513,6 +2527,8 @@ static void gen_bnd_jmp(DisasContext *s)
 static void
 do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, TCGv jr)
 {
+    DisasContextBase *b = &s->base;
+
     gen_update_cc_op(s);
 
     /* If several instructions disable interrupts, only the first does it.  */
@@ -2522,10 +2538,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 (b->tb->flags & HF_RF_MASK) {
         gen_helper_reset_rf(cpu_env);
     }
-    if (s->singlestep_enabled) {
+    if (b->singlestep_enabled) {
         gen_helper_debug(cpu_env);
     } else if (recheck_tf) {
         gen_helper_rechecking_single_step(cpu_env);
@@ -2541,7 +2557,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;
+    b->is_jmp = DISAS_TB_JUMP;
 }
 
 static inline void
@@ -2576,11 +2592,13 @@ static void gen_jr(DisasContext *s, TCGv dest)
    direct call to the next block may occur */
 static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
 {
+    DisasContextBase *b = &s->base;
+
     gen_update_cc_op(s);
     set_cc_op(s, CC_OP_DYNAMIC);
     if (s->jmp_opt) {
         gen_goto_tb(s, tb_num, eip);
-        s->is_jmp = DISAS_TB_JUMP;
+        b->is_jmp = DISAS_TB_JUMP;
     } else {
         gen_jmp_im(eip);
         gen_eob(s);
@@ -4415,11 +4433,12 @@ 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)
 {
+    DisasContextBase *db = &s->base;
     int b, prefixes;
     int shift;
     TCGMemOp ot, aflag, dflag;
@@ -5375,7 +5394,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 (db->is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             if (reg == R_SS) {
                 s->tf = 0;
@@ -5390,7 +5409,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 (db->is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             gen_eob(s);
         }
@@ -5441,7 +5460,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 (db->is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             if (reg == R_SS) {
                 s->tf = 0;
@@ -5650,7 +5669,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 (db->is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             gen_eob(s);
         }
@@ -6306,7 +6325,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 (db->tb->cflags & CF_USE_ICOUNT) {
                 gen_jmp(s, s->pc - s->cs_base);
             }
         }
@@ -6321,7 +6340,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 (db->tb->cflags & CF_USE_ICOUNT) {
                 gen_jmp(s, s->pc - s->cs_base);
             }
         }
@@ -6337,14 +6356,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 (db->tb->cflags & CF_USE_ICOUNT) {
             gen_io_start(cpu_env);
 	}
         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 (db->tb->cflags & CF_USE_ICOUNT) {
             gen_io_end(cpu_env);
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6358,14 +6377,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 (db->tb->cflags & CF_USE_ICOUNT) {
             gen_io_start(cpu_env);
 	}
         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 (db->tb->cflags & CF_USE_ICOUNT) {
             gen_io_end(cpu_env);
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6376,14 +6395,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 (db->tb->cflags & CF_USE_ICOUNT) {
             gen_io_start(cpu_env);
 	}
         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 (db->tb->cflags & CF_USE_ICOUNT) {
             gen_io_end(cpu_env);
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6396,14 +6415,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 (db->tb->cflags & CF_USE_ICOUNT) {
             gen_io_start(cpu_env);
 	}
         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 (db->tb->cflags & CF_USE_ICOUNT) {
             gen_io_end(cpu_env);
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6942,7 +6961,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;
+            db->is_jmp = DISAS_TB_JUMP;
         }
         break;
     case 0x9b: /* fwait */
@@ -7111,11 +7130,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 (db->tb->cflags & CF_USE_ICOUNT) {
             gen_io_start(cpu_env);
 	}
         gen_helper_rdtsc(cpu_env);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (db->tb->cflags & CF_USE_ICOUNT) {
             gen_io_end(cpu_env);
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -7187,7 +7206,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;
+            db->is_jmp = DISAS_TB_JUMP;
         }
         break;
     case 0x100:
@@ -7370,7 +7389,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;
+            db->is_jmp = DISAS_TB_JUMP;
             break;
 
         case 0xd9: /* VMMCALL */
@@ -7570,11 +7589,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 (db->tb->cflags & CF_USE_ICOUNT) {
                 gen_io_start(cpu_env);
             }
             gen_helper_rdtscp(cpu_env);
-            if (s->tb->cflags & CF_USE_ICOUNT) {
+            if (db->tb->cflags & CF_USE_ICOUNT) {
                 gen_io_end(cpu_env);
                 gen_jmp(s, s->pc - s->cs_base);
             }
@@ -7939,24 +7958,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 (db->tb->cflags & CF_USE_ICOUNT) {
                         gen_io_start(cpu_env);
                     }
                     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 (db->tb->cflags & CF_USE_ICOUNT) {
                         gen_io_end(cpu_env);
                     }
                     gen_jmp_im(s->pc - s->cs_base);
                     gen_eob(s);
                 } else {
-                    if (s->tb->cflags & CF_USE_ICOUNT) {
+                    if (db->tb->cflags & CF_USE_ICOUNT) {
                         gen_io_start(cpu_env);
                     }
                     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 (db->tb->cflags & CF_USE_ICOUNT) {
                         gen_io_end(cpu_env);
                     }
                 }
@@ -8382,15 +8401,14 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
     CPUX86State *env = cpu->env_ptr;
     DisasContext dc1, *dc = &dc1;
-    target_ulong pc_ptr;
+    DisasContextBase *db = &dc1.base;
     uint32_t flags;
-    target_ulong pc_start;
     target_ulong cs_base;
     int num_insns;
     int max_insns;
 
     /* generate intermediate code */
-    pc_start = tb->pc;
+    db->pc_first = tb->pc;
     cs_base = tb->cs_base;
     flags = tb->flags;
 
@@ -8403,11 +8421,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;
+    db->singlestep_enabled = cpu->singlestep_enabled;
     dc->cc_op = CC_OP_DYNAMIC;
     dc->cc_op_dirty = false;
     dc->cs_base = cs_base;
-    dc->tb = tb;
+    db->tb = tb;
     dc->popl_esp_hack = 0;
     /* select memory access functions */
     dc->mem_index = 0;
@@ -8457,8 +8475,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;
+    db->is_jmp = DISAS_NEXT;
+    db->pc_next = db->pc_first;
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
@@ -8470,37 +8488,38 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 
     gen_tb_start(tb, cpu_env);
     for(;;) {
-        tcg_gen_insn_start(pc_ptr, dc->cc_op);
+        tcg_gen_insn_start(db->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, db->pc_next,
                                          tb->flags & HF_RF_MASK
                                          ? BP_GDB : BP_ANY))) {
-            gen_debug(dc, pc_ptr - dc->cs_base);
+            gen_debug(dc, db->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;
+            db->pc_next += 1;
             goto done_generating;
         }
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start(cpu_env);
         }
 
-        pc_ptr = disas_insn(env, dc, pc_ptr);
+        db->pc_next = disas_insn(env, dc, db->pc_next);
         /* stop translation if indicated */
-        if (dc->is_jmp)
+        if (db->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 || db->singlestep_enabled ||
             (flags & HF_INHIBIT_IRQ_MASK)) {
-            gen_jmp_im(pc_ptr - dc->cs_base);
+            gen_jmp_im(db->pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
@@ -8511,23 +8530,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);
+            && ((db->pc_next & TARGET_PAGE_MASK)
+                != ((db->pc_next + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
+                || (db->pc_next & ~TARGET_PAGE_MASK) == 0)) {
+            gen_jmp_im(db->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) ||
+            (db->pc_next - db->pc_first) >= (TARGET_PAGE_SIZE - 32) ||
             num_insns >= max_insns) {
-            gen_jmp_im(pc_ptr - dc->cs_base);
+            gen_jmp_im(db->pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
         if (singlestep) {
-            gen_jmp_im(pc_ptr - dc->cs_base);
+            gen_jmp_im(db->pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
@@ -8539,24 +8558,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(db->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(db->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, db->pc_first, db->pc_next - db->pc_first,
+                         disas_flags);
         qemu_log("\n");
         qemu_log_unlock();
     }
 #endif
 
-    tb->size = pc_ptr - pc_start;
+    tb->size = db->pc_next - db->pc_first;
     tb->icount = num_insns;
 }
 

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

* [Qemu-devel] [PATCH v9 07/26] target: [tcg, i386] Refactor init_disas_context
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (5 preceding siblings ...)
  2017-06-25  9:07 ` [Qemu-devel] [PATCH v9 06/26] target: [tcg, i386] Port to DisasContextBase Lluís Vilanova
@ 2017-06-25  9:12 ` Lluís Vilanova
  2017-06-27  2:57   ` Richard Henderson
  2017-06-25  9:16 ` [Qemu-devel] [PATCH v9 08/26] target: [tcg, i386] Refactor init_globals Lluís Vilanova
                   ` (19 subsequent siblings)
  26 siblings, 1 reply; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 5a801766e5..84ff49030b 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8396,21 +8396,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 *db, CPUState *cpu)
 {
+    DisasContext *dc = container_of(db, DisasContext, base);
     CPUX86State *env = cpu->env_ptr;
-    DisasContext dc1, *dc = &dc1;
-    DisasContextBase *db = &dc1.base;
-    uint32_t flags;
-    target_ulong cs_base;
-    int num_insns;
-    int max_insns;
-
-    /* generate intermediate code */
-    db->pc_first = tb->pc;
-    cs_base = tb->cs_base;
-    flags = tb->flags;
+    uint32_t flags = db->tb->flags;
+    target_ulong cs_base = db->tb->cs_base;
 
     dc->pe = (flags >> HF_PE_SHIFT) & 1;
     dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
@@ -8421,11 +8412,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;
-    db->singlestep_enabled = cpu->singlestep_enabled;
     dc->cc_op = CC_OP_DYNAMIC;
     dc->cc_op_dirty = false;
     dc->cs_base = cs_base;
-    db->tb = tb;
     dc->popl_esp_hack = 0;
     /* select memory access functions */
     dc->mem_index = 0;
@@ -8455,12 +8444,30 @@ 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 && !(db->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;
+    DisasContextBase *db = &dc1.base;
+    int num_insns;
+    int max_insns;
+
+    /* generate intermediate code */
+    db->singlestep_enabled = cpu->singlestep_enabled;
+    db->tb = tb;
+    db->is_jmp = DISAS_NEXT;
+    db->pc_first = tb->pc;
+    db->pc_next = db->pc_first;
+    i386_trblock_init_disas_context(db, cpu);
 
     cpu_T0 = tcg_temp_new();
     cpu_T1 = tcg_temp_new();
@@ -8475,8 +8482,6 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     cpu_ptr1 = tcg_temp_new_ptr();
     cpu_cc_srcT = tcg_temp_local_new();
 
-    db->is_jmp = DISAS_NEXT;
-    db->pc_next = db->pc_first;
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
@@ -8518,7 +8523,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 || db->singlestep_enabled ||
-            (flags & HF_INHIBIT_IRQ_MASK)) {
+            (db->tb->flags & HF_INHIBIT_IRQ_MASK)) {
             gen_jmp_im(db->pc_next - dc->cs_base);
             gen_eob(dc);
             break;

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

* [Qemu-devel] [PATCH v9 08/26] target: [tcg, i386] Refactor init_globals
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (6 preceding siblings ...)
  2017-06-25  9:12 ` [Qemu-devel] [PATCH v9 07/26] target: [tcg, i386] Refactor init_disas_context Lluís Vilanova
@ 2017-06-25  9:16 ` Lluís Vilanova
  2017-06-25  9:20 ` [Qemu-devel] [PATCH v9 09/26] target: [tcg, i386] Refactor insn_start Lluís Vilanova
                   ` (18 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:16 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 84ff49030b..f0d12a3d13 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8452,6 +8452,22 @@ static void i386_trblock_init_disas_context(DisasContextBase *db, CPUState *cpu)
 #endif
 }
 
+static void i386_trblock_init_globals(DisasContextBase *db, 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)
 {
@@ -8469,18 +8485,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     db->pc_next = db->pc_first;
     i386_trblock_init_disas_context(db, 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(db, cpu);
 
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;

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

* [Qemu-devel] [PATCH v9 09/26] target: [tcg, i386] Refactor insn_start
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (7 preceding siblings ...)
  2017-06-25  9:16 ` [Qemu-devel] [PATCH v9 08/26] target: [tcg, i386] Refactor init_globals Lluís Vilanova
@ 2017-06-25  9:20 ` Lluís Vilanova
  2017-06-25  9:24 ` [Qemu-devel] [PATCH v9 10/26] target: [tcg, i386] Refactor breakpoint_check Lluís Vilanova
                   ` (17 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index f0d12a3d13..3c7ef4af67 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8468,6 +8468,12 @@ static void i386_trblock_init_globals(DisasContextBase *db, CPUState *cpu)
     cpu_cc_srcT = tcg_temp_local_new();
 }
 
+static void i386_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
+{
+    DisasContext *dc = container_of(db, DisasContext, base);
+    tcg_gen_insn_start(db->pc_next, dc->cc_op);
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -8498,7 +8504,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 
     gen_tb_start(tb, cpu_env);
     for(;;) {
-        tcg_gen_insn_start(db->pc_next, dc->cc_op);
+        i386_trblock_insn_start(db, cpu);
         num_insns++;
 
         /* If RF is set, suppress an internally generated breakpoint.  */

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

* [Qemu-devel] [PATCH v9 10/26] target: [tcg, i386] Refactor breakpoint_check
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (8 preceding siblings ...)
  2017-06-25  9:20 ` [Qemu-devel] [PATCH v9 09/26] target: [tcg, i386] Refactor insn_start Lluís Vilanova
@ 2017-06-25  9:24 ` Lluís Vilanova
  2017-06-25  9:28 ` [Qemu-devel] [PATCH v9 11/26] target: [tcg, i386] Refactor disas_insn Lluís Vilanova
                   ` (16 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |   48 +++++++++++++++++++++++++++++++++++------------
 1 file changed, 36 insertions(+), 12 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3c7ef4af67..04d65b8416 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"
@@ -8474,12 +8475,32 @@ static void i386_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
     tcg_gen_insn_start(db->pc_next, dc->cc_op);
 }
 
+static BreakpointCheckType i386_trblock_breakpoint_check(
+    DisasContextBase *db, CPUState *cpu, const CPUBreakpoint *bp)
+{
+    DisasContext *dc = container_of(db, DisasContext, base);
+    /* If RF is set, suppress an internally generated breakpoint.  */
+    int flags = db->tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
+    if (bp->flags & flags) {
+        gen_debug(dc, db->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.  */
+        db->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)
 {
     CPUX86State *env = cpu->env_ptr;
     DisasContext dc1, *dc = &dc1;
     DisasContextBase *db = &dc1.base;
+    CPUBreakpoint *bp;
     int num_insns;
     int max_insns;
 
@@ -8507,18 +8528,21 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         i386_trblock_insn_start(db, cpu);
         num_insns++;
 
-        /* If RF is set, suppress an internally generated breakpoint.  */
-        if (unlikely(cpu_breakpoint_test(cpu, db->pc_next,
-                                         tb->flags & HF_RF_MASK
-                                         ? BP_GDB : BP_ANY))) {
-            gen_debug(dc, db->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.  */
-            db->pc_next += 1;
-            goto done_generating;
-        }
+        bp = NULL;
+        do {
+            bp = cpu_breakpoint_get(cpu, db->pc_next, bp);
+            if (unlikely(bp)) {
+                BreakpointCheckType bp_check = i386_trblock_breakpoint_check(
+                    db, cpu, bp);
+                if (bp_check == BC_HIT_TB) {
+                    goto done_generating;
+                } else {
+                    error_report("Unexpected BreakpointCheckType %d", bp_check);
+                    abort();
+                }
+            }
+        } while (bp != NULL);
+
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start(cpu_env);
         }

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

* [Qemu-devel] [PATCH v9 11/26] target: [tcg, i386] Refactor disas_insn
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (9 preceding siblings ...)
  2017-06-25  9:24 ` [Qemu-devel] [PATCH v9 10/26] target: [tcg, i386] Refactor breakpoint_check Lluís Vilanova
@ 2017-06-25  9:28 ` Lluís Vilanova
  2017-06-25  9:32 ` [Qemu-devel] [PATCH v9 12/26] target: [tcg,i386] Refactor tb_stop Lluís Vilanova
                   ` (15 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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, 47 insertions(+), 25 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 04d65b8416..34e7cf6788 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4436,16 +4436,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 *db, CPUState *cpu)
 {
-    DisasContextBase *db = &s->base;
+    DisasContext *s = container_of(db, 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 = db->pc_next;
 
     s->pc_start = s->pc = pc_start;
     prefixes = 0;
@@ -8494,10 +8495,50 @@ static BreakpointCheckType i386_trblock_breakpoint_check(
     }
 }
 
+static target_ulong i386_trblock_disas_insn(DisasContextBase *db, CPUState *cpu)
+{
+    DisasContext *dc = container_of(db, DisasContext, base);
+    target_ulong pc_next = disas_insn(db, cpu);
+
+    if (db->is_jmp) {
+        return pc_next;
+    }
+
+    if (dc->tf || (db->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);
+        db->is_jmp = DJ_TOO_MANY;
+    } else if ((db->tb->cflags & CF_USE_ICOUNT)
+               && ((db->pc_next & TARGET_PAGE_MASK)
+                   != ((db->pc_next + TARGET_MAX_INSN_SIZE - 1)
+                       & TARGET_PAGE_MASK)
+                   || (db->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);
+        db->is_jmp = DJ_TOO_MANY;
+    } else if ((pc_next - db->pc_first) >= (TARGET_PAGE_SIZE - 32)) {
+        gen_jmp_im(pc_next - dc->cs_base);
+        gen_eob(dc);
+        db->is_jmp = DJ_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;
     DisasContextBase *db = &dc1.base;
     CPUBreakpoint *bp;
@@ -8547,39 +8588,20 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             gen_io_start(cpu_env);
         }
 
-        db->pc_next = disas_insn(env, dc, db->pc_next);
+        db->pc_next = i386_trblock_disas_insn(db, cpu);
         /* stop translation if indicated */
         if (db->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 || db->singlestep_enabled ||
-            (db->tb->flags & HF_INHIBIT_IRQ_MASK)) {
-            gen_jmp_im(db->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)
-            && ((db->pc_next & TARGET_PAGE_MASK)
-                != ((db->pc_next + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
-                || (db->pc_next & ~TARGET_PAGE_MASK) == 0)) {
+        if (db->singlestep_enabled) {
             gen_jmp_im(db->pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
         /* if too long translation, stop generation too */
         if (tcg_op_buf_full() ||
-            (db->pc_next - db->pc_first) >= (TARGET_PAGE_SIZE - 32) ||
             num_insns >= max_insns) {
             gen_jmp_im(db->pc_next - dc->cs_base);
             gen_eob(dc);

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

* [Qemu-devel] [PATCH v9 12/26] target: [tcg,i386] Refactor tb_stop
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (10 preceding siblings ...)
  2017-06-25  9:28 ` [Qemu-devel] [PATCH v9 11/26] target: [tcg, i386] Refactor disas_insn Lluís Vilanova
@ 2017-06-25  9:32 ` Lluís Vilanova
  2017-06-25  9:36 ` [Qemu-devel] [PATCH v9 13/26] target: [tcg, i386] Refactor disas_flags Lluís Vilanova
                   ` (14 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:32 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 34e7cf6788..e7b46d282a 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8510,8 +8510,6 @@ static target_ulong i386_trblock_disas_insn(DisasContextBase *db, CPUState *cpu)
         /* 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);
         db->is_jmp = DJ_TOO_MANY;
     } else if ((db->tb->cflags & CF_USE_ICOUNT)
                && ((db->pc_next & TARGET_PAGE_MASK)
@@ -8524,18 +8522,24 @@ static target_ulong i386_trblock_disas_insn(DisasContextBase *db, CPUState *cpu)
            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);
         db->is_jmp = DJ_TOO_MANY;
     } else if ((pc_next - db->pc_first) >= (TARGET_PAGE_SIZE - 32)) {
-        gen_jmp_im(pc_next - dc->cs_base);
-        gen_eob(dc);
         db->is_jmp = DJ_TOO_MANY;
     }
 
     return pc_next;
 }
 
+static void i386_trblock_tb_stop(DisasContextBase *db, CPUState *cpu)
+{
+    DisasContext *dc = container_of(db, DisasContext, base);
+
+    if (db->is_jmp == DJ_TOO_MANY) {
+        gen_jmp_im(db->pc_next - dc->cs_base);
+        gen_eob(dc);
+    }
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -8596,23 +8600,21 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         /* if single step mode, we generate only one instruction and
            generate an exception */
         if (db->singlestep_enabled) {
-            gen_jmp_im(db->pc_next - dc->cs_base);
-            gen_eob(dc);
+            db->is_jmp = DJ_TOO_MANY;
             break;
         }
         /* if too long translation, stop generation too */
         if (tcg_op_buf_full() ||
             num_insns >= max_insns) {
-            gen_jmp_im(db->pc_next - dc->cs_base);
-            gen_eob(dc);
+            db->is_jmp = DJ_TOO_MANY;
             break;
         }
         if (singlestep) {
-            gen_jmp_im(db->pc_next - dc->cs_base);
-            gen_eob(dc);
+            db->is_jmp = DJ_TOO_MANY;
             break;
         }
     }
+    i386_trblock_tb_stop(db, cpu);
     if (tb->cflags & CF_LAST_IO)
         gen_io_end(cpu_env);
 done_generating:

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

* [Qemu-devel] [PATCH v9 13/26] target: [tcg, i386] Refactor disas_flags
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (11 preceding siblings ...)
  2017-06-25  9:32 ` [Qemu-devel] [PATCH v9 12/26] target: [tcg,i386] Refactor tb_stop Lluís Vilanova
@ 2017-06-25  9:36 ` Lluís Vilanova
  2017-06-25  9:40 ` [Qemu-devel] [PATCH v9 14/26] target: [tcg, i386] Replace DISAS_* with DJ_* Lluís Vilanova
                   ` (13 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:36 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |   25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index e7b46d282a..5e426de947 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8540,10 +8540,25 @@ static void i386_trblock_tb_stop(DisasContextBase *db, CPUState *cpu)
     }
 }
 
+static int i386_trblock_disas_flags(const DisasContextBase *db)
+{
+    DisasContext *dc = container_of(db, DisasContext, base);
+
+#ifdef TARGET_X86_64
+    if (dc->code64) {
+        return 2;
+    } else {
+        return !dc->code32;
+    }
+#else
+    return !dc->code32;
+#endif
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
-    DisasContext dc1, *dc = &dc1;
+    DisasContext dc1;
     DisasContextBase *db = &dc1.base;
     CPUBreakpoint *bp;
     int num_insns;
@@ -8623,16 +8638,10 @@ done_generating:
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
         && qemu_log_in_addr_range(db->pc_first)) {
-        int disas_flags;
+        int disas_flags = i386_trblock_disas_flags(db);
         qemu_log_lock();
         qemu_log("----------------\n");
         qemu_log("IN: %s\n", lookup_symbol(db->pc_first));
-#ifdef TARGET_X86_64
-        if (dc->code64)
-            disas_flags = 2;
-        else
-#endif
-            disas_flags = !dc->code32;
         log_target_disas(cpu, db->pc_first, db->pc_next - db->pc_first,
                          disas_flags);
         qemu_log("\n");

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

* [Qemu-devel] [PATCH v9 14/26] target: [tcg, i386] Replace DISAS_* with DJ_*
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (12 preceding siblings ...)
  2017-06-25  9:36 ` [Qemu-devel] [PATCH v9 13/26] target: [tcg, i386] Refactor disas_flags Lluís Vilanova
@ 2017-06-25  9:40 ` Lluís Vilanova
  2017-06-25  9:48 ` [Qemu-devel] [PATCH v9 16/26] target: [tcg, arm] " Lluís Vilanova
                   ` (12 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |   27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 5e426de947..c7bb6efbf5 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -71,6 +71,9 @@
     case (2 << 6) | (OP << 3) | 0 ... (2 << 6) | (OP << 3) | 7: \
     case (3 << 6) | (OP << 3) | 0 ... (3 << 6) | (OP << 3) | 7
 
+#define DJ_JUMP (DJ_TARGET + 0)         /* end of block due to call/jump */
+#define DJ_MISC (DJ_TARGET + 1)         /* some other reason */
+
 //#define MACRO_TEST   1
 
 /* global register indexes */
@@ -2180,7 +2183,7 @@ static inline void gen_jcc(DisasContext *s, int b,
 
         gen_set_label(l1);
         gen_goto_tb(s, 1, val);
-        s->base.is_jmp = DISAS_TB_JUMP;
+        s->base.is_jmp = DJ_JUMP;
     } else {
         l1 = gen_new_label();
         l2 = gen_new_label();
@@ -2253,11 +2256,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))
-            b->is_jmp = DISAS_TB_JUMP;
+            b->is_jmp = DJ_JUMP;
     } else {
         gen_op_movl_seg_T0_vm(seg_reg);
         if (seg_reg == R_SS)
-            b->is_jmp = DISAS_TB_JUMP;
+            b->is_jmp = DJ_JUMP;
     }
 }
 
@@ -2431,7 +2434,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));
-    b->is_jmp = DISAS_TB_JUMP;
+    b->is_jmp = DJ_JUMP;
 }
 
 /* Generate #UD for the current instruction.  The assumption here is that
@@ -2471,7 +2474,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));
-    b->is_jmp = DISAS_TB_JUMP;
+    b->is_jmp = DJ_JUMP;
 }
 
 static void gen_debug(DisasContext *s, target_ulong cur_eip)
@@ -2481,7 +2484,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);
-    b->is_jmp = DISAS_TB_JUMP;
+    b->is_jmp = DJ_JUMP;
 }
 
 static void gen_set_hflag(DisasContext *s, uint32_t mask)
@@ -2558,7 +2561,7 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, TCGv jr)
     } else {
         tcg_gen_exit_tb(0);
     }
-    b->is_jmp = DISAS_TB_JUMP;
+    b->is_jmp = DJ_JUMP;
 }
 
 static inline void
@@ -2599,7 +2602,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);
-        b->is_jmp = DISAS_TB_JUMP;
+        b->is_jmp = DJ_JUMP;
     } else {
         gen_jmp_im(eip);
         gen_eob(s);
@@ -6963,7 +6966,7 @@ static target_ulong disas_insn(DisasContextBase *db, CPUState *cpu)
             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));
-            db->is_jmp = DISAS_TB_JUMP;
+            db->is_jmp = DJ_JUMP;
         }
         break;
     case 0x9b: /* fwait */
@@ -7208,7 +7211,7 @@ static target_ulong disas_insn(DisasContextBase *db, CPUState *cpu)
             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));
-            db->is_jmp = DISAS_TB_JUMP;
+            db->is_jmp = DJ_JUMP;
         }
         break;
     case 0x100:
@@ -7391,7 +7394,7 @@ static target_ulong disas_insn(DisasContextBase *db, CPUState *cpu)
             gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
                              tcg_const_i32(s->pc - pc_start));
             tcg_gen_exit_tb(0);
-            db->is_jmp = DISAS_TB_JUMP;
+            db->is_jmp = DJ_JUMP;
             break;
 
         case 0xd9: /* VMMCALL */
@@ -8567,7 +8570,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     /* generate intermediate code */
     db->singlestep_enabled = cpu->singlestep_enabled;
     db->tb = tb;
-    db->is_jmp = DISAS_NEXT;
+    db->is_jmp = DJ_NEXT;
     db->pc_first = tb->pc;
     db->pc_next = db->pc_first;
     i386_trblock_init_disas_context(db, cpu);

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

* [Qemu-devel] [PATCH v9 16/26] target: [tcg, arm] Replace DISAS_* with DJ_*
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (13 preceding siblings ...)
  2017-06-25  9:40 ` [Qemu-devel] [PATCH v9 14/26] target: [tcg, i386] Replace DISAS_* with DJ_* Lluís Vilanova
@ 2017-06-25  9:48 ` Lluís Vilanova
  2017-06-26 18:08   ` Emilio G. Cota
  2017-06-25  9:52 ` [Qemu-devel] [PATCH v9 17/26] target: [tcg, arm] Port to DisasContextBase Lluís Vilanova
                   ` (11 subsequent siblings)
  26 siblings, 1 reply; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:48 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 ++++++++++++++--------------
 target/arm/translate.c     |   90 ++++++++++++++++++++++----------------------
 target/arm/translate.h     |   24 ++++++------
 3 files changed, 87 insertions(+), 85 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 43261e7939..d2fe2718ad 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->is_jmp = DJ_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->is_jmp = DJ_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->is_jmp = DJ_EXC;
 }
 
 static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
@@ -371,7 +371,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t 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->is_jmp = DJ_TB_JUMP;
     } else {
         gen_a64_set_pc_im(dest);
         if (s->ss_active) {
@@ -380,7 +380,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
             gen_exception_internal(EXCP_DEBUG);
         } else {
             tcg_gen_lookup_and_goto_ptr(cpu_pc);
-            s->is_jmp = DISAS_TB_JUMP;
+            s->is_jmp = DJ_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->is_jmp = DJ_WFI;
         return;
     case 1: /* YIELD */
         if (!parallel_cpus) {
-            s->is_jmp = DISAS_YIELD;
+            s->is_jmp = DJ_YIELD;
         }
         return;
     case 2: /* WFE */
         if (!parallel_cpus) {
-            s->is_jmp = DISAS_WFE;
+            s->is_jmp = DJ_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->is_jmp = DJ_UPDATE;
         return;
     default:
         unallocated_encoding(s);
@@ -1422,7 +1422,7 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
         gen_helper_msr_i_pstate(cpu_env, tcg_op, tcg_imm);
         tcg_temp_free_i32(tcg_imm);
         tcg_temp_free_i32(tcg_op);
-        s->is_jmp = DISAS_UPDATE;
+        s->is_jmp = DJ_UPDATE;
         break;
     }
     default:
@@ -1591,13 +1591,13 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
     if ((s->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(cpu_env);
-        s->is_jmp = DISAS_UPDATE;
+        s->is_jmp = DJ_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->is_jmp = DJ_UPDATE;
     }
 }
 
@@ -1786,7 +1786,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->is_jmp = DJ_JUMP;
         return;
     case 5: /* DRPS */
         if (rn != 0x1f) {
@@ -1800,7 +1800,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
         return;
     }
 
-    s->is_jmp = DISAS_JUMP;
+    s->is_jmp = DJ_JUMP;
 }
 
 /* C3.2 Branches, exception generating and system instructions */
@@ -11202,7 +11202,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
 
     dc->tb = tb;
 
-    dc->is_jmp = DISAS_NEXT;
+    dc->is_jmp = DJ_NEXT;
     dc->pc = pc_start;
     dc->singlestep_enabled = cs->singlestep_enabled;
     dc->condjmp = 0;
@@ -11280,7 +11280,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, 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->is_jmp = DJ_UPDATE;
                     } else {
                         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
                         /* The address covered by the breakpoint must be
@@ -11314,7 +11314,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
             assert(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->is_jmp = DJ_EXC;
             break;
         }
 
@@ -11342,14 +11342,14 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
     }
 
     if (unlikely(cs->singlestep_enabled || dc->ss_active)
-        && dc->is_jmp != DISAS_EXC) {
+        && dc->is_jmp != DJ_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->is_jmp != DJ_TB_JUMP);
+        if (dc->is_jmp != DJ_JUMP) {
             gen_a64_set_pc_im(dc->pc);
         }
         if (cs->singlestep_enabled) {
@@ -11359,29 +11359,29 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
         }
     } else {
         switch (dc->is_jmp) {
-        case DISAS_NEXT:
+        case DJ_NEXT:
             gen_goto_tb(dc, 1, dc->pc);
             break;
         default:
-        case DISAS_UPDATE:
+        case DJ_UPDATE:
             gen_a64_set_pc_im(dc->pc);
             /* fall through */
-        case DISAS_JUMP:
+        case DJ_JUMP:
             tcg_gen_lookup_and_goto_ptr(cpu_pc);
             break;
-        case DISAS_TB_JUMP:
-        case DISAS_EXC:
-        case DISAS_SWI:
+        case DJ_TB_JUMP:
+        case DJ_EXC:
+        case DJ_SWI:
             break;
-        case DISAS_WFE:
+        case DJ_WFE:
             gen_a64_set_pc_im(dc->pc);
             gen_helper_wfe(cpu_env);
             break;
-        case DISAS_YIELD:
+        case DJ_YIELD:
             gen_a64_set_pc_im(dc->pc);
             gen_helper_yield(cpu_env);
             break;
-        case DISAS_WFI:
+        case DJ_WFI:
             /* This is a special case because we don't want to just halt the CPU
              * if trying to debug across a WFI.
              */
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 073562269b..04063fed6b 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->is_jmp = DJ_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->is_jmp = DJ_EXC;
 }
 
 static void gen_singlestep_exception(DisasContext *s)
@@ -928,7 +928,7 @@ static inline void gen_bx_im(DisasContext *s, uint32_t addr)
 {
     TCGv_i32 tmp;
 
-    s->is_jmp = DISAS_JUMP;
+    s->is_jmp = DJ_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->is_jmp = DJ_JUMP;
     tcg_gen_andi_i32(cpu_R[15], var, ~1);
     tcg_gen_andi_i32(var, var, 1);
     store_cpu_field(var, thumb);
@@ -959,7 +959,7 @@ static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
      */
     gen_bx(s, var);
     if (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M)) {
-        s->is_jmp = DISAS_BX_EXCRET;
+        s->is_jmp = DJ_BX_EXCRET;
     }
 }
 
@@ -970,7 +970,7 @@ static inline void gen_bx_excret_final_code(DisasContext *s)
 
     /* Is the new PC value in the magic range indicating exception return? */
     tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], 0xff000000, excret_label);
-    /* No: end the TB as we would for a DISAS_JMP */
+    /* No: end the TB as we would for a DJ_JMP */
     if (is_singlestepping(s)) {
         gen_singlestep_exception(s);
     } else {
@@ -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->is_jmp = DJ_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->is_jmp = DJ_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->is_jmp = DJ_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->is_jmp = DJ_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->is_jmp = DJ_EXIT;
 }
 
 static inline void gen_hlt(DisasContext *s, int imm)
@@ -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->is_jmp = DJ_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->is_jmp = DJ_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->is_jmp = DJ_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->is_jmp = DJ_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->is_jmp = DJ_YIELD;
         }
         break;
     case 3: /* wfi */
         gen_set_pc_im(s, s->pc);
-        s->is_jmp = DISAS_WFI;
+        s->is_jmp = DJ_WFI;
         break;
     case 2: /* wfe */
         if (!parallel_cpus) {
             gen_set_pc_im(s, s->pc);
-            s->is_jmp = DISAS_WFE;
+            s->is_jmp = DJ_WFE;
         }
         break;
     case 4: /* sev */
@@ -7647,7 +7647,7 @@ 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->is_jmp = DJ_WFI;
             return 0;
         default:
             break;
@@ -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->is_jmp = DJ_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->is_jmp = DJ_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->is_jmp = DJ_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->is_jmp = DJ_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->is_jmp = DJ_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->is_jmp = DJ_SWI;
             break;
         }
         /* generate a conditional jump to next instruction */
@@ -11812,7 +11812,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 
     dc->tb = tb;
 
-    dc->is_jmp = DISAS_NEXT;
+    dc->is_jmp = DJ_NEXT;
     dc->pc = pc_start;
     dc->singlestep_enabled = cpu->singlestep_enabled;
     dc->condjmp = 0;
@@ -11936,7 +11936,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->is_jmp = DJ_EXC;
             break;
         }
 #endif
@@ -11950,7 +11950,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->is_jmp = DJ_UPDATE;
                     } else {
                         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
                         /* The address covered by the breakpoint must be
@@ -12051,7 +12051,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->is_jmp == DJ_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
@@ -12061,21 +12061,21 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     } else if (unlikely(is_singlestepping(dc))) {
         /* Unconditional and "condition passed" instruction codepath. */
         switch (dc->is_jmp) {
-        case DISAS_SWI:
+        case DJ_SWI:
             gen_ss_advance(dc);
             gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
                           default_exception_el(dc));
             break;
-        case DISAS_HVC:
+        case DJ_HVC:
             gen_ss_advance(dc);
             gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
             break;
-        case DISAS_SMC:
+        case DJ_SMC:
             gen_ss_advance(dc);
             gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
             break;
-        case DISAS_NEXT:
-        case DISAS_UPDATE:
+        case DJ_NEXT:
+        case DJ_UPDATE:
             gen_set_pc_im(dc, dc->pc);
             /* fall through */
         default:
@@ -12092,44 +12092,44 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
            Hardware breakpoints have already been handled and skip this code.
          */
         switch(dc->is_jmp) {
-        case DISAS_NEXT:
+        case DJ_NEXT:
             gen_goto_tb(dc, 1, dc->pc);
             break;
-        case DISAS_UPDATE:
+        case DJ_UPDATE:
             gen_set_pc_im(dc, dc->pc);
             /* fall through */
-        case DISAS_JUMP:
+        case DJ_JUMP:
             gen_goto_ptr();
             break;
         default:
             /* indicate that the hash table must be used to find the next TB */
             tcg_gen_exit_tb(0);
             break;
-        case DISAS_TB_JUMP:
-        case DISAS_EXC:
+        case DJ_TB_JUMP:
+        case DJ_EXC:
             /* nothing more to generate */
             break;
-        case DISAS_WFI:
+        case DJ_WFI:
             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;
-        case DISAS_WFE:
+        case DJ_WFE:
             gen_helper_wfe(cpu_env);
             break;
-        case DISAS_YIELD:
+        case DJ_YIELD:
             gen_helper_yield(cpu_env);
             break;
-        case DISAS_SWI:
+        case DJ_SWI:
             gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
                           default_exception_el(dc));
             break;
-        case DISAS_HVC:
+        case DJ_HVC:
             gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
             break;
-        case DISAS_SMC:
+        case DJ_SMC:
             gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
             break;
         }
diff --git a/target/arm/translate.h b/target/arm/translate.h
index e42fdbe61c..d6511a2524 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -119,31 +119,33 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
     s->insn_start_idx = 0;
 }
 
-/* target-specific extra values for is_jmp */
-/* TODO: rename as DJ_* when transitioning this target to generic translation */
+/* Target-specific values for DisasContextBase::is_jmp */
+#define DJ_JUMP    (DJ_TARGET + 0)
+#define DJ_UPDATE  (DJ_TARGET + 1)
+#define DJ_TB_JUMP (DJ_TARGET + 2)
 /* 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 (DISAS_TARGET + 0)
-#define DISAS_SWI (DISAS_TARGET + 1)
+#define DJ_WFI     (DJ_TARGET + 3)
+#define DJ_SWI     (DJ_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 (DISAS_TARGET + 2)
+#define DJ_EXC     (DJ_TARGET + 5)
 /* WFE */
-#define DISAS_WFE (DISAS_TARGET + 3)
-#define DISAS_HVC (DISAS_TARGET + 4)
-#define DISAS_SMC (DISAS_TARGET + 5)
-#define DISAS_YIELD (DISAS_TARGET + 6)
+#define DJ_WFE     (DJ_TARGET + 6)
+#define DJ_HVC     (DJ_TARGET + 7)
+#define DJ_SMC     (DJ_TARGET + 8)
+#define DJ_YIELD   (DJ_TARGET + 9)
 /* M profile branch which might be an exception return (and so needs
  * custom end-of-TB code)
  */
-#define DISAS_BX_EXCRET (DISAS_TARGET + 7)
+#define DJ_BX_EXCRET (DJ_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 (DISAS_TARGET + 8)
+#define DJ_EXIT (DJ_TARGET + 11)
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);

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

* [Qemu-devel] [PATCH v9 17/26] target: [tcg, arm] Port to DisasContextBase
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (14 preceding siblings ...)
  2017-06-25  9:48 ` [Qemu-devel] [PATCH v9 16/26] target: [tcg, arm] " Lluís Vilanova
@ 2017-06-25  9:52 ` Lluís Vilanova
  2017-06-25  9:56 ` [Qemu-devel] [PATCH v9 18/26] target: [tcg, arm] Port to init_disas_context Lluís Vilanova
                   ` (10 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:52 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |  113 ++++++++++++++++++--------------
 target/arm/translate.c     |  154 ++++++++++++++++++++++++++++----------------
 target/arm/translate.h     |   11 ++-
 3 files changed, 167 insertions(+), 111 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index d2fe2718ad..8d48251321 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -302,17 +302,21 @@ static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
 
 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
 {
+    DisasContextBase *b = &s->base;
+
     gen_a64_set_pc_im(s->pc - offset);
     gen_exception_internal(excp);
-    s->is_jmp = DJ_EXC;
+    b->is_jmp = DJ_EXC;
 }
 
 static void gen_exception_insn(DisasContext *s, int offset, int excp,
                                uint32_t syndrome, uint32_t target_el)
 {
+    DisasContextBase *b = &s->base;
+
     gen_a64_set_pc_im(s->pc - offset);
     gen_exception(excp, syndrome, target_el);
-    s->is_jmp = DJ_EXC;
+    b->is_jmp = DJ_EXC;
 }
 
 static void gen_ss_advance(DisasContext *s)
@@ -328,6 +332,8 @@ static void gen_ss_advance(DisasContext *s)
 
 static void gen_step_complete_exception(DisasContext *s)
 {
+    DisasContextBase *b = &s->base;
+
     /* We just completed step of an insn. Move from Active-not-pending
      * to Active-pending, and then also take the swstep exception.
      * This corresponds to making the (IMPDEF) choice to prioritize
@@ -340,21 +346,23 @@ 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 = DJ_EXC;
+    b->is_jmp = DJ_EXC;
 }
 
 static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
 {
+    DisasContextBase *b = &s->base;
+
     /* 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 (b->singlestep_enabled || s->ss_active || (b->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 ((b->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
         return false;
     }
 #endif
@@ -364,23 +372,24 @@ static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
 
 static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
 {
+    DisasContextBase *b = &s->base;
     TranslationBlock *tb;
 
-    tb = s->tb;
+    tb = b->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 = DJ_TB_JUMP;
+        b->is_jmp = DJ_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 (b->singlestep_enabled) {
             gen_exception_internal(EXCP_DEBUG);
         } else {
             tcg_gen_lookup_and_goto_ptr(cpu_pc);
-            s->is_jmp = DJ_TB_JUMP;
+            b->is_jmp = DJ_TB_JUMP;
         }
     }
 }
@@ -1320,6 +1329,7 @@ static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
 static void handle_hint(DisasContext *s, uint32_t insn,
                         unsigned int op1, unsigned int op2, unsigned int crm)
 {
+    DisasContextBase *b = &s->base;
     unsigned int selector = crm << 3 | op2;
 
     if (op1 != 3) {
@@ -1331,16 +1341,16 @@ static void handle_hint(DisasContext *s, uint32_t insn,
     case 0: /* NOP */
         return;
     case 3: /* WFI */
-        s->is_jmp = DJ_WFI;
+        b->is_jmp = DJ_WFI;
         return;
     case 1: /* YIELD */
         if (!parallel_cpus) {
-            s->is_jmp = DJ_YIELD;
+            b->is_jmp = DJ_YIELD;
         }
         return;
     case 2: /* WFE */
         if (!parallel_cpus) {
-            s->is_jmp = DJ_WFE;
+            b->is_jmp = DJ_WFE;
         }
         return;
     case 4: /* SEV */
@@ -1362,6 +1372,7 @@ static void gen_clrex(DisasContext *s, uint32_t insn)
 static void handle_sync(DisasContext *s, uint32_t insn,
                         unsigned int op1, unsigned int op2, unsigned int crm)
 {
+    DisasContextBase *b = &s->base;
     TCGBar bar;
 
     if (op1 != 3) {
@@ -1393,7 +1404,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 = DJ_UPDATE;
+        b->is_jmp = DJ_UPDATE;
         return;
     default:
         unallocated_encoding(s);
@@ -1405,6 +1416,7 @@ static void handle_sync(DisasContext *s, uint32_t insn,
 static void handle_msr_i(DisasContext *s, uint32_t insn,
                          unsigned int op1, unsigned int op2, unsigned int crm)
 {
+    DisasContextBase *b = &s->base;
     int op = op1 << 3 | op2;
     switch (op) {
     case 0x05: /* SPSel */
@@ -1422,7 +1434,7 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
         gen_helper_msr_i_pstate(cpu_env, tcg_op, tcg_imm);
         tcg_temp_free_i32(tcg_imm);
         tcg_temp_free_i32(tcg_op);
-        s->is_jmp = DJ_UPDATE;
+        b->is_jmp = DJ_UPDATE;
         break;
     }
     default:
@@ -1486,6 +1498,7 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
                        unsigned int op0, unsigned int op1, unsigned int op2,
                        unsigned int crn, unsigned int crm, unsigned int rt)
 {
+    DisasContextBase *b = &s->base;
     const ARMCPRegInfo *ri;
     TCGv_i64 tcg_rt;
 
@@ -1557,7 +1570,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 ((b->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
         gen_io_start(cpu_env);
     }
 
@@ -1588,16 +1601,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 ((b->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(cpu_env);
-        s->is_jmp = DJ_UPDATE;
+        b->is_jmp = DJ_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 = DJ_UPDATE;
+        b->is_jmp = DJ_UPDATE;
     }
 }
 
@@ -1757,6 +1770,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
  */
 static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
 {
+    DisasContextBase *b = &s->base;
     unsigned int opc, op2, op3, rn, op4;
 
     opc = extract32(insn, 21, 4);
@@ -1786,7 +1800,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
             return;
         }
         gen_helper_exception_return(cpu_env);
-        s->is_jmp = DJ_JUMP;
+        b->is_jmp = DJ_JUMP;
         return;
     case 5: /* DRPS */
         if (rn != 0x1f) {
@@ -1800,7 +1814,7 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
         return;
     }
 
-    s->is_jmp = DJ_JUMP;
+    b->is_jmp = DJ_JUMP;
 }
 
 /* C3.2 Branches, exception generating and system instructions */
@@ -11188,23 +11202,23 @@ 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(DisasContextBase *db, ARMCPU *cpu,
+                               TranslationBlock *tb)
 {
     CPUState *cs = CPU(cpu);
     CPUARMState *env = &cpu->env;
-    DisasContext dc1, *dc = &dc1;
-    target_ulong pc_start;
+    DisasContext *dc = container_of(db, DisasContext, base);
     target_ulong next_page_start;
-    int num_insns;
     int max_insns;
 
-    pc_start = tb->pc;
-
-    dc->tb = tb;
+    db->tb = tb;
+    db->pc_first = tb->pc;
+    db->pc_next = db->pc_first;
+    db->is_jmp = DJ_NEXT;
+    db->num_insns = 0;
+    db->singlestep_enabled = cs->singlestep_enabled;
 
-    dc->is_jmp = DJ_NEXT;
-    dc->pc = pc_start;
-    dc->singlestep_enabled = cs->singlestep_enabled;
+    dc->pc = db->pc_first;
     dc->condjmp = 0;
 
     dc->aarch64 = 1;
@@ -11253,8 +11267,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
 
     init_tmp_a64_array(dc);
 
-    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
-    num_insns = 0;
+    next_page_start = (db->pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
         max_insns = CF_COUNT_MASK;
@@ -11268,9 +11281,9 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
     tcg_clear_temp_count();
 
     do {
+        db->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;
@@ -11280,7 +11293,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, 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 = DJ_UPDATE;
+                        db->is_jmp = DJ_UPDATE;
                     } else {
                         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
                         /* The address covered by the breakpoint must be
@@ -11296,7 +11309,7 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
             }
         }
 
-        if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
+        if (db->num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start(cpu_env);
         }
 
@@ -11311,10 +11324,10 @@ void gen_intermediate_code_a64(ARMCPU *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(db->num_insns == 1);
             gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
                           default_exception_el(dc));
-            dc->is_jmp = DJ_EXC;
+            db->is_jmp = DJ_EXC;
             break;
         }
 
@@ -11330,26 +11343,26 @@ void gen_intermediate_code_a64(ARMCPU *cpu, 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 (!db->is_jmp && !tcg_op_buf_full() &&
              !cs->singlestep_enabled &&
              !singlestep &&
              !dc->ss_active &&
              dc->pc < next_page_start &&
-             num_insns < max_insns);
+             db->num_insns < max_insns);
 
     if (tb->cflags & CF_LAST_IO) {
         gen_io_end(cpu_env);
     }
 
     if (unlikely(cs->singlestep_enabled || dc->ss_active)
-        && dc->is_jmp != DJ_EXC) {
+        && db->is_jmp != DJ_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 != DJ_TB_JUMP);
-        if (dc->is_jmp != DJ_JUMP) {
+        assert(db->is_jmp != DJ_TB_JUMP);
+        if (db->is_jmp != DJ_JUMP) {
             gen_a64_set_pc_im(dc->pc);
         }
         if (cs->singlestep_enabled) {
@@ -11358,7 +11371,9 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
             gen_step_complete_exception(dc);
         }
     } else {
-        switch (dc->is_jmp) {
+        /* Cast because target-specific values are not in generic enum */
+        unsigned int is_jmp = (unsigned int)db->is_jmp;
+        switch (is_jmp) {
         case DJ_NEXT:
             gen_goto_tb(dc, 1, dc->pc);
             break;
@@ -11396,20 +11411,20 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
     }
 
 done_generating:
-    gen_tb_end(tb, num_insns);
+    gen_tb_end(tb, db->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(db->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(db->pc_first));
+        log_target_disas(cs, db->pc_first, dc->pc - db->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;
+    tb->size = dc->pc - db->pc_first;
+    tb->icount = db->num_insns;
 }
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 04063fed6b..19d042d843 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -217,6 +217,8 @@ static inline TCGv_i32 load_reg(DisasContext *s, int reg)
    marked as dead.  */
 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
 {
+    DisasContextBase *b = &s->base;
+
     if (reg == 15) {
         /* In Thumb mode, we must ignore bit 0.
          * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
@@ -224,7 +226,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 = DJ_JUMP;
+        b->is_jmp = DJ_JUMP;
     }
     tcg_gen_mov_i32(cpu_R[reg], var);
     tcg_temp_free_i32(var);
@@ -285,6 +287,8 @@ static void gen_ss_advance(DisasContext *s)
 
 static void gen_step_complete_exception(DisasContext *s)
 {
+    DisasContextBase *b = &s->base;
+
     /* We just completed step of an insn. Move from Active-not-pending
      * to Active-pending, and then also take the swstep exception.
      * This corresponds to making the (IMPDEF) choice to prioritize
@@ -297,7 +301,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 = DJ_EXC;
+    b->is_jmp = DJ_EXC;
 }
 
 static void gen_singlestep_exception(DisasContext *s)
@@ -315,13 +319,15 @@ static void gen_singlestep_exception(DisasContext *s)
 
 static inline bool is_singlestepping(DisasContext *s)
 {
+    DisasContextBase *b = &s->base;
+
     /* Return true if we are singlestepping either because of
      * architectural singlestep or QEMU gdbstub singlestep. This does
      * not include the command line '-singlestep' mode which is rather
      * 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 b->singlestep_enabled || s->ss_active;
 }
 
 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
@@ -926,9 +932,10 @@ static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
 /* Set PC and Thumb state from an immediate address.  */
 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
 {
+    DisasContextBase *b = &s->base;
     TCGv_i32 tmp;
 
-    s->is_jmp = DJ_JUMP;
+    b->is_jmp = DJ_JUMP;
     if (s->thumb != (addr & 1)) {
         tmp = tcg_temp_new_i32();
         tcg_gen_movi_i32(tmp, addr & 1);
@@ -941,7 +948,9 @@ 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 = DJ_JUMP;
+    DisasContextBase *b = &s->base;
+
+    b->is_jmp = DJ_JUMP;
     tcg_gen_andi_i32(cpu_R[15], var, ~1);
     tcg_gen_andi_i32(var, var, 1);
     store_cpu_field(var, thumb);
@@ -954,12 +963,14 @@ static inline void gen_bx(DisasContext *s, TCGv_i32 var)
  */
 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
 {
+    DisasContextBase *b = &s->base;
+
     /* 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.
+     * b->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 = DJ_BX_EXCRET;
+        b->is_jmp = DJ_BX_EXCRET;
     }
 }
 
@@ -1146,6 +1157,8 @@ DO_GEN_ST(32, MO_UL)
 
 static inline void gen_hvc(DisasContext *s, int imm16)
 {
+    DisasContextBase *b = &s->base;
+
     /* The pre HVC helper handles cases when HVC gets trapped
      * as an undefined insn by runtime configuration (ie before
      * the insn really executes).
@@ -1159,11 +1172,12 @@ static inline void gen_hvc(DisasContext *s, int imm16)
      */
     s->svc_imm = imm16;
     gen_set_pc_im(s, s->pc);
-    s->is_jmp = DJ_HVC;
+    b->is_jmp = DJ_HVC;
 }
 
 static inline void gen_smc(DisasContext *s)
 {
+    DisasContextBase *b = &s->base;
     /* As with HVC, we may take an exception either before or after
      * the insn executes.
      */
@@ -1174,31 +1188,37 @@ 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 = DJ_SMC;
+    b->is_jmp = DJ_SMC;
 }
 
 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
 {
+    DisasContextBase *b = &s->base;
+
     gen_set_condexec(s);
     gen_set_pc_im(s, s->pc - offset);
     gen_exception_internal(excp);
-    s->is_jmp = DJ_EXC;
+    b->is_jmp = DJ_EXC;
 }
 
 static void gen_exception_insn(DisasContext *s, int offset, int excp,
                                int syn, uint32_t target_el)
 {
+    DisasContextBase *b = &s->base;
+
     gen_set_condexec(s);
     gen_set_pc_im(s, s->pc - offset);
     gen_exception(excp, syn, target_el);
-    s->is_jmp = DJ_EXC;
+    b->is_jmp = DJ_EXC;
 }
 
 /* Force a TB lookup after an instruction that changes the CPU state.  */
 static inline void gen_lookup_tb(DisasContext *s)
 {
+    DisasContextBase *b = &s->base;
+
     tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
-    s->is_jmp = DJ_EXIT;
+    b->is_jmp = DJ_EXIT;
 }
 
 static inline void gen_hlt(DisasContext *s, int imm)
@@ -4143,7 +4163,9 @@ 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) ||
+    DisasContextBase *b = &s->base;
+
+    return (b->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
            ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
 #else
     return true;
@@ -4160,10 +4182,12 @@ static void gen_goto_ptr(void)
 
 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
 {
+    DisasContextBase *b = &s->base;
+
     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)b->tb + n);
     } else {
         gen_set_pc_im(s, dest);
         gen_goto_ptr();
@@ -4172,6 +4196,8 @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
 
 static inline void gen_jmp (DisasContext *s, uint32_t dest)
 {
+    DisasContextBase *b = &s->base;
+
     if (unlikely(is_singlestepping(s))) {
         /* An indirect jump so that we still trigger the debug exception.  */
         if (s->thumb)
@@ -4179,7 +4205,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 = DJ_TB_JUMP;
+        b->is_jmp = DJ_TB_JUMP;
     }
 }
 
@@ -4413,6 +4439,7 @@ undef:
 
 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
 {
+    DisasContextBase *b = &s->base;
     TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
     int tgtmode = 0, regno = 0;
 
@@ -4430,11 +4457,12 @@ 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 = DJ_UPDATE;
+    b->is_jmp = DJ_UPDATE;
 }
 
 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
 {
+    DisasContextBase *b = &s->base;
     TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
     int tgtmode = 0, regno = 0;
 
@@ -4452,7 +4480,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 = DJ_UPDATE;
+    b->is_jmp = DJ_UPDATE;
 }
 
 /* Store value to PC as for an exception return (ie don't
@@ -4468,6 +4496,8 @@ static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
 /* Generate a v6 exception return.  Marks both values as dead.  */
 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
 {
+    DisasContextBase *b = &s->base;
+
     store_pc_exc_ret(s, pc);
     /* The cpsr_write_eret helper will mask the low bits of PC
      * appropriately depending on the new Thumb bit, so it must
@@ -4475,7 +4505,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 = DJ_JUMP;
+    b->is_jmp = DJ_JUMP;
 }
 
 /* Generate an old-style exception return. Marks pc as dead. */
@@ -4494,21 +4524,23 @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
  */
 static void gen_nop_hint(DisasContext *s, int val)
 {
+    DisasContextBase *b = &s->base;
+
     switch (val) {
     case 1: /* yield */
         if (!parallel_cpus) {
             gen_set_pc_im(s, s->pc);
-            s->is_jmp = DJ_YIELD;
+            b->is_jmp = DJ_YIELD;
         }
         break;
     case 3: /* wfi */
         gen_set_pc_im(s, s->pc);
-        s->is_jmp = DJ_WFI;
+        b->is_jmp = DJ_WFI;
         break;
     case 2: /* wfe */
         if (!parallel_cpus) {
             gen_set_pc_im(s, s->pc);
-            s->is_jmp = DJ_WFE;
+            b->is_jmp = DJ_WFE;
         }
         break;
     case 4: /* sev */
@@ -7529,6 +7561,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
 
 static int disas_coproc_insn(DisasContext *s, uint32_t insn)
 {
+    DisasContextBase *b = &s->base;
+
     int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
     const ARMCPRegInfo *ri;
 
@@ -7647,13 +7681,13 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
                 return 1;
             }
             gen_set_pc_im(s, s->pc);
-            s->is_jmp = DJ_WFI;
+            b->is_jmp = DJ_WFI;
             return 0;
         default:
             break;
         }
 
-        if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
+        if ((b->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
             gen_io_start(cpu_env);
         }
 
@@ -7744,7 +7778,7 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
             }
         }
 
-        if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
+        if ((b->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(cpu_env);
             gen_lookup_tb(s);
@@ -7946,6 +7980,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
 static void gen_srs(DisasContext *s,
                     uint32_t mode, uint32_t amode, bool writeback)
 {
+    DisasContextBase *b = &s->base;
     int32_t offset;
     TCGv_i32 addr, tmp;
     bool undef = false;
@@ -8058,11 +8093,12 @@ static void gen_srs(DisasContext *s,
         tcg_temp_free_i32(tmp);
     }
     tcg_temp_free_i32(addr);
-    s->is_jmp = DJ_UPDATE;
+    b->is_jmp = DJ_UPDATE;
 }
 
 static void disas_arm_insn(DisasContext *s, unsigned int insn)
 {
+    DisasContextBase *b = &s->base;
     unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
     TCGv_i32 tmp;
     TCGv_i32 tmp2;
@@ -8146,7 +8182,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 = DJ_UPDATE;
+                b->is_jmp = DJ_UPDATE;
             }
             return;
         } else if ((insn & 0x0fffff00) == 0x057ff000) {
@@ -9519,7 +9555,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 = DJ_JUMP;
+                    b->is_jmp = DJ_JUMP;
                 }
             }
             break;
@@ -9557,7 +9593,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 = DJ_SWI;
+            b->is_jmp = DJ_SWI;
             break;
         default:
         illegal_op:
@@ -11013,6 +11049,7 @@ illegal_op:
 
 static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
 {
+    DisasContextBase *b = &s->base;
     uint32_t val, insn, op, rm, rn, rd, shift, cond;
     int32_t offset;
     int i;
@@ -11619,7 +11656,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 = DJ_UPDATE;
+                    b->is_jmp = DJ_UPDATE;
                 }
                 break;
             case 3:
@@ -11713,7 +11750,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 = DJ_SWI;
+            b->is_jmp = DJ_SWI;
             break;
         }
         /* generate a conditional jump to next instruction */
@@ -11792,9 +11829,8 @@ 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;
+    DisasContextBase *db = &dc->base;
     target_ulong next_page_start;
-    int num_insns;
     int max_insns;
     bool end_of_page;
 
@@ -11804,17 +11840,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(arm_cpu, tb);
+        gen_intermediate_code_a64(db, arm_cpu, tb);
         return;
     }
 
-    pc_start = tb->pc;
-
-    dc->tb = tb;
+    db->tb = tb;
+    db->pc_first = tb->pc;
+    db->pc_next = db->pc_first;
+    db->is_jmp = DJ_NEXT;
+    db->num_insns = 0;
+    db->singlestep_enabled = cpu->singlestep_enabled;
 
-    dc->is_jmp = DJ_NEXT;
-    dc->pc = pc_start;
-    dc->singlestep_enabled = cpu->singlestep_enabled;
+    dc->pc = db->pc_first;
     dc->condjmp = 0;
 
     dc->aarch64 = 0;
@@ -11871,8 +11908,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 = (db->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 +11960,11 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         store_cpu_field(tmp, condexec_bits);
       }
     do {
+        db->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.  */
@@ -11950,7 +11986,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 = DJ_UPDATE;
+                        db->is_jmp = DJ_UPDATE;
                     } else {
                         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
                         /* The address covered by the breakpoint must be
@@ -11968,7 +12004,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             }
         }
 
-        if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
+        if (db->num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start(cpu_env);
         }
 
@@ -11983,7 +12019,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(db->num_insns == 1);
             gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
                           default_exception_el(dc));
             goto done_generating;
@@ -12005,7 +12041,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             disas_arm_insn(dc, insn);
         }
 
-        if (dc->condjmp && !dc->is_jmp) {
+        if (dc->condjmp && !db->is_jmp) {
             gen_set_label(dc->condlabel);
             dc->condjmp = 0;
         }
@@ -12032,11 +12068,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 (!db->is_jmp && !tcg_op_buf_full() &&
              !is_singlestepping(dc) &&
              !singlestep &&
              !end_of_page &&
-             num_insns < max_insns);
+             db->num_insns < max_insns);
 
     if (tb->cflags & CF_LAST_IO) {
         if (dc->condjmp) {
@@ -12051,7 +12087,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 == DJ_BX_EXCRET) {
+    if (db->is_jmp == DJ_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
@@ -12059,8 +12095,10 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
          */
         gen_bx_excret_final_code(dc);
     } else if (unlikely(is_singlestepping(dc))) {
+        /* Cast because target-specific values are not in generic enum */
+        unsigned int is_jmp = (unsigned int)db->is_jmp;
         /* Unconditional and "condition passed" instruction codepath. */
-        switch (dc->is_jmp) {
+        switch (is_jmp) {
         case DJ_SWI:
             gen_ss_advance(dc);
             gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
@@ -12083,6 +12121,8 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             gen_singlestep_exception(dc);
         }
     } else {
+        /* Cast because target-specific values are not in generic enum */
+        unsigned int is_jmp = (unsigned int)db->is_jmp;
         /* While branches must always occur at the end of an IT block,
            there are a few other things that can cause us to terminate
            the TB in the middle of an IT block:
@@ -12091,7 +12131,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 (is_jmp) {
         case DJ_NEXT:
             gen_goto_tb(dc, 1, dc->pc);
             break;
@@ -12148,22 +12188,22 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     }
 
 done_generating:
-    gen_tb_end(tb, num_insns);
+    gen_tb_end(tb, db->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(db->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(db->pc_first));
+        log_target_disas(cpu, db->pc_first, dc->pc - db->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 - db->pc_first;
+    tb->icount = db->num_insns;
 }
 
 static const char *cpu_mode_names[16] = {
diff --git a/target/arm/translate.h b/target/arm/translate.h
index d6511a2524..190d461134 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -3,9 +3,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.  */
@@ -13,8 +14,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;
@@ -149,7 +148,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(ARMCPU *cpu, TranslationBlock *tb);
+void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *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);
@@ -158,7 +158,8 @@ 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(DisasContextBase *db, ARMCPU *cpu,
+                                             TranslationBlock *tb)
 {
 }
 

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

* [Qemu-devel] [PATCH v9 18/26] target: [tcg, arm] Port to init_disas_context
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (15 preceding siblings ...)
  2017-06-25  9:52 ` [Qemu-devel] [PATCH v9 17/26] target: [tcg, arm] Port to DisasContextBase Lluís Vilanova
@ 2017-06-25  9:56 ` Lluís Vilanova
  2017-06-25 10:00 ` [Qemu-devel] [PATCH v9 19/26] target: [tcg, arm] Port to init_globals Lluís Vilanova
                   ` (9 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25  9:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |   51 +++++++++++++++-----------
 target/arm/translate.c     |   87 ++++++++++++++++++++++++--------------------
 2 files changed, 78 insertions(+), 60 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 8d48251321..1959f27377 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11202,21 +11202,12 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
     free_tmp_a64(s);
 }
 
-void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
-                               TranslationBlock *tb)
+static void aarch64_trblock_init_disas_context(DisasContextBase *db,
+                                               CPUState *cpu)
 {
-    CPUState *cs = CPU(cpu);
-    CPUARMState *env = &cpu->env;
     DisasContext *dc = container_of(db, DisasContext, base);
-    target_ulong next_page_start;
-    int max_insns;
-
-    db->tb = tb;
-    db->pc_first = tb->pc;
-    db->pc_next = db->pc_first;
-    db->is_jmp = DJ_NEXT;
-    db->num_insns = 0;
-    db->singlestep_enabled = cs->singlestep_enabled;
+    CPUARMState *env = cpu->env_ptr;
+    ARMCPU *arm_cpu = arm_env_get_cpu(env);
 
     dc->pc = db->pc_first;
     dc->condjmp = 0;
@@ -11229,20 +11220,20 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
                                !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(db->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(db->tb->flags));
+    dc->tbi0 = ARM_TBFLAG_TBI0(db->tb->flags);
+    dc->tbi1 = ARM_TBFLAG_TBI1(db->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(db->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:
@@ -11260,12 +11251,30 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
      *   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(db->tb->flags);
+    dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(db->tb->flags);
     dc->is_ldex = false;
     dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
 
     init_tmp_a64_array(dc);
+}
+
+void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
+                               TranslationBlock *tb)
+{
+    CPUState *cs = CPU(cpu);
+    CPUARMState *env = &cpu->env;
+    DisasContext *dc = container_of(db, DisasContext, base);
+    target_ulong next_page_start;
+    int max_insns;
+
+    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 = cs->singlestep_enabled;
+    aarch64_trblock_init_disas_context(db, cs);
 
     next_page_start = (db->pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     max_insns = tb->cflags & CF_COUNT_MASK;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 19d042d843..c469bc70ac 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11823,33 +11823,11 @@ 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 *db, CPUState *cpu)
 {
+    DisasContext *dc = container_of(db, DisasContext, base);
     CPUARMState *env = cpu->env_ptr;
     ARMCPU *arm_cpu = arm_env_get_cpu(env);
-    DisasContext dc1, *dc = &dc1;
-    DisasContextBase *db = &dc->base;
-    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(db, arm_cpu, tb);
-        return;
-    }
-
-    db->tb = tb;
-    db->pc_first = tb->pc;
-    db->pc_next = db->pc_first;
-    db->is_jmp = DJ_NEXT;
-    db->num_insns = 0;
-    db->singlestep_enabled = cpu->singlestep_enabled;
 
     dc->pc = db->pc_first;
     dc->condjmp = 0;
@@ -11860,23 +11838,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(db->tb->flags);
+    dc->sctlr_b = ARM_TBFLAG_SCTLR_B(db->tb->flags);
+    dc->be_data = ARM_TBFLAG_BE_DATA(db->tb->flags) ? MO_BE : MO_LE;
+    dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(db->tb->flags) & 0xf) << 1;
+    dc->condexec_cond = ARM_TBFLAG_CONDEXEC(db->tb->flags) >> 4;
+    dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(db->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(db->tb->flags);
+    dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(db->tb->flags);
+    dc->vfp_enabled = ARM_TBFLAG_VFPEN(db->tb->flags);
+    dc->vec_len = ARM_TBFLAG_VECLEN(db->tb->flags);
+    dc->vec_stride = ARM_TBFLAG_VECSTRIDE(db->tb->flags);
+    dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(db->tb->flags);
+    dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(db->tb->flags);
     dc->cp_regs = arm_cpu->cp_regs;
     dc->features = env->features;
 
@@ -11895,10 +11873,41 @@ 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(db->tb->flags);
+    dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(db->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;
+    ARMCPU *arm_cpu = arm_env_get_cpu(env);
+    DisasContext dc1, *dc = &dc1;
+    DisasContextBase *db = &dc->base;
+    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(db, arm_cpu, tb);
+        return;
+    }
+
+    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;
+    arm_trblock_init_disas_context(db, cpu);
+
 
     cpu_F0s = tcg_temp_new_i32();
     cpu_F1s = tcg_temp_new_i32();

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

* [Qemu-devel] [PATCH v9 19/26] target: [tcg, arm] Port to init_globals
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (16 preceding siblings ...)
  2017-06-25  9:56 ` [Qemu-devel] [PATCH v9 18/26] target: [tcg, arm] Port to init_disas_context Lluís Vilanova
@ 2017-06-25 10:00 ` Lluís Vilanova
  2017-06-25 10:04 ` [Qemu-devel] [PATCH v9 20/26] target: [tcg,arm] Port to tb_start Lluís Vilanova
                   ` (8 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25 10:00 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 c469bc70ac..cc11dacd56 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11879,6 +11879,18 @@ static void arm_trblock_init_disas_context(DisasContextBase *db, CPUState *cpu)
     dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
 }
 
+static void arm_trblock_init_globals(DisasContextBase *db, 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)
 {
@@ -11909,14 +11921,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     arm_trblock_init_disas_context(db, 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(db, cpu);
     next_page_start = (db->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] 57+ messages in thread

* [Qemu-devel] [PATCH v9 20/26] target: [tcg,arm] Port to tb_start
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (17 preceding siblings ...)
  2017-06-25 10:00 ` [Qemu-devel] [PATCH v9 19/26] target: [tcg, arm] Port to init_globals Lluís Vilanova
@ 2017-06-25 10:04 ` Lluís Vilanova
  2017-06-25 10:08 ` [Qemu-devel] [PATCH v9 21/26] target: [tcg, arm] Port to insn_start Lluís Vilanova
                   ` (7 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25 10:04 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 cc11dacd56..ae3f772446 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11891,6 +11891,49 @@ static void arm_trblock_init_globals(DisasContextBase *db, CPUState *cpu)
     cpu_M0 = tcg_temp_new_i64();
 }
 
+static void arm_trblock_tb_start(DisasContextBase *db, CPUState *cpu)
+{
+    DisasContext *dc = container_of(db, 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)
 {
@@ -11934,45 +11977,8 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     gen_tb_start(tb, cpu_env);
 
     tcg_clear_temp_count();
+    arm_trblock_tb_start(db, 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 {
         db->num_insns++;
         dc->insn_start_idx = tcg_op_buf_count();

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

* [Qemu-devel] [PATCH v9 21/26] target: [tcg, arm] Port to insn_start
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (18 preceding siblings ...)
  2017-06-25 10:04 ` [Qemu-devel] [PATCH v9 20/26] target: [tcg,arm] Port to tb_start Lluís Vilanova
@ 2017-06-25 10:08 ` Lluís Vilanova
  2017-06-26 11:31   ` Alex Bennée
  2017-06-27  3:33   ` Richard Henderson
  2017-06-25 10:12 ` [Qemu-devel] [PATCH v9 22/26] target: [tcg, arm] Port to breakpoint_check Lluís Vilanova
                   ` (6 subsequent siblings)
  26 siblings, 2 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25 10:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 +++++++++--
 target/arm/translate.c     |   36 +++++++++++++++++++++---------------
 2 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 1959f27377..bfc2cdabb5 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11259,6 +11259,14 @@ static void aarch64_trblock_init_disas_context(DisasContextBase *db,
     init_tmp_a64_array(dc);
 }
 
+static void aarch64_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
+{
+    DisasContext *dc = container_of(db, DisasContext, base);
+
+    dc->insn_start_idx = tcg_op_buf_count();
+    tcg_gen_insn_start(dc->pc, 0, 0);
+}
+
 void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
                                TranslationBlock *tb)
 {
@@ -11291,8 +11299,7 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
 
     do {
         db->num_insns++;
-        dc->insn_start_idx = tcg_op_buf_count();
-        tcg_gen_insn_start(dc->pc, 0, 0);
+        aarch64_trblock_insn_start(db, cs);
 
         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
             CPUBreakpoint *bp;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index ae3f772446..18b0e8fbb6 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11934,6 +11934,26 @@ static void arm_trblock_tb_start(DisasContextBase *db, CPUState *cpu)
     }
 }
 
+static void arm_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
+{
+    DisasContext *dc = container_of(db, 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->is_jmp = DJ_EXC;
+    }
+#endif
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -11981,21 +12001,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 
     do {
         db->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);
-
-#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->is_jmp = DJ_EXC;
-            break;
-        }
-#endif
+        arm_trblock_insn_start(db, cpu);
 
         if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
             CPUBreakpoint *bp;

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

* [Qemu-devel] [PATCH v9 22/26] target: [tcg, arm] Port to breakpoint_check
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (19 preceding siblings ...)
  2017-06-25 10:08 ` [Qemu-devel] [PATCH v9 21/26] target: [tcg, arm] Port to insn_start Lluís Vilanova
@ 2017-06-25 10:12 ` Lluís Vilanova
  2017-06-25 10:16 ` [Qemu-devel] [PATCH v9 23/26] target: [tcg, arm] Port to disas_insn Lluís Vilanova
                   ` (5 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25 10:12 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |   59 ++++++++++++++++++++++++++-------------
 target/arm/translate.c     |   66 +++++++++++++++++++++++++++++---------------
 2 files changed, 82 insertions(+), 43 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index bfc2cdabb5..4321767355 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11267,6 +11267,29 @@ static void aarch64_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
     tcg_gen_insn_start(dc->pc, 0, 0);
 }
 
+static BreakpointCheckType aarch64_trblock_breakpoint_check(
+    DisasContextBase *db, CPUState *cpu, const CPUBreakpoint *bp)
+{
+    DisasContext *dc = container_of(db, 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 */
+        db->is_jmp = DJ_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 *db, ARMCPU *cpu,
                                TranslationBlock *tb)
 {
@@ -11275,6 +11298,7 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
     DisasContext *dc = container_of(db, DisasContext, base);
     target_ulong next_page_start;
     int max_insns;
+    CPUBreakpoint *bp;
 
     db->tb = tb;
     db->pc_first = tb->pc;
@@ -11301,29 +11325,24 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
         db->num_insns++;
         aarch64_trblock_insn_start(db, 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 */
-                        db->is_jmp = DJ_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.  */
-                        dc->pc += 4;
-                        goto done_generating;
-                    }
+        bp = NULL;
+        do {
+            bp = cpu_breakpoint_get(cs, db->pc_next, bp);
+            if (unlikely(bp)) {
+                BreakpointCheckType bp_check =
+                    aarch64_trblock_breakpoint_check(db, cs, bp);
+                if (bp_check == 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.
+                     */
                     break;
+                } else {
+                    goto done_generating;
                 }
             }
-        }
+        } while (bp != NULL);
 
         if (db->num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start(cpu_env);
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 18b0e8fbb6..a7fcaf2a21 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11954,6 +11954,33 @@ static void arm_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
 #endif
 }
 
+static BreakpointCheckType arm_trblock_breakpoint_check(DisasContextBase *db,
+                                                        CPUState *cpu,
+                                                        const CPUBreakpoint *bp)
+{
+    DisasContext *dc = container_of(db, 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 */
+        db->is_jmp = DJ_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)
 {
@@ -11964,6 +11991,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     target_ulong next_page_start;
     int max_insns;
     bool end_of_page;
+    CPUBreakpoint *bp;
 
     /* generate intermediate code */
 
@@ -12003,32 +12031,24 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
         db->num_insns++;
         arm_trblock_insn_start(db, cpu);
 
-        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 */
-                        db->is_jmp = DJ_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;
-                        goto done_generating;
-                    }
+        bp = NULL;
+        do {
+            bp = cpu_breakpoint_get(cpu, db->pc_next, bp);
+            if (unlikely(bp)) {
+                BreakpointCheckType bp_check = arm_trblock_breakpoint_check(
+                    db, cpu, bp);
+                if (bp_check == 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.
+                     */
                     break;
+                } else {
+                    goto done_generating;
                 }
             }
-        }
+        } while (bp != NULL);
 
         if (db->num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start(cpu_env);

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

* [Qemu-devel] [PATCH v9 23/26] target: [tcg, arm] Port to disas_insn
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (20 preceding siblings ...)
  2017-06-25 10:12 ` [Qemu-devel] [PATCH v9 22/26] target: [tcg, arm] Port to breakpoint_check Lluís Vilanova
@ 2017-06-25 10:16 ` Lluís Vilanova
  2017-06-25 10:20 ` [Qemu-devel] [PATCH v9 24/26] target: [tcg,arm] Port to tb_stop Lluís Vilanova
                   ` (4 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25 10:16 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |   73 ++++++++++++++--------
 target/arm/translate.c     |  144 +++++++++++++++++++++++++-------------------
 target/arm/translate.h     |    4 +
 3 files changed, 131 insertions(+), 90 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 4321767355..f618a15062 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11256,6 +11256,8 @@ static void aarch64_trblock_init_disas_context(DisasContextBase *db,
     dc->is_ldex = false;
     dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
 
+    dc->next_page_start = (db->pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+
     init_tmp_a64_array(dc);
 }
 
@@ -11290,13 +11292,46 @@ static BreakpointCheckType aarch64_trblock_breakpoint_check(
     }
 }
 
+static target_ulong aarch64_trblock_disas_insn(DisasContextBase *db,
+                                               CPUState *cpu)
+{
+    DisasContext *dc = container_of(db, 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(db->num_insns == 1);
+        gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
+                      default_exception_el(dc));
+        db->is_jmp = DJ_EXC;
+    } else {
+        disas_a64_insn(env, dc);
+    }
+
+    if (dc->ss_active) {
+        db->is_jmp = DJ_SS;
+    } else if (dc->pc >= dc->next_page_start) {
+        db->is_jmp = DJ_PAGE_CROSS;
+    }
+
+    return dc->pc;
+}
+
 void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
                                TranslationBlock *tb)
 {
     CPUState *cs = CPU(cpu);
-    CPUARMState *env = &cpu->env;
     DisasContext *dc = container_of(db, DisasContext, base);
-    target_ulong next_page_start;
     int max_insns;
     CPUBreakpoint *bp;
 
@@ -11308,7 +11343,6 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
     db->singlestep_enabled = cs->singlestep_enabled;
     aarch64_trblock_init_disas_context(db, cs);
 
-    next_page_start = (db->pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
         max_insns = CF_COUNT_MASK;
@@ -11348,42 +11382,24 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
             gen_io_start(cpu_env);
         }
 
-        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(db->num_insns == 1);
-            gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
-                          default_exception_el(dc));
-            db->is_jmp = DJ_EXC;
-            break;
-        }
-
-        disas_a64_insn(env, dc);
+        db->pc_next = aarch64_trblock_disas_insn(db, cs);
 
         if (tcg_check_temp_count()) {
             fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
                     dc->pc);
         }
 
+        if (!db->is_jmp && (tcg_op_buf_full() || cs->singlestep_enabled ||
+                            singlestep || db->num_insns >= max_insns)) {
+            db->is_jmp = DJ_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 (!db->is_jmp && !tcg_op_buf_full() &&
-             !cs->singlestep_enabled &&
-             !singlestep &&
-             !dc->ss_active &&
-             dc->pc < next_page_start &&
-             db->num_insns < max_insns);
+    } while (!db->is_jmp);
 
     if (tb->cflags & CF_LAST_IO) {
         gen_io_end(cpu_env);
@@ -11410,6 +11426,7 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
         unsigned int is_jmp = (unsigned int)db->is_jmp;
         switch (is_jmp) {
         case DJ_NEXT:
+        case DJ_TOO_MANY:
             gen_goto_tb(dc, 1, dc->pc);
             break;
         default:
diff --git a/target/arm/translate.c b/target/arm/translate.c
index a7fcaf2a21..f4c57ed078 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11877,6 +11877,8 @@ static void arm_trblock_init_disas_context(DisasContextBase *db, CPUState *cpu)
     dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(db->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 = (db->pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
 }
 
 static void arm_trblock_init_globals(DisasContextBase *db, CPUState *cpu)
@@ -11981,6 +11983,76 @@ static BreakpointCheckType arm_trblock_breakpoint_check(DisasContextBase *db,
     }
 }
 
+static target_ulong arm_trblock_disas_insn(DisasContextBase *db, CPUState *cpu)
+{
+    DisasContext *dc = container_of(db, 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(db->num_insns == 1);
+        gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
+                      default_exception_el(dc));
+        db->is_jmp = DJ_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 && !db->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)) {
+        db->is_jmp = DJ_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 DJ_PAGE_CROSS;
+    }
+
+    return dc->pc;
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -11988,9 +12060,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
     ARMCPU *arm_cpu = arm_env_get_cpu(env);
     DisasContext dc1, *dc = &dc1;
     DisasContextBase *db = &dc->base;
-    target_ulong next_page_start;
     int max_insns;
-    bool end_of_page;
     CPUBreakpoint *bp;
 
     /* generate intermediate code */
@@ -12013,7 +12083,6 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 
 
     arm_trblock_init_globals(db, cpu);
-    next_page_start = (db->pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
         max_insns = CF_COUNT_MASK;
@@ -12054,72 +12123,20 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             gen_io_start(cpu_env);
         }
 
-        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(db->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 && !db->is_jmp) {
-            gen_set_label(dc->condlabel);
-            dc->condjmp = 0;
-        }
+        db->pc_next = arm_trblock_disas_insn(db, 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 (!db->is_jmp && !tcg_op_buf_full() &&
-             !is_singlestepping(dc) &&
-             !singlestep &&
-             !end_of_page &&
-             db->num_insns < max_insns);
+        if (!db->is_jmp && (tcg_op_buf_full() || singlestep ||
+                            db->num_insns >= max_insns)) {
+            db->is_jmp = DJ_TOO_MANY;
+        }
+    } while (!db->is_jmp);
 
+    if (db->is_jmp != DJ_SKIP) {
     if (tb->cflags & CF_LAST_IO) {
         if (dc->condjmp) {
             /* FIXME:  This can theoretically happen with self-modifying
@@ -12159,6 +12176,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
             break;
         case DJ_NEXT:
+        case DJ_TOO_MANY:
         case DJ_UPDATE:
             gen_set_pc_im(dc, dc->pc);
             /* fall through */
@@ -12179,6 +12197,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
          */
         switch (is_jmp) {
         case DJ_NEXT:
+        case DJ_TOO_MANY:
             gen_goto_tb(dc, 1, dc->pc);
             break;
         case DJ_UPDATE:
@@ -12232,6 +12251,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
             gen_goto_tb(dc, 1, dc->pc);
         }
     }
+    }
 
 done_generating:
     gen_tb_end(tb, db->num_insns);
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 190d461134..43e8b555e3 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -6,6 +6,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;
@@ -145,6 +146,9 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
  * as opposed to attempting to use lookup_and_goto_ptr.
  */
 #define DJ_EXIT (DJ_TARGET + 11)
+#define DJ_SS   (DJ_TARGET + 12)
+#define DJ_PAGE_CROSS (DJ_TARGET + 13)
+#define DJ_SKIP (DJ_TARGET + 14)
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);

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

* [Qemu-devel] [PATCH v9 24/26] target: [tcg,arm] Port to tb_stop
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (21 preceding siblings ...)
  2017-06-25 10:16 ` [Qemu-devel] [PATCH v9 23/26] target: [tcg, arm] Port to disas_insn Lluís Vilanova
@ 2017-06-25 10:20 ` Lluís Vilanova
  2017-06-25 10:24 ` [Qemu-devel] [PATCH v9 25/26] target: [tcg, arm] Port to disas_flags Lluís Vilanova
                   ` (3 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25 10:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |  121 +++++++++++++++--------------
 target/arm/translate.c     |  185 ++++++++++++++++++++++++--------------------
 2 files changed, 164 insertions(+), 142 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index f618a15062..b14e96cd58 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11327,6 +11327,68 @@ static target_ulong aarch64_trblock_disas_insn(DisasContextBase *db,
     return dc->pc;
 }
 
+static void aarch64_trblock_tb_stop(DisasContextBase *db, CPUState *cpu)
+{
+    DisasContext *dc = container_of(db, DisasContext, base);
+
+    if (unlikely(db->singlestep_enabled || dc->ss_active)
+        && db->is_jmp != DJ_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(db->is_jmp != DJ_TB_JUMP);
+        if (db->is_jmp != DJ_JUMP) {
+            gen_a64_set_pc_im(dc->pc);
+        }
+        if (db->singlestep_enabled) {
+            gen_exception_internal(EXCP_DEBUG);
+        } else {
+            gen_step_complete_exception(dc);
+        }
+    } else {
+        /* Cast because target-specific values are not in generic enum */
+        unsigned int is_jmp = (unsigned int)db->is_jmp;
+        switch (is_jmp) {
+        case DJ_NEXT:
+        case DJ_TOO_MANY:
+            gen_goto_tb(dc, 1, dc->pc);
+            break;
+        default:
+        case DJ_UPDATE:
+            gen_a64_set_pc_im(dc->pc);
+            /* fall through */
+        case DJ_JUMP:
+            tcg_gen_lookup_and_goto_ptr(cpu_pc);
+            break;
+        case DJ_TB_JUMP:
+        case DJ_EXC:
+        case DJ_SWI:
+            break;
+        case DJ_WFE:
+            gen_a64_set_pc_im(dc->pc);
+            gen_helper_wfe(cpu_env);
+            break;
+        case DJ_YIELD:
+            gen_a64_set_pc_im(dc->pc);
+            gen_helper_yield(cpu_env);
+            break;
+        case DJ_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 *db, ARMCPU *cpu,
                                TranslationBlock *tb)
 {
@@ -11401,67 +11463,12 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
          */
     } while (!db->is_jmp);
 
+    aarch64_trblock_tb_stop(db, cs);
+
     if (tb->cflags & CF_LAST_IO) {
         gen_io_end(cpu_env);
     }
 
-    if (unlikely(cs->singlestep_enabled || dc->ss_active)
-        && db->is_jmp != DJ_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(db->is_jmp != DJ_TB_JUMP);
-        if (db->is_jmp != DJ_JUMP) {
-            gen_a64_set_pc_im(dc->pc);
-        }
-        if (cs->singlestep_enabled) {
-            gen_exception_internal(EXCP_DEBUG);
-        } else {
-            gen_step_complete_exception(dc);
-        }
-    } else {
-        /* Cast because target-specific values are not in generic enum */
-        unsigned int is_jmp = (unsigned int)db->is_jmp;
-        switch (is_jmp) {
-        case DJ_NEXT:
-        case DJ_TOO_MANY:
-            gen_goto_tb(dc, 1, dc->pc);
-            break;
-        default:
-        case DJ_UPDATE:
-            gen_a64_set_pc_im(dc->pc);
-            /* fall through */
-        case DJ_JUMP:
-            tcg_gen_lookup_and_goto_ptr(cpu_pc);
-            break;
-        case DJ_TB_JUMP:
-        case DJ_EXC:
-        case DJ_SWI:
-            break;
-        case DJ_WFE:
-            gen_a64_set_pc_im(dc->pc);
-            gen_helper_wfe(cpu_env);
-            break;
-        case DJ_YIELD:
-            gen_a64_set_pc_im(dc->pc);
-            gen_helper_yield(cpu_env);
-            break;
-        case DJ_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, db->num_insns);
 
diff --git a/target/arm/translate.c b/target/arm/translate.c
index f4c57ed078..db31611258 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -12053,97 +12053,23 @@ static target_ulong arm_trblock_disas_insn(DisasContextBase *db, CPUState *cpu)
     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 *db, CPUState *cpu)
 {
-    CPUARMState *env = cpu->env_ptr;
-    ARMCPU *arm_cpu = arm_env_get_cpu(env);
-    DisasContext dc1, *dc = &dc1;
-    DisasContextBase *db = &dc->base;
-    int max_insns;
-    CPUBreakpoint *bp;
-
-    /* generate intermediate code */
+    DisasContext *dc = container_of(db, DisasContext, base);
+    /* Cast because target-specific values are not in generic enum */
+    unsigned int is_jmp = (unsigned int)db->is_jmp;
 
-    /* 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(db, arm_cpu, tb);
+    if (is_jmp == DJ_SKIP) {
         return;
     }
 
-    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;
-    arm_trblock_init_disas_context(db, cpu);
-
-
-    arm_trblock_init_globals(db, cpu);
-    max_insns = tb->cflags & CF_COUNT_MASK;
-    if (max_insns == 0) {
-        max_insns = CF_COUNT_MASK;
+    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");
     }
-    if (max_insns > TCG_MAX_INSNS) {
-        max_insns = TCG_MAX_INSNS;
-    }
-
-    gen_tb_start(tb, cpu_env);
-
-    tcg_clear_temp_count();
-    arm_trblock_tb_start(db, cpu);
-
-    do {
-        db->num_insns++;
-        arm_trblock_insn_start(db, cpu);
-
-        bp = NULL;
-        do {
-            bp = cpu_breakpoint_get(cpu, db->pc_next, bp);
-            if (unlikely(bp)) {
-                BreakpointCheckType bp_check = arm_trblock_breakpoint_check(
-                    db, cpu, bp);
-                if (bp_check == 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.
-                     */
-                    break;
-                } else {
-                    goto done_generating;
-                }
-            }
-        } while (bp != NULL);
-
-        if (db->num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start(cpu_env);
-        }
-
-        db->pc_next = arm_trblock_disas_insn(db, cpu);
-
-        if (tcg_check_temp_count()) {
-            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
-                    dc->pc);
-        }
-
-        if (!db->is_jmp && (tcg_op_buf_full() || singlestep ||
-                            db->num_insns >= max_insns)) {
-            db->is_jmp = DJ_TOO_MANY;
-        }
-    } while (!db->is_jmp);
-
-    if (db->is_jmp != DJ_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(cpu_env);
+    if (db->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
@@ -12251,6 +12177,95 @@ 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)
+{
+    CPUARMState *env = cpu->env_ptr;
+    ARMCPU *arm_cpu = arm_env_get_cpu(env);
+    DisasContext dc1, *dc = &dc1;
+    DisasContextBase *db = &dc->base;
+    int max_insns;
+    CPUBreakpoint *bp;
+
+    /* 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(db, arm_cpu, tb);
+        return;
+    }
+
+    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;
+    arm_trblock_init_disas_context(db, cpu);
+
+
+    arm_trblock_init_globals(db, 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, cpu_env);
+
+    tcg_clear_temp_count();
+    arm_trblock_tb_start(db, cpu);
+
+    do {
+        db->num_insns++;
+        arm_trblock_insn_start(db, cpu);
+
+        bp = NULL;
+        do {
+            bp = cpu_breakpoint_get(cpu, db->pc_next, bp);
+            if (unlikely(bp)) {
+                BreakpointCheckType bp_check = arm_trblock_breakpoint_check(
+                    db, cpu, bp);
+                if (bp_check == 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.
+                     */
+                    break;
+                } else {
+                    goto done_generating;
+                }
+            }
+        } while (bp != NULL);
+
+        if (db->num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start(cpu_env);
+        }
+
+        db->pc_next = arm_trblock_disas_insn(db, cpu);
+
+        if (tcg_check_temp_count()) {
+            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
+                    dc->pc);
+        }
+
+        if (!db->is_jmp && (tcg_op_buf_full() || singlestep ||
+                            db->num_insns >= max_insns)) {
+            db->is_jmp = DJ_TOO_MANY;
+        }
+    } while (!db->is_jmp);
+
+    arm_trblock_tb_stop(db, cpu);
+
+    if (tb->cflags & CF_LAST_IO) {
+        gen_io_end(cpu_env);
     }
 
 done_generating:

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

* [Qemu-devel] [PATCH v9 25/26] target: [tcg, arm] Port to disas_flags
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (22 preceding siblings ...)
  2017-06-25 10:20 ` [Qemu-devel] [PATCH v9 24/26] target: [tcg,arm] Port to tb_stop Lluís Vilanova
@ 2017-06-25 10:24 ` Lluís Vilanova
  2017-06-25 10:28 ` [Qemu-devel] [PATCH v9 26/26] target: [tcg, arm] Port to generic translation framework Lluís Vilanova
                   ` (2 subsequent siblings)
  26 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25 10:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |   10 +++++++++-
 target/arm/translate.c     |   10 +++++++++-
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index b14e96cd58..97e8bda230 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11389,6 +11389,13 @@ static void aarch64_trblock_tb_stop(DisasContextBase *db, CPUState *cpu)
     }
 }
 
+static int aarch64_trblock_disas_flags(const DisasContextBase *db)
+{
+    DisasContext *dc = container_of(db, DisasContext, base);
+
+    return 4 | (bswap_code(dc->sctlr_b) ? 2 : 0);
+}
+
 void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
                                TranslationBlock *tb)
 {
@@ -11475,11 +11482,12 @@ done_generating:
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
         qemu_log_in_addr_range(db->pc_first)) {
+        int disas_flags = aarch64_trblock_disas_flags(db);
         qemu_log_lock();
         qemu_log("----------------\n");
         qemu_log("IN: %s\n", lookup_symbol(db->pc_first));
         log_target_disas(cs, db->pc_first, dc->pc - db->pc_first,
-                         4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
+                         disas_flags);
         qemu_log("\n");
         qemu_log_unlock();
     }
diff --git a/target/arm/translate.c b/target/arm/translate.c
index db31611258..d87328602a 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -12179,6 +12179,13 @@ static void arm_trblock_tb_stop(DisasContextBase *db, CPUState *cpu)
     }
 }
 
+static int arm_trblock_disas_flags(const DisasContextBase *db)
+{
+    DisasContext *dc = container_of(db, DisasContext, base);
+
+    return dc->thumb | (dc->sctlr_b << 1);
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
@@ -12274,11 +12281,12 @@ done_generating:
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
         qemu_log_in_addr_range(db->pc_first)) {
+        int disas_flags = arm_trblock_disas_flags(db);
         qemu_log_lock();
         qemu_log("----------------\n");
         qemu_log("IN: %s\n", lookup_symbol(db->pc_first));
         log_target_disas(cpu, db->pc_first, dc->pc - db->pc_first,
-                         dc->thumb | (dc->sctlr_b << 1));
+                         disas_flags);
         qemu_log("\n");
         qemu_log_unlock();
     }

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

* [Qemu-devel] [PATCH v9 26/26] target: [tcg, arm] Port to generic translation framework
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (23 preceding siblings ...)
  2017-06-25 10:24 ` [Qemu-devel] [PATCH v9 25/26] target: [tcg, arm] Port to disas_flags Lluís Vilanova
@ 2017-06-25 10:28 ` Lluís Vilanova
  2017-06-27  3:47   ` Richard Henderson
  2017-06-26 11:34 ` [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic " Alex Bennée
  2017-06-27  3:00 ` Eric Blake
  26 siblings, 1 reply; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-25 10:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: 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 |  110 ++++++-------------------------------------
 target/arm/translate.c     |  112 +++++++-------------------------------------
 target/arm/translate.h     |    6 +-
 3 files changed, 36 insertions(+), 192 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 97e8bda230..59c5d58dd1 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11387,6 +11387,9 @@ static void aarch64_trblock_tb_stop(DisasContextBase *db, CPUState *cpu)
             break;
         }
     }
+
+    /* Functions above can change dc->pc, so re-align db->pc_next */
+    db->pc_next = dc->pc;
 }
 
 static int aarch64_trblock_disas_flags(const DisasContextBase *db)
@@ -11396,102 +11399,17 @@ static int aarch64_trblock_disas_flags(const DisasContextBase *db)
     return 4 | (bswap_code(dc->sctlr_b) ? 2 : 0);
 }
 
-void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
+static TranslatorOps aarch64_translator_ops = {
+    .init_disas_context = aarch64_trblock_init_disas_context,
+    .insn_start = aarch64_trblock_insn_start,
+    .breakpoint_check = aarch64_trblock_breakpoint_check,
+    .disas_insn = aarch64_trblock_disas_insn,
+    .tb_stop = aarch64_trblock_tb_stop,
+    .disas_flags = aarch64_trblock_disas_flags,
+};
+
+void gen_intermediate_code_a64(DisasContextBase *db, CPUState *cpu,
                                TranslationBlock *tb)
 {
-    CPUState *cs = CPU(cpu);
-    DisasContext *dc = container_of(db, DisasContext, base);
-    int max_insns;
-    CPUBreakpoint *bp;
-
-    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 = cs->singlestep_enabled;
-    aarch64_trblock_init_disas_context(db, cs);
-
-    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, cpu_env);
-
-    tcg_clear_temp_count();
-
-    do {
-        db->num_insns++;
-        aarch64_trblock_insn_start(db, cs);
-
-        bp = NULL;
-        do {
-            bp = cpu_breakpoint_get(cs, db->pc_next, bp);
-            if (unlikely(bp)) {
-                BreakpointCheckType bp_check =
-                    aarch64_trblock_breakpoint_check(db, cs, bp);
-                if (bp_check == 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.
-                     */
-                    break;
-                } else {
-                    goto done_generating;
-                }
-            }
-        } while (bp != NULL);
-
-        if (db->num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start(cpu_env);
-        }
-
-        db->pc_next = aarch64_trblock_disas_insn(db, cs);
-
-        if (tcg_check_temp_count()) {
-            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
-                    dc->pc);
-        }
-
-        if (!db->is_jmp && (tcg_op_buf_full() || cs->singlestep_enabled ||
-                            singlestep || db->num_insns >= max_insns)) {
-            db->is_jmp = DJ_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 (!db->is_jmp);
-
-    aarch64_trblock_tb_stop(db, cs);
-
-    if (tb->cflags & CF_LAST_IO) {
-        gen_io_end(cpu_env);
-    }
-
-done_generating:
-    gen_tb_end(tb, db->num_insns);
-
-#ifdef DEBUG_DISAS
-    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
-        qemu_log_in_addr_range(db->pc_first)) {
-        int disas_flags = aarch64_trblock_disas_flags(db);
-        qemu_log_lock();
-        qemu_log("----------------\n");
-        qemu_log("IN: %s\n", lookup_symbol(db->pc_first));
-        log_target_disas(cs, db->pc_first, dc->pc - db->pc_first,
-                         disas_flags);
-        qemu_log("\n");
-        qemu_log_unlock();
-    }
-#endif
-    tb->size = dc->pc - db->pc_first;
-    tb->icount = db->num_insns;
+    translate_block(&aarch64_translator_ops, db, cpu, &cpu_env, tb);
 }
diff --git a/target/arm/translate.c b/target/arm/translate.c
index d87328602a..d9a7d870cb 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -12177,6 +12177,9 @@ static void arm_trblock_tb_stop(DisasContextBase *db, CPUState *cpu)
             gen_goto_tb(dc, 1, dc->pc);
         }
     }
+
+    /* Functions above can change dc->pc, so re-align db->pc_next */
+    db->pc_next = dc->pc;
 }
 
 static int arm_trblock_disas_flags(const DisasContextBase *db)
@@ -12186,15 +12189,24 @@ static int arm_trblock_disas_flags(const DisasContextBase *db)
     return dc->thumb | (dc->sctlr_b << 1);
 }
 
+static 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,
+    .disas_insn = arm_trblock_disas_insn,
+    .tb_stop = arm_trblock_tb_stop,
+    .disas_flags = arm_trblock_disas_flags,
+};
+
+#include "qemu/error-report.h"
+
 /* generate intermediate code for basic block 'tb'.  */
 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;
     DisasContextBase *db = &dc->base;
-    int max_insns;
-    CPUBreakpoint *bp;
 
     /* generate intermediate code */
 
@@ -12202,97 +12214,11 @@ 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(db, arm_cpu, tb);
+        gen_intermediate_code_a64(db, cpu, tb);
         return;
+    } else {
+        translate_block(&arm_translator_ops, db, cpu, &cpu_env, tb);
     }
-
-    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;
-    arm_trblock_init_disas_context(db, cpu);
-
-
-    arm_trblock_init_globals(db, 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, cpu_env);
-
-    tcg_clear_temp_count();
-    arm_trblock_tb_start(db, cpu);
-
-    do {
-        db->num_insns++;
-        arm_trblock_insn_start(db, cpu);
-
-        bp = NULL;
-        do {
-            bp = cpu_breakpoint_get(cpu, db->pc_next, bp);
-            if (unlikely(bp)) {
-                BreakpointCheckType bp_check = arm_trblock_breakpoint_check(
-                    db, cpu, bp);
-                if (bp_check == 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.
-                     */
-                    break;
-                } else {
-                    goto done_generating;
-                }
-            }
-        } while (bp != NULL);
-
-        if (db->num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start(cpu_env);
-        }
-
-        db->pc_next = arm_trblock_disas_insn(db, cpu);
-
-        if (tcg_check_temp_count()) {
-            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
-                    dc->pc);
-        }
-
-        if (!db->is_jmp && (tcg_op_buf_full() || singlestep ||
-                            db->num_insns >= max_insns)) {
-            db->is_jmp = DJ_TOO_MANY;
-        }
-    } while (!db->is_jmp);
-
-    arm_trblock_tb_stop(db, cpu);
-
-    if (tb->cflags & CF_LAST_IO) {
-        gen_io_end(cpu_env);
-    }
-
-done_generating:
-    gen_tb_end(tb, db->num_insns);
-
-#ifdef DEBUG_DISAS
-    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
-        qemu_log_in_addr_range(db->pc_first)) {
-        int disas_flags = arm_trblock_disas_flags(db);
-        qemu_log_lock();
-        qemu_log("----------------\n");
-        qemu_log("IN: %s\n", lookup_symbol(db->pc_first));
-        log_target_disas(cpu, db->pc_first, dc->pc - db->pc_first,
-                         disas_flags);
-        qemu_log("\n");
-        qemu_log_unlock();
-    }
-#endif
-    tb->size = dc->pc - db->pc_first;
-    tb->icount = db->num_insns;
 }
 
 static const char *cpu_mode_names[16] = {
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 43e8b555e3..0e60d4d771 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -152,7 +152,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(DisasContextBase *db, ARMCPU *cpu,
+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,
@@ -162,8 +162,8 @@ static inline void a64_translate_init(void)
 {
 }
 
-static inline void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
-                                             TranslationBlock *tb)
+static inline void gen_intermediate_code_a64(
+    DisasContextBase *db, CPUState *cpu, TranslationBlock *tb)
 {
 }
 

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

* [Qemu-devel] [PATCH] fixup! Pass generic CPUState to gen_intermediate_code()
  2017-06-25  8:47 ` [Qemu-devel] [PATCH v9 01/26] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
@ 2017-06-26 10:04   ` Alex Bennée
  2017-06-26 12:37     ` Lluís Vilanova
  2017-06-26 17:50   ` [Qemu-devel] [PATCH v9 01/26] " Emilio G. Cota
  1 sibling, 1 reply; 57+ messages in thread
From: Alex Bennée @ 2017-06-26 10:04 UTC (permalink / raw)
  To: vilanova
  Cc: qemu-devel, Alex Bennée, Richard Henderson, Chris Wulff,
	Marek Vasut, Stafford Horne

---
 target/hppa/translate.c     | 5 ++---
 target/nios2/translate.c    | 5 ++---
 target/openrisc/translate.c | 3 +--
 3 files changed, 5 insertions(+), 8 deletions(-)

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/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 aaac359d5b..4a28c96e53 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -1520,9 +1520,8 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
 
 void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
 {
-    OpenRISCState *env = cpu->env_ptr;
+    CPUOpenRISCState *env = cpu->env_ptr;
     OpenRISCCPU *or_cpu = openrisc_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
     struct DisasContext ctx, *dc = &ctx;
     uint32_t pc_start;
     uint32_t next_page_start;
-- 
2.13.0

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

* Re: [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-25  8:59 ` [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework Lluís Vilanova
@ 2017-06-26 10:14   ` Alex Bennée
  2017-06-26 12:50     ` Lluís Vilanova
  2017-06-27  2:47     ` Richard Henderson
  2017-06-26 17:57   ` Emilio G. Cota
                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 57+ messages in thread
From: Alex Bennée @ 2017-06-26 10:14 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Richard Henderson, Peter Crosthwaite, Paolo Bonzini


Lluís Vilanova <vilanova@ac.upc.edu> writes:

> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
>  Makefile.target                |    1
>  include/exec/gen-icount.h      |    2
>  include/exec/translate-block.h |  125 +++++++++++++++++++++++++++
>  include/qom/cpu.h              |   22 +++++
>  translate-block.c              |  185 ++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 334 insertions(+), 1 deletion(-)
>  create mode 100644 include/exec/translate-block.h
>  create mode 100644 translate-block.c
>
> diff --git a/Makefile.target b/Makefile.target
> index ce8dfe44a8..253c6e7999 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -90,6 +90,7 @@ all: $(PROGS) stap
>  # cpu emulator library
>  obj-y = exec.o translate-all.o cpu-exec.o
>  obj-y += translate-common.o
> +obj-y += translate-block.o

This clases with the changes now in master to move tcg functions into
accel/tcg/

>  obj-y += cpu-exec-common.o
>  obj-y += tcg/tcg.o tcg/tcg-op.o tcg/optimize.o
>  obj-$(CONFIG_TCG_INTERPRETER) += tci.o
> diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
> index 9b26c7da5f..f4ad61014b 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, TCGv_env cpu_env)
>      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/translate-block.h b/include/exec/translate-block.h
> new file mode 100644
> index 0000000000..d14d23f2cb
> --- /dev/null
> +++ b/include/exec/translate-block.h
> @@ -0,0 +1,125 @@
> +/*
> + * 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__TRANSLATE_BLOCK_H
> +#define EXEC__TRANSLATE_BLOCK_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:
> + * @DJ_NEXT: Next instruction in program order.
> + * @DJ_TOO_MANY: Too many instructions translated.
> + * @DJ_TARGET: Start of target-specific conditions.
> + *
> + * What instruction to disassemble next.
> + */
> +typedef enum DisasJumpType {
> +    DJ_NEXT,
> +    DJ_TOO_MANY,
> +    DJ_TARGET,
> +} 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.
> + *
> + * All operations but disas_insn() are optional, and ignored when not set.
> + * A missing breakpoint_check() will ignore breakpoints. A missing disas_flags()
> + * will pass no flags.
> + */
> +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 (*disas_insn)(DisasContextBase *db, CPUState *cpu);
> +    void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
> +    int (*disas_flags)(const DisasContextBase *db);
> +} TranslatorOps;
> +
> +/**
> + * translate_block:
> + * @ops: Target-specific operations.
> + * @db:
> + * @cpu:
> + * @tb:
> + *
> + * Generic translator loop.
> + */
> +void translate_block(const TranslatorOps *ops, DisasContextBase *db,
> +                     CPUState *cpu, TCGv_env *tcg_cpu, TranslationBlock *tb);
> +
> +#endif  /* EXEC__TRANSLATE_BLOCK_H */
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index 89ddb686fb..d46e8df756 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -982,6 +982,28 @@ static inline bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask)
>      return false;
>  }
>
> +/* Get first breakpoint matching a PC */
> +static inline CPUBreakpoint *cpu_breakpoint_get(CPUState *cpu, vaddr pc,
> +                                                CPUBreakpoint *bp)
> +{
> +    if (likely(bp == NULL)) {
> +        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
> +            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
> +                if (bp->pc == pc) {
> +                    return bp;
> +                }
> +            }
> +        }
> +    } else {
> +        QTAILQ_FOREACH_CONTINUE(bp, entry) {
> +            if (bp->pc == pc) {
> +                return bp;
> +            }
> +        }
> +    }
> +    return NULL;
> +}
> +
>  int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
>                            int flags, CPUWatchpoint **watchpoint);
>  int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
> diff --git a/translate-block.c b/translate-block.c
> new file mode 100644
> index 0000000000..1aac80560e
> --- /dev/null
> +++ b/translate-block.c
> @@ -0,0 +1,185 @@
> +/*
> + * 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/translate-block.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, TCGv_env *tcg_cpu, TranslationBlock *tb)
> +{
> +    int max_insns;
> +
> +    /* Sanity-check ops */
> +    if (ops->disas_insn == NULL) {
> +        error_report("Missing ops->disas_insn");
> +        abort();
> +    }
> +
> +    /* Initialize DisasContext */
> +    db->tb = tb;
> +    db->pc_first = tb->pc;
> +    db->pc_next = db->pc_first;
> +    db->is_jmp = DJ_NEXT;
> +    db->num_insns = 0;
> +    db->singlestep_enabled = cpu->singlestep_enabled;
> +    if (ops->init_disas_context) {
> +        ops->init_disas_context(db, cpu);
> +    }
> +
> +    /* Initialize globals */
> +    if (ops->init_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, *tcg_cpu);
> +    if (ops->tb_start) {
> +        ops->tb_start(db, cpu);
> +    }
> +
> +    while (true) {
> +        CPUBreakpoint *bp;
> +
> +        db->num_insns++;
> +        if (ops->insn_start) {
> +            ops->insn_start(db, cpu);
> +        }
> +
> +        /* Early exit before breakpoint checks */
> +        if (unlikely(db->is_jmp != DJ_NEXT)) {
> +            break;
> +        }
> +
> +        /* Pass breakpoint hits to target for further processing */
> +        bp = NULL;
> +        do {
> +            bp = cpu_breakpoint_get(cpu, db->pc_next, bp);
> +            if (unlikely(bp) && ops->breakpoint_check) {
> +                BreakpointCheckType bp_check = ops->breakpoint_check(
> +                    db, cpu, bp);
> +                if (bp_check == 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.
> +                     */
> +                    break;
> +                } else if (bp_check == BC_HIT_TB) {
> +                    goto done_generating;
> +                } else {
> +                    error_report("Unexpected BreakpointCheckType %d", bp_check);
> +                    abort();
> +                }
> +            }
> +        } while (bp != NULL);
> +
> +        /* Accept I/O on last instruction */
> +        if (db->num_insns == max_insns && (db->tb->cflags & CF_LAST_IO)) {
> +            gen_io_start(*tcg_cpu);
> +        }
> +
> +        /* Disassemble one instruction */
> +        db->pc_next = ops->disas_insn(db, cpu);
> +
> +        /**************************************************/
> +        /* Conditions to stop translation                 */
> +        /**************************************************/
> +
> +        /* Target-specific conditions set by disassembly */
> +        if (db->is_jmp != DJ_NEXT) {
> +            break;
> +        }
> +
> +        /* Too many instructions */
> +        if (tcg_op_buf_full() || db->num_insns >= max_insns) {
> +            db->is_jmp = DJ_TOO_MANY;
> +            break;
> +        }
> +
> +        /*
> +         * Check if next instruction is on next page, which can cause an
> +         * exception.
> +         *
> +         * NOTE: Target-specific code must check a single instruction does not
> +         *       cross page boundaries; the first in the TB is always allowed to
> +         *       cross pages (never goes through this check).
> +         */
> +        if ((db->pc_first & TARGET_PAGE_MASK)
> +            != (db->pc_next & TARGET_PAGE_MASK)) {
> +            db->is_jmp = DJ_TOO_MANY;
> +            break;
> +        }

How does the first insn avoid this check? And if it does is that right?

I mean I understand you can construct weird multi-byte instructions
(especially on x86) that cross the boundary but even if it is the first
in a TB shouldn't it error if there are no contiguous pages?

Also isn't the page crossing issue different for SoftMMU and linux-user?

> +
> +        translate_block_tcg_check(db);
> +    }
> +
> +    if (ops->tb_stop) {
> +        ops->tb_stop(db, cpu);
> +    }
> +
> +    if (db->tb->cflags & CF_LAST_IO) {
> +        gen_io_end(*tcg_cpu);
> +    }
> +
> +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)) {
> +        int flags;
> +        if (ops->disas_flags) {
> +            flags = ops->disas_flags(db);
> +        } else {
> +            flags = 0;
> +        }
> +        qemu_log_lock();
> +        qemu_log("----------------\n");
> +        qemu_log("IN: %s\n", lookup_symbol(db->pc_first));
> +        log_target_disas(cpu, db->pc_first, db->pc_next - db->pc_first, flags);
> +        qemu_log("\n");
> +        qemu_log_unlock();
> +    }
> +#endif
> +
> +    db->tb->size = db->pc_next - db->pc_first;
> +    db->tb->icount = db->num_insns;
> +}


--
Alex Bennée

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

* [Qemu-devel] [PATCH] maybe fixup! target: [tcg] Redefine DISAS_* onto the generic translation framework (DJ_*)
  2017-06-25  9:03 ` [Qemu-devel] [PATCH v9 05/26] target: [tcg] Redefine DISAS_* onto the generic translation framework (DJ_*) Lluís Vilanova
@ 2017-06-26 11:28   ` Alex Bennée
  2017-06-26 18:05   ` [Qemu-devel] [PATCH v9 05/26] " Emilio G. Cota
  1 sibling, 0 replies; 57+ messages in thread
From: Alex Bennée @ 2017-06-26 11:28 UTC (permalink / raw)
  To: vilanova; +Cc: qemu-devel, Alex Bennée, Chris Wulff, Marek Vasut

Arguably these should be applied to nios2 before these changes.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 target/nios2/cpu.h       | 2 --
 target/nios2/op_helper.c | 1 +
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index 13931f3f0b..b6a97c131e 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -259,8 +259,6 @@ static inline int cpu_interrupts_enabled(CPUNios2State *env)
 }
 
 #include "exec/cpu-all.h"
-#include "exec/exec-all.h"
-
 static inline void cpu_get_tb_cpu_state(CPUNios2State *env, target_ulong *pc,
                                         target_ulong *cs_base, uint32_t *flags)
 {
diff --git a/target/nios2/op_helper.c b/target/nios2/op_helper.c
index efb1c489c9..04c16e8701 100644
--- a/target/nios2/op_helper.c
+++ b/target/nios2/op_helper.c
@@ -21,6 +21,7 @@
 #include "cpu.h"
 #include "exec/helper-proto.h"
 #include "exec/cpu_ldst.h"
+#include "exec/exec-all.h"
 #include "qemu/main-loop.h"
 
 #if !defined(CONFIG_USER_ONLY)
-- 
2.13.0

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

* Re: [Qemu-devel] [PATCH v9 21/26] target: [tcg, arm] Port to insn_start
  2017-06-25 10:08 ` [Qemu-devel] [PATCH v9 21/26] target: [tcg, arm] Port to insn_start Lluís Vilanova
@ 2017-06-26 11:31   ` Alex Bennée
  2017-06-27  3:33   ` Richard Henderson
  1 sibling, 0 replies; 57+ messages in thread
From: Alex Bennée @ 2017-06-26 11:31 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Richard Henderson, Peter Crosthwaite, Paolo Bonzini,
	Peter Maydell, open list:ARM


Lluís Vilanova <vilanova@ac.upc.edu> writes:

> 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 +++++++++--
>  target/arm/translate.c     |   36 +++++++++++++++++++++---------------
>  2 files changed, 30 insertions(+), 17 deletions(-)
>
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 1959f27377..bfc2cdabb5 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -11259,6 +11259,14 @@ static void aarch64_trblock_init_disas_context(DisasContextBase *db,
>      init_tmp_a64_array(dc);
>  }
>
> +static void aarch64_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
> +{
> +    DisasContext *dc = container_of(db, DisasContext, base);
> +
> +    dc->insn_start_idx = tcg_op_buf_count();
> +    tcg_gen_insn_start(dc->pc, 0, 0);
> +}
> +
>  void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
>                                 TranslationBlock *tb)
>  {
> @@ -11291,8 +11299,7 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
>
>      do {
>          db->num_insns++;
> -        dc->insn_start_idx = tcg_op_buf_count();
> -        tcg_gen_insn_start(dc->pc, 0, 0);
> +        aarch64_trblock_insn_start(db, cs);
>
>          if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
>              CPUBreakpoint *bp;
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index ae3f772446..18b0e8fbb6 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -11934,6 +11934,26 @@ static void arm_trblock_tb_start(DisasContextBase *db, CPUState *cpu)
>      }
>  }
>
> +static void arm_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
> +{
> +    DisasContext *dc = container_of(db, 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->is_jmp = DJ_EXC;

This fails to build.

> +    }
> +#endif
> +}
> +
>  /* generate intermediate code for basic block 'tb'.  */
>  void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
>  {
> @@ -11981,21 +12001,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
>
>      do {
>          db->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);
> -
> -#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->is_jmp = DJ_EXC;
> -            break;
> -        }
> -#endif
> +        arm_trblock_insn_start(db, cpu);
>
>          if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
>              CPUBreakpoint *bp;


--
Alex Bennée

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

* Re: [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (24 preceding siblings ...)
  2017-06-25 10:28 ` [Qemu-devel] [PATCH v9 26/26] target: [tcg, arm] Port to generic translation framework Lluís Vilanova
@ 2017-06-26 11:34 ` Alex Bennée
  2017-06-26 13:02   ` Lluís Vilanova
  2017-06-27  3:00 ` Eric Blake
  26 siblings, 1 reply; 57+ messages in thread
From: Alex Bennée @ 2017-06-26 11:34 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Richard Henderson, Peter Crosthwaite, Paolo Bonzini


Lluís Vilanova <vilanova@ac.upc.edu> writes:

> 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.

I started going through this but I found a number of problems. There are
some merge failures against master due to recent changes (moving tcg
into accel, the UPDATE/JUMP lockup fixes in ARM). I also ran into a
number of compile failures which I've sent some fixup patches to.

However the series does need to complete a clean compile on all arches
(SoftMMU & linux-user) even though the porting to the new framework is
partial.

FWIW you can find my tree with fixups and other attempts to fixup
compilation @ :

  https://github.com/stsquad/qemu/tree/review/generic-tcg-v9

>
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
>
> 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 (26):
>       Pass generic CPUState to gen_intermediate_code()
>       queue: Add macro for incremental traversal
>       cpu-exec: Avoid global variables in icount-related functions
>       target: [tcg] Add generic translation framework
>       target: [tcg] Redefine DISAS_* onto the generic translation framework (DJ_*)
>       target: [tcg,i386] Port to DisasContextBase
>       target: [tcg,i386] Refactor init_disas_context
>       target: [tcg,i386] Refactor init_globals
>       target: [tcg,i386] Refactor insn_start
>       target: [tcg,i386] Refactor breakpoint_check
>       target: [tcg,i386] Refactor disas_insn
>       target: [tcg,i386] Refactor tb_stop
>       target: [tcg,i386] Refactor disas_flags
>       target: [tcg,i386] Replace DISAS_* with DJ_*
>       target: [tcg,i386] Port to generic translation framework
>       target: [tcg,arm] Replace DISAS_* with DJ_*
>       target: [tcg,arm] Port to DisasContextBase
>       target: [tcg,arm] Port to init_disas_context
>       target: [tcg,arm] Port to init_globals
>       target: [tcg,arm] Port to tb_start
>       target: [tcg,arm] Port to insn_start
>       target: [tcg,arm] Port to breakpoint_check
>       target: [tcg,arm] Port to disas_insn
>       target: [tcg,arm] Port to tb_stop
>       target: [tcg,arm] Port to disas_flags
>       target: [tcg,arm] Port to generic translation framework
>
>
>  Makefile.target                |    1
>  include/exec/exec-all.h        |   13 +
>  include/exec/gen-icount.h      |    8 -
>  include/exec/translate-block.h |  125 ++++++++++
>  include/qemu/queue.h           |   12 +
>  include/qom/cpu.h              |   22 ++
>  target/alpha/translate.c       |   25 +-
>  target/arm/translate-a64.c     |  312 ++++++++++++-------------
>  target/arm/translate.c         |  503 ++++++++++++++++++++++------------------
>  target/arm/translate.h         |   38 ++-
>  target/cris/translate.c        |   26 +-
>  target/hppa/translate.c        |    6
>  target/i386/translate.c        |  353 +++++++++++++++-------------
>  target/lm32/translate.c        |   36 +--
>  target/m68k/translate.c        |   24 +-
>  target/microblaze/translate.c  |   28 +-
>  target/mips/translate.c        |   41 ++-
>  target/moxie/translate.c       |   16 +
>  target/nios2/translate.c       |    6
>  target/openrisc/translate.c    |   25 +-
>  target/ppc/translate.c         |   21 +-
>  target/ppc/translate_init.c    |   32 +--
>  target/s390x/translate.c       |   22 +-
>  target/sh4/translate.c         |   21 +-
>  target/sparc/translate.c       |   17 +
>  target/tilegx/translate.c      |    9 -
>  target/tricore/translate.c     |   11 -
>  target/unicore32/translate.c   |   26 +-
>  target/xtensa/translate.c      |   39 ++-
>  translate-all.c                |    2
>  translate-block.c              |  185 +++++++++++++++
>  31 files changed, 1212 insertions(+), 793 deletions(-)
>  create mode 100644 include/exec/translate-block.h
>  create mode 100644 translate-block.c
>
>
> 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>


--
Alex Bennée

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

* Re: [Qemu-devel] [PATCH] fixup! Pass generic CPUState to gen_intermediate_code()
  2017-06-26 10:04   ` [Qemu-devel] [PATCH] fixup! " Alex Bennée
@ 2017-06-26 12:37     ` Lluís Vilanova
  0 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-26 12:37 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Marek Vasut, Chris Wulff, qemu-devel, Stafford Horne, Richard Henderson

Alex Bennée writes:

> ---
>  target/hppa/translate.c     | 5 ++---
>  target/nios2/translate.c    | 5 ++---
>  target/openrisc/translate.c | 3 +--
>  3 files changed, 5 insertions(+), 8 deletions(-)

I rebased the patches and forgot to test the compilation of other
architectures. Sorry about that.

Thanks,
  Lluis



> 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/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 aaac359d5b..4a28c96e53 100644
> --- a/target/openrisc/translate.c
> +++ b/target/openrisc/translate.c
> @@ -1520,9 +1520,8 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
 
>  void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
>  {
> -    OpenRISCState *env = cpu->env_ptr;
> +    CPUOpenRISCState *env = cpu->env_ptr;
>      OpenRISCCPU *or_cpu = openrisc_env_get_cpu(env);
> -    CPUState *cs = CPU(cpu);
>      struct DisasContext ctx, *dc = &ctx;
>      uint32_t pc_start;
>      uint32_t next_page_start;
> -- 
> 2.13.0

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

* Re: [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-26 10:14   ` Alex Bennée
@ 2017-06-26 12:50     ` Lluís Vilanova
  2017-06-26 18:21       ` Peter Maydell
  2017-06-27  2:47     ` Richard Henderson
  1 sibling, 1 reply; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-26 12:50 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, Peter Crosthwaite, qemu-devel, Richard Henderson

Alex Bennée writes:

> Lluís Vilanova <vilanova@ac.upc.edu> writes:

>> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
>> ---
>> Makefile.target                |    1
>> include/exec/gen-icount.h      |    2
>> include/exec/translate-block.h |  125 +++++++++++++++++++++++++++
>> include/qom/cpu.h              |   22 +++++
>> translate-block.c              |  185 ++++++++++++++++++++++++++++++++++++++++
>> 5 files changed, 334 insertions(+), 1 deletion(-)
>> create mode 100644 include/exec/translate-block.h
>> create mode 100644 translate-block.c
>> 
>> diff --git a/Makefile.target b/Makefile.target
>> index ce8dfe44a8..253c6e7999 100644
>> --- a/Makefile.target
>> +++ b/Makefile.target
>> @@ -90,6 +90,7 @@ all: $(PROGS) stap
>> # cpu emulator library
>> obj-y = exec.o translate-all.o cpu-exec.o
>> obj-y += translate-common.o
>> +obj-y += translate-block.o

> This clases with the changes now in master to move tcg functions into
> accel/tcg/

I see. I'll rebase again and move the new code there.


>> obj-y += cpu-exec-common.o
>> obj-y += tcg/tcg.o tcg/tcg-op.o tcg/optimize.o
>> obj-$(CONFIG_TCG_INTERPRETER) += tci.o
>> diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
>> index 9b26c7da5f..f4ad61014b 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, TCGv_env cpu_env)
>> 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/translate-block.h b/include/exec/translate-block.h
>> new file mode 100644
>> index 0000000000..d14d23f2cb
>> --- /dev/null
>> +++ b/include/exec/translate-block.h
>> @@ -0,0 +1,125 @@
>> +/*
>> + * 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__TRANSLATE_BLOCK_H
>> +#define EXEC__TRANSLATE_BLOCK_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:
>> + * @DJ_NEXT: Next instruction in program order.
>> + * @DJ_TOO_MANY: Too many instructions translated.
>> + * @DJ_TARGET: Start of target-specific conditions.
>> + *
>> + * What instruction to disassemble next.
>> + */
>> +typedef enum DisasJumpType {
>> +    DJ_NEXT,
>> +    DJ_TOO_MANY,
>> +    DJ_TARGET,
>> +} 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.
>> + *
>> + * All operations but disas_insn() are optional, and ignored when not set.
>> + * A missing breakpoint_check() will ignore breakpoints. A missing disas_flags()
>> + * will pass no flags.
>> + */
>> +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 (*disas_insn)(DisasContextBase *db, CPUState *cpu);
>> +    void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
>> +    int (*disas_flags)(const DisasContextBase *db);
>> +} TranslatorOps;
>> +
>> +/**
>> + * translate_block:
>> + * @ops: Target-specific operations.
>> + * @db:
>> + * @cpu:
>> + * @tb:
>> + *
>> + * Generic translator loop.
>> + */
>> +void translate_block(const TranslatorOps *ops, DisasContextBase *db,
>> +                     CPUState *cpu, TCGv_env *tcg_cpu, TranslationBlock *tb);
>> +
>> +#endif  /* EXEC__TRANSLATE_BLOCK_H */
>> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
>> index 89ddb686fb..d46e8df756 100644
>> --- a/include/qom/cpu.h
>> +++ b/include/qom/cpu.h
>> @@ -982,6 +982,28 @@ static inline bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask)
>> return false;
>> }
>> 
>> +/* Get first breakpoint matching a PC */
>> +static inline CPUBreakpoint *cpu_breakpoint_get(CPUState *cpu, vaddr pc,
>> +                                                CPUBreakpoint *bp)
>> +{
>> +    if (likely(bp == NULL)) {
>> +        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
>> +            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
>> +                if (bp->pc == pc) {
>> +                    return bp;
>> +                }
>> +            }
>> +        }
>> +    } else {
>> +        QTAILQ_FOREACH_CONTINUE(bp, entry) {
>> +            if (bp->pc == pc) {
>> +                return bp;
>> +            }
>> +        }
>> +    }
>> +    return NULL;
>> +}
>> +
>> int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
>> int flags, CPUWatchpoint **watchpoint);
>> int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
>> diff --git a/translate-block.c b/translate-block.c
>> new file mode 100644
>> index 0000000000..1aac80560e
>> --- /dev/null
>> +++ b/translate-block.c
>> @@ -0,0 +1,185 @@
>> +/*
>> + * 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/translate-block.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, TCGv_env *tcg_cpu, TranslationBlock *tb)
>> +{
>> +    int max_insns;
>> +
>> +    /* Sanity-check ops */
>> +    if (ops->disas_insn == NULL) {
>> +        error_report("Missing ops->disas_insn");
>> +        abort();
>> +    }
>> +
>> +    /* Initialize DisasContext */
>> +    db->tb = tb;
>> +    db->pc_first = tb->pc;
>> +    db->pc_next = db->pc_first;
>> +    db->is_jmp = DJ_NEXT;
>> +    db->num_insns = 0;
>> +    db->singlestep_enabled = cpu->singlestep_enabled;
>> +    if (ops->init_disas_context) {
>> +        ops->init_disas_context(db, cpu);
>> +    }
>> +
>> +    /* Initialize globals */
>> +    if (ops->init_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, *tcg_cpu);
>> +    if (ops->tb_start) {
>> +        ops->tb_start(db, cpu);
>> +    }
>> +
>> +    while (true) {
>> +        CPUBreakpoint *bp;
>> +
>> +        db->num_insns++;
>> +        if (ops->insn_start) {
>> +            ops->insn_start(db, cpu);
>> +        }
>> +
>> +        /* Early exit before breakpoint checks */
>> +        if (unlikely(db->is_jmp != DJ_NEXT)) {
>> +            break;
>> +        }
>> +
>> +        /* Pass breakpoint hits to target for further processing */
>> +        bp = NULL;
>> +        do {
>> +            bp = cpu_breakpoint_get(cpu, db->pc_next, bp);
>> +            if (unlikely(bp) && ops->breakpoint_check) {
>> +                BreakpointCheckType bp_check = ops->breakpoint_check(
>> +                    db, cpu, bp);
>> +                if (bp_check == 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.
>> +                     */
>> +                    break;
>> +                } else if (bp_check == BC_HIT_TB) {
>> +                    goto done_generating;
>> +                } else {
>> +                    error_report("Unexpected BreakpointCheckType %d", bp_check);
>> +                    abort();
>> +                }
>> +            }
>> +        } while (bp != NULL);
>> +
>> +        /* Accept I/O on last instruction */
>> +        if (db->num_insns == max_insns && (db->tb->cflags & CF_LAST_IO)) {
>> +            gen_io_start(*tcg_cpu);
>> +        }
>> +
>> +        /* Disassemble one instruction */
>> +        db->pc_next = ops->disas_insn(db, cpu);
>> +
>> +        /**************************************************/
>> +        /* Conditions to stop translation                 */
>> +        /**************************************************/
>> +
>> +        /* Target-specific conditions set by disassembly */
>> +        if (db->is_jmp != DJ_NEXT) {
>> +            break;
>> +        }
>> +
>> +        /* Too many instructions */
>> +        if (tcg_op_buf_full() || db->num_insns >= max_insns) {
>> +            db->is_jmp = DJ_TOO_MANY;
>> +            break;
>> +        }
>> +
>> +        /*
>> +         * Check if next instruction is on next page, which can cause an
>> +         * exception.
>> +         *
>> +         * NOTE: Target-specific code must check a single instruction does not
>> +         *       cross page boundaries; the first in the TB is always allowed to
>> +         *       cross pages (never goes through this check).
>> +         */
>> +        if ((db->pc_first & TARGET_PAGE_MASK)
>> +            != (db->pc_next & TARGET_PAGE_MASK)) {
>> +            db->is_jmp = DJ_TOO_MANY;
>> +            break;
>> +        }

> How does the first insn avoid this check? And if it does is that right?

All translation loops I've seen put the page crossing check at the end of the
loop, when the first instruction has already been translated.


> I mean I understand you can construct weird multi-byte instructions
> (especially on x86) that cross the boundary but even if it is the first
> in a TB shouldn't it error if there are no contiguous pages?

Honestly, I've coded it in a way that reproduces the existing behavior, but have
not checked if it makes sense to change or try to simplify it.


> Also isn't the page crossing issue different for SoftMMU and linux-user?

Not that I've seen (at the level of the translation loop). Now I wonder if QEMU
w/ TCG has a bug that lets it successfully execute instructions that cross page
boundaries, one of them with invalid permissions (haven't checked).


What I can say is that this check is a very weak one (but common to all
targets), and that targets like i386 and arm need to refine it further in the
target-specific code. In fact, now I suspect all targets will need to refine it,
so it probably makes sense to simply drop this generic check and burden all
targets with handling it.


>> +
>> +        translate_block_tcg_check(db);
>> +    }
>> +
>> +    if (ops->tb_stop) {
>> +        ops->tb_stop(db, cpu);
>> +    }
>> +
>> +    if (db->tb->cflags & CF_LAST_IO) {
>> +        gen_io_end(*tcg_cpu);
>> +    }
>> +
>> +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)) {
>> +        int flags;
>> +        if (ops->disas_flags) {
>> +            flags = ops->disas_flags(db);
>> +        } else {
>> +            flags = 0;
>> +        }
>> +        qemu_log_lock();
>> +        qemu_log("----------------\n");
>> +        qemu_log("IN: %s\n", lookup_symbol(db->pc_first));
>> +        log_target_disas(cpu, db->pc_first, db->pc_next - db->pc_first, flags);
>> +        qemu_log("\n");
>> +        qemu_log_unlock();
>> +    }
>> +#endif
>> +
>> +    db->tb->size = db->pc_next - db->pc_first;
>> +    db->tb->icount = db->num_insns;
>> +}


Thanks,
  Lluis

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

* Re: [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework
  2017-06-26 11:34 ` [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic " Alex Bennée
@ 2017-06-26 13:02   ` Lluís Vilanova
  0 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-26 13:02 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Paolo Bonzini, Peter Crosthwaite, qemu-devel, Richard Henderson

Alex Bennée writes:

> Lluís Vilanova <vilanova@ac.upc.edu> writes:

>> 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.

> I started going through this but I found a number of problems. There are
> some merge failures against master due to recent changes (moving tcg
> into accel, the UPDATE/JUMP lockup fixes in ARM). I also ran into a
> number of compile failures which I've sent some fixup patches to.

> However the series does need to complete a clean compile on all arches
> (SoftMMU & linux-user) even though the porting to the new framework is
> partial.

> FWIW you can find my tree with fixups and other attempts to fixup
> compilation @ :

>   https://github.com/stsquad/qemu/tree/review/generic-tcg-v9

I've integrated them and I'm now compiling for all targets to make sure it
passes.

Thanks a lot,
  Lluis


>> 
>> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
>> ---
>> 
>> 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 (26):
>> Pass generic CPUState to gen_intermediate_code()
>> queue: Add macro for incremental traversal
>> cpu-exec: Avoid global variables in icount-related functions
>> target: [tcg] Add generic translation framework
>> target: [tcg] Redefine DISAS_* onto the generic translation framework (DJ_*)
>> target: [tcg,i386] Port to DisasContextBase
>> target: [tcg,i386] Refactor init_disas_context
>> target: [tcg,i386] Refactor init_globals
>> target: [tcg,i386] Refactor insn_start
>> target: [tcg,i386] Refactor breakpoint_check
>> target: [tcg,i386] Refactor disas_insn
>> target: [tcg,i386] Refactor tb_stop
>> target: [tcg,i386] Refactor disas_flags
>> target: [tcg,i386] Replace DISAS_* with DJ_*
>> target: [tcg,i386] Port to generic translation framework
>> target: [tcg,arm] Replace DISAS_* with DJ_*
>> target: [tcg,arm] Port to DisasContextBase
>> target: [tcg,arm] Port to init_disas_context
>> target: [tcg,arm] Port to init_globals
>> target: [tcg,arm] Port to tb_start
>> target: [tcg,arm] Port to insn_start
>> target: [tcg,arm] Port to breakpoint_check
>> target: [tcg,arm] Port to disas_insn
>> target: [tcg,arm] Port to tb_stop
>> target: [tcg,arm] Port to disas_flags
>> target: [tcg,arm] Port to generic translation framework
>> 
>> 
>> Makefile.target                |    1
>> include/exec/exec-all.h        |   13 +
>> include/exec/gen-icount.h      |    8 -
>> include/exec/translate-block.h |  125 ++++++++++
>> include/qemu/queue.h           |   12 +
>> include/qom/cpu.h              |   22 ++
>> target/alpha/translate.c       |   25 +-
>> target/arm/translate-a64.c     |  312 ++++++++++++-------------
>> target/arm/translate.c         |  503 ++++++++++++++++++++++------------------
>> target/arm/translate.h         |   38 ++-
>> target/cris/translate.c        |   26 +-
>> target/hppa/translate.c        |    6
>> target/i386/translate.c        |  353 +++++++++++++++-------------
>> target/lm32/translate.c        |   36 +--
>> target/m68k/translate.c        |   24 +-
>> target/microblaze/translate.c  |   28 +-
>> target/mips/translate.c        |   41 ++-
>> target/moxie/translate.c       |   16 +
>> target/nios2/translate.c       |    6
>> target/openrisc/translate.c    |   25 +-
>> target/ppc/translate.c         |   21 +-
>> target/ppc/translate_init.c    |   32 +--
>> target/s390x/translate.c       |   22 +-
>> target/sh4/translate.c         |   21 +-
>> target/sparc/translate.c       |   17 +
>> target/tilegx/translate.c      |    9 -
>> target/tricore/translate.c     |   11 -
>> target/unicore32/translate.c   |   26 +-
>> target/xtensa/translate.c      |   39 ++-
>> translate-all.c                |    2
>> translate-block.c              |  185 +++++++++++++++
>> 31 files changed, 1212 insertions(+), 793 deletions(-)
>> create mode 100644 include/exec/translate-block.h
>> create mode 100644 translate-block.c
>> 
>> 
>> 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>


> --
> Alex Bennée

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

* Re: [Qemu-devel] [PATCH v9 01/26] Pass generic CPUState to gen_intermediate_code()
  2017-06-25  8:47 ` [Qemu-devel] [PATCH v9 01/26] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
  2017-06-26 10:04   ` [Qemu-devel] [PATCH] fixup! " Alex Bennée
@ 2017-06-26 17:50   ` Emilio G. Cota
  1 sibling, 0 replies; 57+ messages in thread
From: Emilio G. Cota @ 2017-06-26 17:50 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Peter Maydell, Anthony Green, Mark Cave-Ayland,
	Max Filippov, Edgar E. Iglesias, Guan Xuetao, Alexander Graf,
	Richard Henderson, Artyom Tarasenko, Eduardo Habkost,
	open list:ARM, Yongbok Kim, Stafford Horne, Alex Bennée,
	David Gibson, Peter Crosthwaite, Bastian Koppelmann,
	Laurent Vivier, Michael Walle, open list:PowerPC, Paolo Bonzini,
	Aurelien Jarno

On Sun, Jun 25, 2017 at 11:47:46 +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>
> ---
>  include/exec/exec-all.h       |    2 +-
>  target/alpha/translate.c      |   11 +++++------
>  target/arm/translate.c        |   20 ++++++++++----------

Let's also convert gen_intermediate_code_a64 in target/arm/translate-a64.c.

		E.

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

* Re: [Qemu-devel] [PATCH v9 03/26] cpu-exec: Avoid global variables in icount-related functions
  2017-06-25  8:55 ` [Qemu-devel] [PATCH v9 03/26] cpu-exec: Avoid global variables in icount-related functions Lluís Vilanova
@ 2017-06-26 17:53   ` Emilio G. Cota
  0 siblings, 0 replies; 57+ messages in thread
From: Emilio G. Cota @ 2017-06-26 17:53 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Peter Maydell, Anthony Green, Mark Cave-Ayland,
	Max Filippov, Edgar E. Iglesias, Guan Xuetao, Marek Vasut,
	Alexander Graf, Richard Henderson, 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 Sun, Jun 25, 2017 at 11:55:50 +0300, Lluís Vilanova wrote:
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
This approach was NACKed by Richard. I suggest you pick up the v2 I sent
which uses tcg_ctx.tcg_env instead, thereby avoiding a lot of churn.

v2 here: https://lists.gnu.org/archive/html/qemu-devel/2017-06/msg03994.html

		E.

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

* Re: [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-25  8:59 ` [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework Lluís Vilanova
  2017-06-26 10:14   ` Alex Bennée
@ 2017-06-26 17:57   ` Emilio G. Cota
  2017-06-26 18:12   ` Emilio G. Cota
  2017-06-27  2:39   ` Richard Henderson
  3 siblings, 0 replies; 57+ messages in thread
From: Emilio G. Cota @ 2017-06-26 17:57 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Paolo Bonzini, Peter Crosthwaite, Alex Bennée,
	Richard Henderson

On Sun, Jun 25, 2017 at 11:59:54 +0300, Lluís Vilanova wrote:
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
>  Makefile.target                |    1 
>  include/exec/gen-icount.h      |    2 
>  include/exec/translate-block.h |  125 +++++++++++++++++++++++++++
>  include/qom/cpu.h              |   22 +++++
>  translate-block.c              |  185 ++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 334 insertions(+), 1 deletion(-)
>  create mode 100644 include/exec/translate-block.h
>  create mode 100644 translate-block.c
> 
> diff --git a/Makefile.target b/Makefile.target
> index ce8dfe44a8..253c6e7999 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -90,6 +90,7 @@ all: $(PROGS) stap
>  # cpu emulator library
>  obj-y = exec.o translate-all.o cpu-exec.o
>  obj-y += translate-common.o
> +obj-y += translate-block.o

Let's just call this something else; the string "block" will just confuse
people who work on the "block" layer (and will slow down the visual
filtering of patches on qemu-devel).

I suggest translator.[ch] since TranslatorOps is the key struct here.

		E.

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

* Re: [Qemu-devel] [PATCH v9 05/26] target: [tcg] Redefine DISAS_* onto the generic translation framework (DJ_*)
  2017-06-25  9:03 ` [Qemu-devel] [PATCH v9 05/26] target: [tcg] Redefine DISAS_* onto the generic translation framework (DJ_*) Lluís Vilanova
  2017-06-26 11:28   ` [Qemu-devel] [PATCH] maybe fixup! " Alex Bennée
@ 2017-06-26 18:05   ` Emilio G. Cota
  1 sibling, 0 replies; 57+ messages in thread
From: Emilio G. Cota @ 2017-06-26 18:05 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Peter Maydell, Peter Crosthwaite, Laurent Vivier,
	Alexander Graf, open list:ARM, Edgar E. Iglesias, Paolo Bonzini,
	Guan Xuetao, Alex Bennée, Richard Henderson

On Sun, Jun 25, 2017 at 12:03:56 +0300, Lluís Vilanova wrote:
> Temporarily redefine DISAS_* values based on DJ_TARGET. They should
> disappear as targets get ported to the generic framework.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Acked-by: David Gibson <david@gibson.dropbear.id.au> (ppc)
> Acked-by: Eduardo Habkost <ehabkost@redhat.com>
> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> (i386)
> Acked-by: Laurent Vivier <laurent@vivier.eu> (m68k)
> Reviewed-by: Alex Benée <alex.benee@linaro.org> (arm)

Why don't we just keep DISAS_* instead? That will simplify diffs (i.e.
no need to eventually convert anything to DJ_*), and really DISAS_NEXT
makes more sense than DJ_NEXT. You can define a few generic DISAS_foo's,
plus DISAS_TARGET that the existing DISAS_* can build from.

Also, IMO DJ is a poor choice for an acronym. Am I the only one
immediately thinking of 'disc jockey'? =)

		E.

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

* Re: [Qemu-devel] [PATCH v9 16/26] target: [tcg, arm] Replace DISAS_* with DJ_*
  2017-06-25  9:48 ` [Qemu-devel] [PATCH v9 16/26] target: [tcg, arm] " Lluís Vilanova
@ 2017-06-26 18:08   ` Emilio G. Cota
  0 siblings, 0 replies; 57+ messages in thread
From: Emilio G. Cota @ 2017-06-26 18:08 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Peter Maydell, Peter Crosthwaite, open list:ARM,
	Paolo Bonzini, Alex Bennée, Richard Henderson

On Sun, Jun 25, 2017 at 12:48:17 +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/arm/translate-a64.c |   58 ++++++++++++++--------------
>  target/arm/translate.c     |   90 ++++++++++++++++++++++----------------------
>  target/arm/translate.h     |   24 ++++++------
>  3 files changed, 87 insertions(+), 85 deletions(-)

I'd do arm and a64 patches separately; much better for bisectability.

The DisasContextBase patch cannot be split up, obviously.

		E.

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

* Re: [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-25  8:59 ` [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework Lluís Vilanova
  2017-06-26 10:14   ` Alex Bennée
  2017-06-26 17:57   ` Emilio G. Cota
@ 2017-06-26 18:12   ` Emilio G. Cota
  2017-06-27 11:32     ` Lluís Vilanova
  2017-06-27  2:39   ` Richard Henderson
  3 siblings, 1 reply; 57+ messages in thread
From: Emilio G. Cota @ 2017-06-26 18:12 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Paolo Bonzini, Peter Crosthwaite, Alex Bennée,
	Richard Henderson

On Sun, Jun 25, 2017 at 11:59:54 +0300, Lluís Vilanova wrote:
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
>  Makefile.target                |    1 
>  include/exec/gen-icount.h      |    2 
>  include/exec/translate-block.h |  125 +++++++++++++++++++++++++++
>  include/qom/cpu.h              |   22 +++++
>  translate-block.c              |  185 ++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 334 insertions(+), 1 deletion(-)
>  create mode 100644 include/exec/translate-block.h
>  create mode 100644 translate-block.c
(snip)
> diff --git a/include/exec/translate-block.h b/include/exec/translate-block.h
> new file mode 100644
> index 0000000000..d14d23f2cb
> --- /dev/null
> +++ b/include/exec/translate-block.h
(snip)
> +/**
> + * DisasJumpType:
> + * @DJ_NEXT: Next instruction in program order.
> + * @DJ_TOO_MANY: Too many instructions translated.
> + * @DJ_TARGET: Start of target-specific conditions.
> + *
> + * What instruction to disassemble next.
> + */
> +typedef enum DisasJumpType {
> +    DJ_NEXT,
> +    DJ_TOO_MANY,
> +    DJ_TARGET,
> +} DisasJumpType;

I'd give up on the enum to avoid unnecessary casts. Just define DJ_TARGET
(or rather, DISAS_TARGET :>) and let the architecture code add more define's
using it.

		E.

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

* Re: [Qemu-devel] [PATCH v9 06/26] target: [tcg, i386] Port to DisasContextBase
  2017-06-25  9:07 ` [Qemu-devel] [PATCH v9 06/26] target: [tcg, i386] Port to DisasContextBase Lluís Vilanova
@ 2017-06-26 18:14   ` Emilio G. Cota
  2017-06-28 11:23     ` Lluís Vilanova
  0 siblings, 1 reply; 57+ messages in thread
From: Emilio G. Cota @ 2017-06-26 18:14 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: qemu-devel, Paolo Bonzini, Peter Crosthwaite, Alex Bennée,
	Eduardo Habkost, Richard Henderson

On Sun, Jun 25, 2017 at 12:07:57 +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>

Just a minor nit: the commit titles are a little strange to me.
I'd rather do: "target/arch: foo" than "target: [tcg, arch]: foo" --
it's less characters ("tcg" is redundant) and seems more in line with
qemu's idioms.

Thanks,

		E.

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

* Re: [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-26 12:50     ` Lluís Vilanova
@ 2017-06-26 18:21       ` Peter Maydell
  2017-06-27  3:22         ` Richard Henderson
  0 siblings, 1 reply; 57+ messages in thread
From: Peter Maydell @ 2017-06-26 18:21 UTC (permalink / raw)
  To: Alex Bennée, Paolo Bonzini, Peter Crosthwaite,
	QEMU Developers, Richard Henderson

On 26 June 2017 at 13:50, Lluís Vilanova <vilanova@ac.upc.edu> wrote:
> Not that I've seen (at the level of the translation loop). Now I wonder if QEMU
> w/ TCG has a bug that lets it successfully execute instructions that cross page
> boundaries, one of them with invalid permissions (haven't checked).

ARM takes care to get this right -- we stop the TB if the next
insn is going to span the page boundary (or in some corner cases
merely if we think it might span the boundary, because if we guess
wrong that way round the worst that happens is an unnecessarily
short TB). Then the next TB will get the prefetch abort in the right
place if the next page is inaccessible (we will longjump out
of the translate.c code when we attempt the arm_lduw_code for
the 2nd half of the insn). This was fixed in commit 541ebcd401ee4.
The key thing is:
 * first insn in TB: read all its bytes (may result in longjump)
 * subsequent insns in same TB: don't even try to read bytes
   which aren't in pages already known to be safe because of
   having dealt with the first insn (longjump will result in a
   fault with the wrong address)

x86 definitely gets this totally wrong. I would be unsurprised
to find that other variable-length-insn targets do too.

> What I can say is that this check is a very weak one (but common to all
> targets), and that targets like i386 and arm need to refine it further in the
> target-specific code. In fact, now I suspect all targets will need to refine it,
> so it probably makes sense to simply drop this generic check and burden all
> targets with handling it.

For targets which can never have instructions that cross the
page boundary, the only requirement is that we do not attempt
to fetch an instruction from a page other than the one we
started on (otherwise we will cause a spurious instruction
fetch abort).

The simple test program I used to test Thumb
page-boundary crossing instructions is here:
http://people.linaro.org/~peter.maydell/thumb-over-page.c
The signal handler it installs prints the r0 and pc values
reported to the handler so you can check the correct insns
executed and the reported PC was right. Works in linux-user
mode and also system mode (you'll need to sort out your own
guest kernel and filesystem).

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-25  8:59 ` [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework Lluís Vilanova
                     ` (2 preceding siblings ...)
  2017-06-26 18:12   ` Emilio G. Cota
@ 2017-06-27  2:39   ` Richard Henderson
  2017-06-27 15:41     ` Lluís Vilanova
  3 siblings, 1 reply; 57+ messages in thread
From: Richard Henderson @ 2017-06-27  2:39 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Paolo Bonzini, Peter Crosthwaite, Alex Bennée

On 06/25/2017 01:59 AM, Lluís Vilanova wrote:
> +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, TCGv_env *tcg_cpu, TranslationBlock *tb)

tcg_cpu isn't the best name -- it doesn't reference a version of cpu.  Of 
course, you can always get at tcg_ctx.tcg_env, so there's no point in passing 
it anyway.

> +    /* Sanity-check ops */
> +    if (ops->disas_insn == NULL) {
> +        error_report("Missing ops->disas_insn");
> +        abort();
> +    }

Why?  Surely an immediate crash by calling to null is just as easy to debug.

And, bikeshedding, perhaps translate_insn is a better name.  On the first read 
through I assumed this was related to the disassembly log.

> +    while (true) {
> +        CPUBreakpoint *bp;
> +
> +        db->num_insns++;
> +        if (ops->insn_start) {
> +            ops->insn_start(db, cpu);
> +        }

This *must* be defined.  A target cannot skip emitting insn_start or unwinding 
won't work.

> +
> +        /* Early exit before breakpoint checks */
> +        if (unlikely(db->is_jmp != DJ_NEXT)) {
> +            break;
> +        }

This must be done at the end of the loop, not at the beginning of the next 
loop, after we've already emitted insn_start for the following insn.

That said, you already do have that check below, so what is this intended to do?

> +        /* Pass breakpoint hits to target for further processing */
> +        bp = NULL;
> +        do {
> +            bp = cpu_breakpoint_get(cpu, db->pc_next, bp);
> +            if (unlikely(bp) && ops->breakpoint_check) {
> +                BreakpointCheckType bp_check = ops->breakpoint_check(

Is there any point in any of these hooks being null?
An empty function in most cases, or here, one that returns BC_MISS.

> +                    db, cpu, bp);
> +                if (bp_check == 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.
> +                     */
> +                    break;
> +                } else if (bp_check == BC_HIT_TB) {
> +                    goto done_generating;
> +                } else {
> +                    error_report("Unexpected BreakpointCheckType %d", bp_check);
> +                    abort();

What happened to BC_MISS?  And surely better structured as a switch with

     default:
         g_assert_not_reached();

rather than custom logging.

> +#ifdef DEBUG_DISAS
> +    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
> +        qemu_log_in_addr_range(db->pc_first)) {
> +        int flags;
> +        if (ops->disas_flags) {
> +            flags = ops->disas_flags(db);
> +        } else {
> +            flags = 0;
> +        }
> +        qemu_log_lock();
> +        qemu_log("----------------\n");
> +        qemu_log("IN: %s\n", lookup_symbol(db->pc_first));
> +        log_target_disas(cpu, db->pc_first, db->pc_next - db->pc_first, flags);
> +        qemu_log("\n");
> +        qemu_log_unlock();

I think the hook shouldn't be just the flags, but the whole call to 
log_target_disas, at which point there isn't a reason to have a separate in a 
hook for the flags.  Consider the extra checks done for s390x and hppa.


r~

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

* Re: [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-26 10:14   ` Alex Bennée
  2017-06-26 12:50     ` Lluís Vilanova
@ 2017-06-27  2:47     ` Richard Henderson
  1 sibling, 0 replies; 57+ messages in thread
From: Richard Henderson @ 2017-06-27  2:47 UTC (permalink / raw)
  To: Alex Bennée, Lluís Vilanova
  Cc: Paolo Bonzini, Peter Crosthwaite, qemu-devel

On 06/26/2017 03:14 AM, Alex Bennée wrote:
>> +        if ((db->pc_first & TARGET_PAGE_MASK)
>> +            != (db->pc_next & TARGET_PAGE_MASK)) {
>> +            db->is_jmp = DJ_TOO_MANY;
>> +            break;
>> +        }
> 
> How does the first insn avoid this check? And if it does is that right?
> 
> I mean I understand you can construct weird multi-byte instructions
> (especially on x86) that cross the boundary but even if it is the first
> in a TB shouldn't it error if there are no contiguous pages?
> 
> Also isn't the page crossing issue different for SoftMMU and linux-user?

It could be, though I don't believe that many front-ends take advantage.  I 
don't think it makes *that* much difference.

But if it comes to that, there are other edge conditions that can be used, e.g. 
the KSEG non-paged addressing segment for Alpha or MIPS kernel mode.


r~

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

* Re: [Qemu-devel] [PATCH v9 07/26] target: [tcg, i386] Refactor init_disas_context
  2017-06-25  9:12 ` [Qemu-devel] [PATCH v9 07/26] target: [tcg, i386] Refactor init_disas_context Lluís Vilanova
@ 2017-06-27  2:57   ` Richard Henderson
  2017-06-27  6:07     ` Lluís Vilanova
  0 siblings, 1 reply; 57+ messages in thread
From: Richard Henderson @ 2017-06-27  2:57 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Paolo Bonzini, Peter Crosthwaite, Alex Bennée, Eduardo Habkost

On 06/25/2017 02:12 AM, Lluís Vilanova wrote:
> +    DisasContext *dc = container_of(db, DisasContext, base);
>       CPUX86State *env = cpu->env_ptr;
> -    DisasContext dc1, *dc = &dc1;
> -    DisasContextBase *db = &dc1.base;
> -    uint32_t flags;
> -    target_ulong cs_base;
> -    int num_insns;
> -    int max_insns;
> -
> -    /* generate intermediate code */
> -    db->pc_first = tb->pc;
> -    cs_base = tb->cs_base;
> -    flags = tb->flags;
> +    uint32_t flags = db->tb->flags;
> +    target_ulong cs_base = db->tb->cs_base;

As a nit, it would be better for the compiler if you keep only one of the two 
pointers {dc,db} live.  That is, once you've used container_of, always use 
dc->base instead of db.


r~

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

* Re: [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework
  2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
                   ` (25 preceding siblings ...)
  2017-06-26 11:34 ` [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic " Alex Bennée
@ 2017-06-27  3:00 ` Eric Blake
  2017-06-27 12:23   ` Lluís Vilanova
  26 siblings, 1 reply; 57+ messages in thread
From: Eric Blake @ 2017-06-27  3:00 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Paolo Bonzini, Peter Crosthwaite, Alex Bennée, Richard Henderson

[-- Attachment #1: Type: text/plain, Size: 1602 bytes --]

On 06/25/2017 03:43 AM, Lluís Vilanova wrote:
> 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 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).

It's more likely that your rejection message was from your SMTP
connection than from the list (I've had to deal with my ISP's SMTP
server prohibiting me from sending more than 10 patches in a minute;
while using my company's SMTP server did not have that rate-limiting
restriction).

But yes, it would be neat if 'git send-email' had a knob to easily tweak
things to avoid flooding beyond a picky SMTP server's rate limits.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

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

* Re: [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-26 18:21       ` Peter Maydell
@ 2017-06-27  3:22         ` Richard Henderson
  2017-06-27  9:23           ` Peter Maydell
  0 siblings, 1 reply; 57+ messages in thread
From: Richard Henderson @ 2017-06-27  3:22 UTC (permalink / raw)
  To: Peter Maydell, Alex Bennée, Paolo Bonzini,
	Peter Crosthwaite, QEMU Developers

On 06/26/2017 11:21 AM, Peter Maydell wrote:
> x86 definitely gets this totally wrong. I would be unsurprised
> to find that other variable-length-insn targets do too.

For x86, doing this optimally is difficult.  We *could* fix it simply by 
single-stepping when executing within the last 15 bytes of the page.


r~

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

* Re: [Qemu-devel] [PATCH v9 21/26] target: [tcg, arm] Port to insn_start
  2017-06-25 10:08 ` [Qemu-devel] [PATCH v9 21/26] target: [tcg, arm] Port to insn_start Lluís Vilanova
  2017-06-26 11:31   ` Alex Bennée
@ 2017-06-27  3:33   ` Richard Henderson
  2017-06-28 11:48     ` Lluís Vilanova
  1 sibling, 1 reply; 57+ messages in thread
From: Richard Henderson @ 2017-06-27  3:33 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, open list:ARM, Paolo Bonzini,
	Alex Bennée

On 06/25/2017 03:08 AM, Lluís Vilanova wrote:
> +static void arm_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
> +{
> +    DisasContext *dc = container_of(db, 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->is_jmp = DJ_EXC;
> +    }
> +#endif
> +}

I think this DJ_EXC block is better placed at the start of disas_insn.

It is, however, the answer to one of my questions re patch 4/26.


r~

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

* Re: [Qemu-devel] [PATCH v9 26/26] target: [tcg, arm] Port to generic translation framework
  2017-06-25 10:28 ` [Qemu-devel] [PATCH v9 26/26] target: [tcg, arm] Port to generic translation framework Lluís Vilanova
@ 2017-06-27  3:47   ` Richard Henderson
  0 siblings, 0 replies; 57+ messages in thread
From: Richard Henderson @ 2017-06-27  3:47 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Peter Maydell, Peter Crosthwaite, open list:ARM, Paolo Bonzini,
	Alex Bennée

On 06/25/2017 03:28 AM, Lluís Vilanova wrote:
> +static TranslatorOps aarch64_translator_ops = {
> +    .init_disas_context = aarch64_trblock_init_disas_context,
> +    .insn_start = aarch64_trblock_insn_start,
> +    .breakpoint_check = aarch64_trblock_breakpoint_check,
> +    .disas_insn = aarch64_trblock_disas_insn,
> +    .tb_stop = aarch64_trblock_tb_stop,
> +    .disas_flags = aarch64_trblock_disas_flags,
> +};

const.

> +void gen_intermediate_code_a64(DisasContextBase *db, CPUState *cpu,
>                                  TranslationBlock *tb)
>   {
> +    translate_block(&aarch64_translator_ops, db, cpu, &cpu_env, tb);
>   }
...
>   /* generate intermediate code for basic block 'tb'.  */
>   void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
>   {
>       DisasContext dc1, *dc = &dc1;
>       DisasContextBase *db = &dc->base;
>   
>       /* generate intermediate code */
>   
> @@ -12202,97 +12214,11 @@ 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(db, cpu, tb);
>           return;
> +    } else {
> +        translate_block(&arm_translator_ops, db, cpu, &cpu_env, tb);
>       }

There's really no point in keeping gen_intermediate_code_a64 is there.

This is better written as

   translate_block((ARM_TBFLAG_AARCH64_STATE(tb->flags)
                    ? &aarch64_translator_ops
                    : &arm_translator_ops),
                   &dc->base, cpu, tb);


r~

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

* Re: [Qemu-devel] [PATCH v9 07/26] target: [tcg, i386] Refactor init_disas_context
  2017-06-27  2:57   ` Richard Henderson
@ 2017-06-27  6:07     ` Lluís Vilanova
  0 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-27  6:07 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Paolo Bonzini, Peter Crosthwaite, Alex Bennée,
	Eduardo Habkost

Richard Henderson writes:

> On 06/25/2017 02:12 AM, Lluís Vilanova wrote:
>> +    DisasContext *dc = container_of(db, DisasContext, base);
>> CPUX86State *env = cpu->env_ptr;
>> -    DisasContext dc1, *dc = &dc1;
>> -    DisasContextBase *db = &dc1.base;
>> -    uint32_t flags;
>> -    target_ulong cs_base;
>> -    int num_insns;
>> -    int max_insns;
>> -
>> -    /* generate intermediate code */
>> -    db->pc_first = tb->pc;
>> -    cs_base = tb->cs_base;
>> -    flags = tb->flags;
>> +    uint32_t flags = db->tb->flags;
>> +    target_ulong cs_base = db->tb->cs_base;

> As a nit, it would be better for the compiler if you keep only one of the two
> pointers {dc,db} live.  That is, once you've used container_of, always use
> dc-> base instead of db.

That's what the previous version did, but Emilio proposed to use both to keep
diffs more readable.

Still, if using both dc/db will confuse the compiler's alias analysis, I can
revert it back to dc->base.

Thanks,
  Lluis

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

* Re: [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-27  3:22         ` Richard Henderson
@ 2017-06-27  9:23           ` Peter Maydell
  0 siblings, 0 replies; 57+ messages in thread
From: Peter Maydell @ 2017-06-27  9:23 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Alex Bennée, Paolo Bonzini, Peter Crosthwaite, QEMU Developers

On 27 June 2017 at 04:22, Richard Henderson <rth@twiddle.net> wrote:
> On 06/26/2017 11:21 AM, Peter Maydell wrote:
>>
>> x86 definitely gets this totally wrong. I would be unsurprised
>> to find that other variable-length-insn targets do too.
>
>
> For x86, doing this optimally is difficult.  We *could* fix it simply by
> single-stepping when executing within the last 15 bytes of the page.

My feeling is that the "longjump out of translate.c on insn aborts"
approach is pretty confusing and ideally we should get rid of that
entirely in favour of having the translate code handle an error
return from the "load byte/short/word" functions it calls. That might
then make it easier to bail out on page-crossing instructions.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-26 18:12   ` Emilio G. Cota
@ 2017-06-27 11:32     ` Lluís Vilanova
  0 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-27 11:32 UTC (permalink / raw)
  To: Emilio G. Cota
  Cc: Paolo Bonzini, Richard Henderson, Alex Bennée, qemu-devel,
	Peter Crosthwaite

Emilio G Cota writes:

> On Sun, Jun 25, 2017 at 11:59:54 +0300, Lluís Vilanova wrote:
>> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
>> ---
>> Makefile.target                |    1 
>> include/exec/gen-icount.h      |    2 
>> include/exec/translate-block.h |  125 +++++++++++++++++++++++++++
>> include/qom/cpu.h              |   22 +++++
>> translate-block.c              |  185 ++++++++++++++++++++++++++++++++++++++++
>> 5 files changed, 334 insertions(+), 1 deletion(-)
>> create mode 100644 include/exec/translate-block.h
>> create mode 100644 translate-block.c
> (snip)
>> diff --git a/include/exec/translate-block.h b/include/exec/translate-block.h
>> new file mode 100644
>> index 0000000000..d14d23f2cb
>> --- /dev/null
>> +++ b/include/exec/translate-block.h
> (snip)
>> +/**
>> + * DisasJumpType:
>> + * @DJ_NEXT: Next instruction in program order.
>> + * @DJ_TOO_MANY: Too many instructions translated.
>> + * @DJ_TARGET: Start of target-specific conditions.
>> + *
>> + * What instruction to disassemble next.
>> + */
>> +typedef enum DisasJumpType {
>> +    DJ_NEXT,
>> +    DJ_TOO_MANY,
>> +    DJ_TARGET,
>> +} DisasJumpType;

> I'd give up on the enum to avoid unnecessary casts. Just define DJ_TARGET
> (or rather, DISAS_TARGET :>) and let the architecture code add more define's
> using it.

I'm all for restoring the original name (haven't checked if it will produce any
redefine errors).

But using an enum makes the API more explicit about the intended values. Still,
if the churn of casting outweighs the API clarity, I can revert this.

Another option previously suggested on the list is defining DISAS_TARGET_[0..N]
on the enum, and letting targets simply define their own name when mapped to
those. I'll try that one before completely dropping the enum. That is, unless
someone is strongly for going back to defines.


Cheers,
  Lluis

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

* Re: [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework
  2017-06-27  3:00 ` Eric Blake
@ 2017-06-27 12:23   ` Lluís Vilanova
  0 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-27 12:23 UTC (permalink / raw)
  To: Eric Blake
  Cc: qemu-devel, Paolo Bonzini, Richard Henderson, Alex Bennée,
	Peter Crosthwaite

Eric Blake writes:

> On 06/25/2017 03:43 AM, Lluís Vilanova wrote:
>> 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 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).

> It's more likely that your rejection message was from your SMTP
> connection than from the list (I've had to deal with my ISP's SMTP
> server prohibiting me from sending more than 10 patches in a minute;
> while using my company's SMTP server did not have that rate-limiting
> restriction).

> But yes, it would be neat if 'git send-email' had a knob to easily tweak
> things to avoid flooding beyond a picky SMTP server's rate limits.

Yup, it's my SMTP, not the list. Since I'm using "stg mail --git" (uses git
send-email underneath), I can set up an inter-mail wait time.


Cheers,
  Lluis

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

* Re: [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework
  2017-06-27  2:39   ` Richard Henderson
@ 2017-06-27 15:41     ` Lluís Vilanova
  0 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-27 15:41 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Paolo Bonzini, Peter Crosthwaite, Alex Bennée

Richard Henderson writes:

> On 06/25/2017 01:59 AM, Lluís Vilanova wrote:
[...]
>> +
>> +        /* Early exit before breakpoint checks */
>> +        if (unlikely(db->is_jmp != DJ_NEXT)) {
>> +            break;
>> +        }

> This must be done at the end of the loop, not at the beginning of the next loop,
> after we've already emitted insn_start for the following insn.

> That said, you already do have that check below, so what is this intended to do?

Some targets (for now, arm-linux-user) need to finish the translation loop
before even the first instruction.


Cheers,
  Lluis

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

* Re: [Qemu-devel] [PATCH v9 06/26] target: [tcg, i386] Port to DisasContextBase
  2017-06-26 18:14   ` Emilio G. Cota
@ 2017-06-28 11:23     ` Lluís Vilanova
  2017-06-29 21:50       ` Emilio G. Cota
  0 siblings, 1 reply; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-28 11:23 UTC (permalink / raw)
  To: Emilio G. Cota
  Cc: qemu-devel, Paolo Bonzini, Peter Crosthwaite, Alex Bennée,
	Eduardo Habkost, Richard Henderson

Emilio G Cota writes:

> On Sun, Jun 25, 2017 at 12:07:57 +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>

> Just a minor nit: the commit titles are a little strange to me.
> I'd rather do: "target/arch: foo" than "target: [tcg, arch]: foo" --
> it's less characters ("tcg" is redundant) and seems more in line with
> qemu's idioms.

Is tcg redundant? I thought it was necessary for differentiating it from the kvm
target-specific parts.


Cheers,
  Lluis

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

* Re: [Qemu-devel] [PATCH v9 21/26] target: [tcg, arm] Port to insn_start
  2017-06-27  3:33   ` Richard Henderson
@ 2017-06-28 11:48     ` Lluís Vilanova
  0 siblings, 0 replies; 57+ messages in thread
From: Lluís Vilanova @ 2017-06-28 11:48 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, Peter Maydell, Peter Crosthwaite, open list:ARM,
	Paolo Bonzini, Alex Bennée

Richard Henderson writes:

> On 06/25/2017 03:08 AM, Lluís Vilanova wrote:
>> +static void arm_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
>> +{
>> +    DisasContext *dc = container_of(db, 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->is_jmp = DJ_EXC;
>> +    }
>> +#endif
>> +}

> I think this DJ_EXC block is better placed at the start of disas_insn.

> It is, however, the answer to one of my questions re patch 4/26.

It cannot, because DJ_EXC make the generic code break out of trasnlation before
doing anything else, which is what the original code does.

Cheers,
  Lluis

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

* Re: [Qemu-devel] [PATCH v9 06/26] target: [tcg, i386] Port to DisasContextBase
  2017-06-28 11:23     ` Lluís Vilanova
@ 2017-06-29 21:50       ` Emilio G. Cota
  0 siblings, 0 replies; 57+ messages in thread
From: Emilio G. Cota @ 2017-06-29 21:50 UTC (permalink / raw)
  To: qemu-devel, Paolo Bonzini, Peter Crosthwaite, Alex Bennée,
	Eduardo Habkost, Richard Henderson

On Wed, Jun 28, 2017 at 14:23:07 +0300, Lluís Vilanova wrote:
> Emilio G Cota writes:
> 
> > On Sun, Jun 25, 2017 at 12:07:57 +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>
> 
> > Just a minor nit: the commit titles are a little strange to me.
> > I'd rather do: "target/arch: foo" than "target: [tcg, arch]: foo" --
> > it's less characters ("tcg" is redundant) and seems more in line with
> > qemu's idioms.
> 
> Is tcg redundant? I thought it was necessary for differentiating it from the kvm
> target-specific parts.

In most cases it is redundant -- anyway my point is that "targer/foo"
will be enough to get the right eyes on the patch.

Cheers,

		E.

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

end of thread, other threads:[~2017-06-29 21:50 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-25  8:43 [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic translation framework Lluís Vilanova
2017-06-25  8:47 ` [Qemu-devel] [PATCH v9 01/26] Pass generic CPUState to gen_intermediate_code() Lluís Vilanova
2017-06-26 10:04   ` [Qemu-devel] [PATCH] fixup! " Alex Bennée
2017-06-26 12:37     ` Lluís Vilanova
2017-06-26 17:50   ` [Qemu-devel] [PATCH v9 01/26] " Emilio G. Cota
2017-06-25  8:51 ` [Qemu-devel] [PATCH v9 02/26] queue: Add macro for incremental traversal Lluís Vilanova
2017-06-25  8:55 ` [Qemu-devel] [PATCH v9 03/26] cpu-exec: Avoid global variables in icount-related functions Lluís Vilanova
2017-06-26 17:53   ` Emilio G. Cota
2017-06-25  8:59 ` [Qemu-devel] [PATCH v9 04/26] target: [tcg] Add generic translation framework Lluís Vilanova
2017-06-26 10:14   ` Alex Bennée
2017-06-26 12:50     ` Lluís Vilanova
2017-06-26 18:21       ` Peter Maydell
2017-06-27  3:22         ` Richard Henderson
2017-06-27  9:23           ` Peter Maydell
2017-06-27  2:47     ` Richard Henderson
2017-06-26 17:57   ` Emilio G. Cota
2017-06-26 18:12   ` Emilio G. Cota
2017-06-27 11:32     ` Lluís Vilanova
2017-06-27  2:39   ` Richard Henderson
2017-06-27 15:41     ` Lluís Vilanova
2017-06-25  9:03 ` [Qemu-devel] [PATCH v9 05/26] target: [tcg] Redefine DISAS_* onto the generic translation framework (DJ_*) Lluís Vilanova
2017-06-26 11:28   ` [Qemu-devel] [PATCH] maybe fixup! " Alex Bennée
2017-06-26 18:05   ` [Qemu-devel] [PATCH v9 05/26] " Emilio G. Cota
2017-06-25  9:07 ` [Qemu-devel] [PATCH v9 06/26] target: [tcg, i386] Port to DisasContextBase Lluís Vilanova
2017-06-26 18:14   ` Emilio G. Cota
2017-06-28 11:23     ` Lluís Vilanova
2017-06-29 21:50       ` Emilio G. Cota
2017-06-25  9:12 ` [Qemu-devel] [PATCH v9 07/26] target: [tcg, i386] Refactor init_disas_context Lluís Vilanova
2017-06-27  2:57   ` Richard Henderson
2017-06-27  6:07     ` Lluís Vilanova
2017-06-25  9:16 ` [Qemu-devel] [PATCH v9 08/26] target: [tcg, i386] Refactor init_globals Lluís Vilanova
2017-06-25  9:20 ` [Qemu-devel] [PATCH v9 09/26] target: [tcg, i386] Refactor insn_start Lluís Vilanova
2017-06-25  9:24 ` [Qemu-devel] [PATCH v9 10/26] target: [tcg, i386] Refactor breakpoint_check Lluís Vilanova
2017-06-25  9:28 ` [Qemu-devel] [PATCH v9 11/26] target: [tcg, i386] Refactor disas_insn Lluís Vilanova
2017-06-25  9:32 ` [Qemu-devel] [PATCH v9 12/26] target: [tcg,i386] Refactor tb_stop Lluís Vilanova
2017-06-25  9:36 ` [Qemu-devel] [PATCH v9 13/26] target: [tcg, i386] Refactor disas_flags Lluís Vilanova
2017-06-25  9:40 ` [Qemu-devel] [PATCH v9 14/26] target: [tcg, i386] Replace DISAS_* with DJ_* Lluís Vilanova
2017-06-25  9:48 ` [Qemu-devel] [PATCH v9 16/26] target: [tcg, arm] " Lluís Vilanova
2017-06-26 18:08   ` Emilio G. Cota
2017-06-25  9:52 ` [Qemu-devel] [PATCH v9 17/26] target: [tcg, arm] Port to DisasContextBase Lluís Vilanova
2017-06-25  9:56 ` [Qemu-devel] [PATCH v9 18/26] target: [tcg, arm] Port to init_disas_context Lluís Vilanova
2017-06-25 10:00 ` [Qemu-devel] [PATCH v9 19/26] target: [tcg, arm] Port to init_globals Lluís Vilanova
2017-06-25 10:04 ` [Qemu-devel] [PATCH v9 20/26] target: [tcg,arm] Port to tb_start Lluís Vilanova
2017-06-25 10:08 ` [Qemu-devel] [PATCH v9 21/26] target: [tcg, arm] Port to insn_start Lluís Vilanova
2017-06-26 11:31   ` Alex Bennée
2017-06-27  3:33   ` Richard Henderson
2017-06-28 11:48     ` Lluís Vilanova
2017-06-25 10:12 ` [Qemu-devel] [PATCH v9 22/26] target: [tcg, arm] Port to breakpoint_check Lluís Vilanova
2017-06-25 10:16 ` [Qemu-devel] [PATCH v9 23/26] target: [tcg, arm] Port to disas_insn Lluís Vilanova
2017-06-25 10:20 ` [Qemu-devel] [PATCH v9 24/26] target: [tcg,arm] Port to tb_stop Lluís Vilanova
2017-06-25 10:24 ` [Qemu-devel] [PATCH v9 25/26] target: [tcg, arm] Port to disas_flags Lluís Vilanova
2017-06-25 10:28 ` [Qemu-devel] [PATCH v9 26/26] target: [tcg, arm] Port to generic translation framework Lluís Vilanova
2017-06-27  3:47   ` Richard Henderson
2017-06-26 11:34 ` [Qemu-devel] [RFC PATCH v9 00/26] translate: [tcg] Generic " Alex Bennée
2017-06-26 13:02   ` Lluís Vilanova
2017-06-27  3:00 ` Eric Blake
2017-06-27 12:23   ` 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.