qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v14 00/34] Generic translation framework
@ 2017-07-15  9:42 Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 01/34] Pass generic CPUState to gen_intermediate_code() Richard Henderson
                   ` (34 more replies)
  0 siblings, 35 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

This is my take on Lluis' v13.  I've also written patches for
Alpha, SH4, and HPPA as examples of more complicated cases.
I have not included them here, but for the record:

  git://github.com/rth7680/qemu.git tgt-axp-2 tgt-sh4-2 tgt-pa

have the patches.  In the case of Alpha and SH4, there were
other dependencies not in tree.

Changes to the generic loop include

  * Move adjustment of max_insns from tb_start to init_disas_context.

  * Removed pc_next return from translate_insn.
    Just assign to that field from within the hook.

  * Removed tcg_check_temp_count from generic loop.

    It turns out that HPPA is not ameanable to this at all.
    There is in fact a temp that may be live between
    tb_start -> translate_insn and translate_insn -> tb_stop.

    I've added the check back to arm specifically, added a
    common function that can log the error, and use qem_log
    instead of error_report.

  * Moved gen_io_end to exactly match gen_io_start.
    I'm pretty sure this is what we always intended anyway.
    
  * Moved TB size/icount assignments before disas_log.

Changes to the ARM and i386 targets include

  * Tidy DisasJumpType usage wrt DISAS_NORETURN.

Changes to the ARM target include

  * Move the kernel magic page check after breakpoint checks.
    There's no reason why gdb couldn't attach in the magic page.
    This movement allows the insn_start hook to not be so weird
    generically.

  * Split out a separate thum translate_insn hook.
    There's a lot that T32 needs to do that A32 doesn't.

  * Reduce the number of end-of-TB checks in translate_insn.
    For A64 and A32, this means page crossing checks moved to
    init_disas_context.  Even T32 can have its single-step
    check moved.


r~


Lluís Vilanova (25):
  Pass generic CPUState to gen_intermediate_code()
  target: [tcg] Use a generic enum for DISAS_ values
  tcg: Add generic translation framework
  target/i386: [tcg] Port to DisasContextBase
  target/i386: [tcg] Port to init_disas_context
  target/i386: [tcg] Port to insn_start
  target/i386: [tcg] Port to breakpoint_check
  target/i386: [tcg] Port to translate_insn
  target/i386: [tcg] Port to tb_stop
  target/i386: [tcg] Port to disas_log
  target/i386: [tcg] Port to generic translation framework
  target/arm: [tcg] Port to DisasContextBase
  target/arm: [tcg] Port to init_disas_context
  target/arm: [tcg,a64] Port to init_disas_context
  target/arm: [tcg] Port to tb_start
  target/arm: [tcg] Port to insn_start
  target/arm: [tcg,a64] Port to insn_start
  target/arm: [tcg,a64] Port to breakpoint_check
  target/arm: [tcg] Port to translate_insn
  target/arm: [tcg,a64] Port to translate_insn
  target/arm: [tcg] Port to tb_stop
  target/arm: [tcg,a64] Port to tb_stop
  target/arm: [tcg] Port to disas_log
  target/arm: [tcg,a64] Port to disas_log
  target/arm: [tcg] Port to generic translation framework

Richard Henderson (9):
  tcg: Add generic DISAS_NORETURN
  target/i386: Use generic DISAS_* enumerators
  target/arm: Use DISAS_NORETURN
  target/arm: Delay check for magic kernel page
  target/arm: Set is_jmp properly after single-stepping
  target/arm: [a64] Move page and ss checks to init_disas_context
  target/arm: Move ss check to init_disas_context
  target/arm: Split out thumb_tr_translate_insn
  target/arm: Perform per-insn cross-page check only for Thumb

 include/exec/exec-all.h       |   8 +-
 include/exec/translator.h     | 141 +++++++++++++
 target/arm/translate.h        |  39 ++--
 accel/tcg/translate-all.c     |   2 +-
 accel/tcg/translator.c        | 133 ++++++++++++
 target/alpha/translate.c      |   5 +-
 target/arm/translate-a64.c    | 288 +++++++++++++------------
 target/arm/translate.c        | 481 +++++++++++++++++++++++-------------------
 target/cris/translate.c       |  14 +-
 target/hppa/translate.c       |   5 +-
 target/i386/translate.c       | 299 +++++++++++++-------------
 target/lm32/translate.c       |  10 +-
 target/m68k/translate.c       |  12 +-
 target/microblaze/translate.c |  10 +-
 target/mips/translate.c       |   5 +-
 target/moxie/translate.c      |   4 +-
 target/nios2/translate.c      |  11 +-
 target/openrisc/translate.c   |  10 +-
 target/ppc/translate.c        |   5 +-
 target/s390x/translate.c      |   8 +-
 target/sh4/translate.c        |   5 +-
 target/sparc/translate.c      |   5 +-
 target/tilegx/translate.c     |   5 +-
 target/tricore/translate.c    |   5 +-
 target/unicore32/translate.c  |  12 +-
 target/xtensa/translate.c     |   9 +-
 accel/tcg/Makefile.objs       |   1 +
 27 files changed, 936 insertions(+), 596 deletions(-)
 create mode 100644 include/exec/translator.h
 create mode 100644 accel/tcg/translator.c

-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 01/34] Pass generic CPUState to gen_intermediate_code()
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-17 22:56   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 02/34] tcg: Add generic DISAS_NORETURN Richard Henderson
                   ` (33 subsequent siblings)
  34 siblings, 1 reply; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002025498.22386.18051908483085660588.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 include/exec/exec-all.h       | 2 +-
 target/arm/translate.h        | 4 ++--
 accel/tcg/translate-all.c     | 2 +-
 target/alpha/translate.c      | 5 ++---
 target/arm/translate-a64.c    | 6 +++---
 target/arm/translate.c        | 6 +++---
 target/cris/translate.c       | 7 +++----
 target/hppa/translate.c       | 5 ++---
 target/i386/translate.c       | 5 ++---
 target/lm32/translate.c       | 4 ++--
 target/m68k/translate.c       | 5 ++---
 target/microblaze/translate.c | 4 ++--
 target/mips/translate.c       | 5 ++---
 target/moxie/translate.c      | 4 ++--
 target/nios2/translate.c      | 5 ++---
 target/openrisc/translate.c   | 4 ++--
 target/ppc/translate.c        | 5 ++---
 target/s390x/translate.c      | 5 ++---
 target/sh4/translate.c        | 5 ++---
 target/sparc/translate.c      | 5 ++---
 target/tilegx/translate.c     | 5 ++---
 target/tricore/translate.c    | 5 ++---
 target/unicore32/translate.c  | 5 ++---
 target/xtensa/translate.c     | 5 ++---
 24 files changed, 49 insertions(+), 64 deletions(-)

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index bf8da2a..48d9d11 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 *cpu, struct TranslationBlock *tb);
 void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb,
                           target_ulong *data);
 
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 15d383d..e5da614 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -146,7 +146,7 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);
-void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb);
+void gen_intermediate_code_a64(CPUState *cpu, TranslationBlock *tb);
 void gen_a64_set_pc_im(uint64_t val);
 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
                             fprintf_function cpu_fprintf, int flags);
@@ -155,7 +155,7 @@ static inline void a64_translate_init(void)
 {
 }
 
-static inline void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
+static inline void gen_intermediate_code_a64(CPUState *cpu, TranslationBlock *tb)
 {
 }
 
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 4e1831c..02b357f 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1273,7 +1273,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
     tcg_func_start(&tcg_ctx);
 
     tcg_ctx.cpu = ENV_GET_CPU(env);
-    gen_intermediate_code(env, tb);
+    gen_intermediate_code(cpu, tb);
     tcg_ctx.cpu = NULL;
 
     trace_translate_block(tb, tb->pc, tb->tc_ptr);
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 232af9e..7b39101 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -2911,10 +2911,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
     return ret;
 }
 
-void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
 {
-    AlphaCPU *cpu = alpha_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUAlphaState *env = cs->env_ptr;
     DisasContext ctx, *ctxp = &ctx;
     target_ulong pc_start;
     target_ulong pc_mask;
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index e55547d..f9bd1a9 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11190,10 +11190,10 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
     free_tmp_a64(s);
 }
 
-void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
+void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
 {
-    CPUState *cs = CPU(cpu);
-    CPUARMState *env = &cpu->env;
+    CPUARMState *env = cs->env_ptr;
+    ARMCPU *cpu = arm_env_get_cpu(env);
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_start;
     target_ulong next_page_start;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 0862f9e..e80cc35 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 *cs, TranslationBlock *tb)
 {
+    CPUARMState *env = cs->env_ptr;
     ARMCPU *cpu = arm_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
     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(cs, tb);
         return;
     }
 
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 0ee05ca..12b96eb 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 *cs, struct TranslationBlock *tb)
 {
-    CRISCPU *cpu = cris_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUCRISState *env = cs->env_ptr;
     uint32_t pc_start;
     unsigned int insn_len;
     struct DisasContext ctx;
@@ -3105,7 +3104,7 @@ 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;
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index e10abc5..900870c 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -3740,10 +3740,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
     return gen_illegal(ctx);
 }
 
-void gen_intermediate_code(CPUHPPAState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
 {
-    HPPACPU *cpu = hppa_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUHPPAState *env = cs->env_ptr;
     DisasContext ctx;
     ExitStatus ret;
     int num_insns, max_insns, i;
diff --git a/target/i386/translate.c b/target/i386/translate.c
index ed3b896..cab9e32 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 *cs, TranslationBlock *tb)
 {
-    X86CPU *cpu = x86_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUX86State *env = cs->env_ptr;
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_ptr;
     uint32_t flags;
diff --git a/target/lm32/translate.c b/target/lm32/translate.c
index 692882f..f68f372 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 *cs, struct TranslationBlock *tb)
 {
+    CPULM32State *env = cs->env_ptr;
     LM32CPU *cpu = lm32_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
     struct DisasContext ctx, *dc = &ctx;
     uint32_t pc_start;
     uint32_t next_page_start;
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 3a519b7..9161df2 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -5519,10 +5519,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 *cs, TranslationBlock *tb)
 {
-    M68kCPU *cpu = m68k_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUM68KState *env = cs->env_ptr;
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_start;
     int pc_offset;
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index cb65d1e..a24373c 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -1625,10 +1625,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 *cs, struct TranslationBlock *tb)
 {
+    CPUMBState *env = cs->env_ptr;
     MicroBlazeCPU *cpu = mb_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
     uint32_t pc_start;
     struct DisasContext ctx;
     struct DisasContext *dc = &ctx;
diff --git a/target/mips/translate.c b/target/mips/translate.c
index befb87f..7a45aa6 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -19882,10 +19882,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
     }
 }
 
-void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
 {
-    MIPSCPU *cpu = mips_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUMIPSState *env = cs->env_ptr;
     DisasContext ctx;
     target_ulong pc_start;
     target_ulong next_page_start;
diff --git a/target/moxie/translate.c b/target/moxie/translate.c
index 0660b44..3cfd232 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 *cs, struct TranslationBlock *tb)
 {
+    CPUMoxieState *env = cs->env_ptr;
     MoxieCPU *cpu = moxie_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
     DisasContext ctx;
     target_ulong pc_start;
     int num_insns, max_insns;
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 2f3c2e5..8b97d65 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 e49518e..a014131 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -1518,10 +1518,10 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
     }
 }
 
-void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
 {
+    CPUOpenRISCState *env = cs->env_ptr;
     OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
     struct DisasContext ctx, *dc = &ctx;
     uint32_t pc_start;
     uint32_t next_page_start;
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index c0cd64d..acb6e88 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 *cs, struct TranslationBlock *tb)
 {
-    PowerPCCPU *cpu = ppc_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUPPCState *env = cs->env_ptr;
     DisasContext ctx, *ctxp = &ctx;
     opc_handler_t **table, *handler;
     target_ulong pc_start;
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 592d6b0..cd8c38d 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -5764,10 +5764,9 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
     return ret;
 }
 
-void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
 {
-    S390CPU *cpu = s390_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUS390XState *env = cs->env_ptr;
     DisasContext dc;
     target_ulong pc_start;
     uint64_t next_page_start;
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
index 8bc132b..1a5ca39 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 *cs, struct TranslationBlock *tb)
 {
-    SuperHCPU *cpu = sh_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUSH4State *env = cs->env_ptr;
     DisasContext ctx;
     target_ulong pc_start;
     int num_insns;
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index aa6734d..293b9c6 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 *cs, TranslationBlock * tb)
 {
-    SPARCCPU *cpu = sparc_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUSPARCState *env = cs->env_ptr;
     target_ulong pc_start, last_pc;
     DisasContext dc1, *dc = &dc1;
     int num_insns;
diff --git a/target/tilegx/translate.c b/target/tilegx/translate.c
index ff2ef7b..ace2830 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 *cs, struct TranslationBlock *tb)
 {
-    TileGXCPU *cpu = tilegx_env_get_cpu(env);
+    CPUTLGState *env = cs->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;
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
index ddd2dd0..4e4198e 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 *cs, struct TranslationBlock *tb)
 {
-    TriCoreCPU *cpu = tricore_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUTriCoreState *env = cs->env_ptr;
     DisasContext ctx;
     target_ulong pc_start;
     int num_insns, max_insns;
diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c
index 666a201..8f30cff 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 *cs, TranslationBlock *tb)
 {
-    UniCore32CPU *cpu = uc32_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUUniCore32State *env = cs->env_ptr;
     DisasContext dc1, *dc = &dc1;
     target_ulong pc_start;
     uint32_t next_page_start;
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index 2630024..f3f0ff5 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 *cs, TranslationBlock *tb)
 {
-    XtensaCPU *cpu = xtensa_env_get_cpu(env);
-    CPUState *cs = CPU(cpu);
+    CPUXtensaState *env = cs->env_ptr;
     DisasContext dc;
     int insn_count = 0;
     int max_insns = tb->cflags & CF_COUNT_MASK;
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 02/34] tcg: Add generic DISAS_NORETURN
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 01/34] Pass generic CPUState to gen_intermediate_code() Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 21:25   ` Emilio G. Cota
  2017-07-21 22:32   ` Lluís Vilanova
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 03/34] target/i386: Use generic DISAS_* enumerators Richard Henderson
                   ` (32 subsequent siblings)
  34 siblings, 2 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

This will allow some amount of cleanup to happen before
switching the backends over to enum DisasJumpType.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 include/exec/exec-all.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 48d9d11..6760078 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -40,6 +40,7 @@ typedef ram_addr_t tb_page_addr_t;
 #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 */
+#define DISAS_NORETURN 4 /* the tb has already been exited */
 
 #include "qemu/log.h"
 
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 03/34] target/i386: Use generic DISAS_* enumerators
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 01/34] Pass generic CPUState to gen_intermediate_code() Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 02/34] tcg: Add generic DISAS_NORETURN Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 21:25   ` Emilio G. Cota
  2017-07-21 22:35   ` Lluís Vilanova
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 04/34] target/arm: Use DISAS_NORETURN Richard Henderson
                   ` (31 subsequent siblings)
  34 siblings, 2 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

This target is not sophisticated in its use of cleanups at the
end of the translation loop.  For the most part, any condition
that exits the TB is dealt with by emitting the exiting opcode
right then and there.  Therefore the only is_jmp indicator that
is needed is DISAS_NORETURN.

For two stack segment modifying cases, we have not yet exited
the TB (therefore DISAS_NORETURN feels wrong), but intend to exit.
The caller of gen_movl_seg_T0 currently checks for any non-zero
value, therefore DISAS_TOO_MANY seems acceptable for that usage.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/i386/translate.c | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index cab9e32..3ffbf1b 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -31,6 +31,7 @@
 #include "trace-tcg.h"
 #include "exec/log.h"
 
+#define DISAS_TOO_MANY 5
 
 #define PREFIX_REPZ   0x01
 #define PREFIX_REPNZ  0x02
@@ -2153,6 +2154,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
         tcg_gen_goto_tb(tb_num);
         gen_jmp_im(eip);
         tcg_gen_exit_tb((uintptr_t)s->tb + tb_num);
+        s->is_jmp = DISAS_NORETURN;
     } else {
         /* jump to another page */
         gen_jmp_im(eip);
@@ -2173,7 +2175,6 @@ 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;
     } else {
         l1 = gen_new_label();
         l2 = gen_new_label();
@@ -2243,12 +2244,14 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
            because ss32 may change. For R_SS, translation must always
            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;
+        if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS)) {
+            s->is_jmp = DISAS_TOO_MANY;
+        }
     } else {
         gen_op_movl_seg_T0_vm(seg_reg);
-        if (seg_reg == R_SS)
-            s->is_jmp = DISAS_TB_JUMP;
+        if (seg_reg == R_SS) {
+            s->is_jmp = DISAS_TOO_MANY;
+        }
     }
 }
 
@@ -2420,7 +2423,7 @@ static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
     gen_update_cc_op(s);
     gen_jmp_im(cur_eip);
     gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
-    s->is_jmp = DISAS_TB_JUMP;
+    s->is_jmp = DISAS_NORETURN;
 }
 
 /* Generate #UD for the current instruction.  The assumption here is that
@@ -2458,7 +2461,7 @@ static void gen_interrupt(DisasContext *s, int intno,
     gen_jmp_im(cur_eip);
     gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
                                tcg_const_i32(next_eip - cur_eip));
-    s->is_jmp = DISAS_TB_JUMP;
+    s->is_jmp = DISAS_NORETURN;
 }
 
 static void gen_debug(DisasContext *s, target_ulong cur_eip)
@@ -2466,7 +2469,7 @@ static void gen_debug(DisasContext *s, target_ulong cur_eip)
     gen_update_cc_op(s);
     gen_jmp_im(cur_eip);
     gen_helper_debug(cpu_env);
-    s->is_jmp = DISAS_TB_JUMP;
+    s->is_jmp = DISAS_NORETURN;
 }
 
 static void gen_set_hflag(DisasContext *s, uint32_t mask)
@@ -2541,7 +2544,7 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, TCGv jr)
     } else {
         tcg_gen_exit_tb(0);
     }
-    s->is_jmp = DISAS_TB_JUMP;
+    s->is_jmp = DISAS_NORETURN;
 }
 
 static inline void
@@ -2580,7 +2583,6 @@ static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
     set_cc_op(s, CC_OP_DYNAMIC);
     if (s->jmp_opt) {
         gen_goto_tb(s, tb_num, eip);
-        s->is_jmp = DISAS_TB_JUMP;
     } else {
         gen_jmp_im(eip);
         gen_eob(s);
@@ -6942,7 +6944,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
             gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
-            s->is_jmp = DISAS_TB_JUMP;
+            s->is_jmp = DISAS_NORETURN;
         }
         break;
     case 0x9b: /* fwait */
@@ -7187,7 +7189,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
             gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
-            s->is_jmp = DISAS_TB_JUMP;
+            s->is_jmp = DISAS_NORETURN;
         }
         break;
     case 0x100:
@@ -7370,7 +7372,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
                              tcg_const_i32(s->pc - pc_start));
             tcg_gen_exit_tb(0);
-            s->is_jmp = DISAS_TB_JUMP;
+            s->is_jmp = DISAS_NORETURN;
             break;
 
         case 0xd9: /* VMMCALL */
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 04/34] target/arm: Use DISAS_NORETURN
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (2 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 03/34] target/i386: Use generic DISAS_* enumerators Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 21:25   ` Emilio G. Cota
  2017-07-21 22:38   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 05/34] target: [tcg] Use a generic enum for DISAS_ values Richard Henderson
                   ` (30 subsequent siblings)
  34 siblings, 2 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

Fold DISAS_EXC and DISAS_TB_JUMP into DISAS_NORETURN.

In both cases all following code is dead.  In the first
case because we have exited the TB via exception; in the
second case because we have exited the TB via goto_tb
and its associated machinery.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.h     |  8 ++------
 target/arm/translate-a64.c | 37 ++++++++++++++++++++-----------------
 target/arm/translate.c     | 15 ++++++++-------
 3 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index e5da614..08ff0b3 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -124,12 +124,8 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
  * 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
-/* 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_WFI 5
+#define DISAS_SWI 6
 /* WFE */
 #define DISAS_WFE 7
 #define DISAS_HVC 8
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index f9bd1a9..342ff7c 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 = DISAS_NORETURN;
 }
 
 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 = DISAS_NORETURN;
 }
 
 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 = DISAS_NORETURN;
 }
 
 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 = DISAS_NORETURN;
     } 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 = DISAS_NORETURN;
         }
     }
 }
@@ -11316,7 +11316,7 @@ void gen_intermediate_code_a64(CPUState *cs, 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 = DISAS_NORETURN;
             break;
         }
 
@@ -11343,21 +11343,25 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
         gen_io_end();
     }
 
-    if (unlikely(cs->singlestep_enabled || dc->ss_active)
-        && dc->is_jmp != DISAS_EXC) {
+    if (unlikely(cs->singlestep_enabled || dc->ss_active)) {
         /* 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) {
+        switch (dc->is_jmp) {
+        default:
             gen_a64_set_pc_im(dc->pc);
-        }
-        if (cs->singlestep_enabled) {
-            gen_exception_internal(EXCP_DEBUG);
-        } else {
-            gen_step_complete_exception(dc);
+            /* fall through */
+        case DISAS_JUMP:
+            if (cs->singlestep_enabled) {
+                gen_exception_internal(EXCP_DEBUG);
+            } else {
+                gen_step_complete_exception(dc);
+            }
+            break;
+        case DISAS_NORETURN:
+            break;
         }
     } else {
         switch (dc->is_jmp) {
@@ -11374,8 +11378,7 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
         case DISAS_EXIT:
             tcg_gen_exit_tb(0);
             break;
-        case DISAS_TB_JUMP:
-        case DISAS_EXC:
+        case DISAS_NORETURN:
         case DISAS_SWI:
             break;
         case DISAS_WFE:
diff --git a/target/arm/translate.c b/target/arm/translate.c
index e80cc35..fea76fb 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -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 = DISAS_NORETURN;
 }
 
 static void gen_singlestep_exception(DisasContext *s)
@@ -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 = DISAS_NORETURN;
 }
 
 static void gen_exception_insn(DisasContext *s, int offset, int excp,
@@ -1191,7 +1191,7 @@ 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 = DISAS_NORETURN;
 }
 
 /* Force a TB lookup after an instruction that changes the CPU state.  */
@@ -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 = DISAS_NORETURN;
     }
 }
 
@@ -11936,7 +11936,7 @@ void gen_intermediate_code(CPUState *cs, 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 = DISAS_NORETURN;
             break;
         }
 #endif
@@ -12081,6 +12081,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
         default:
             /* FIXME: Single stepping a WFI insn will not halt the CPU. */
             gen_singlestep_exception(dc);
+        case DISAS_NORETURN:
+            break;
         }
     } else {
         /* While branches must always occur at the end of an IT block,
@@ -12105,8 +12107,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
             /* 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 DISAS_NORETURN:
             /* nothing more to generate */
             break;
         case DISAS_WFI:
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 05/34] target: [tcg] Use a generic enum for DISAS_ values
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (3 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 04/34] target/arm: Use DISAS_NORETURN Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 06/34] target/arm: Delay check for magic kernel page Richard Henderson
                   ` (29 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-Id: <150002049746.22386.2316077281615710615.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 include/exec/exec-all.h       |  7 -------
 include/exec/translator.h     | 40 ++++++++++++++++++++++++++++++++++++++++
 target/arm/translate.h        | 23 ++++++++++++++---------
 target/cris/translate.c       |  7 ++++++-
 target/i386/translate.c       |  3 +--
 target/lm32/translate.c       |  6 ++++++
 target/m68k/translate.c       |  7 ++++++-
 target/microblaze/translate.c |  6 ++++++
 target/nios2/translate.c      |  6 ++++++
 target/openrisc/translate.c   |  6 ++++++
 target/s390x/translate.c      |  3 ++-
 target/unicore32/translate.c  |  7 ++++++-
 target/xtensa/translate.c     |  4 ++++
 13 files changed, 103 insertions(+), 22 deletions(-)
 create mode 100644 include/exec/translator.h

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 6760078..ba6c641 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -35,13 +35,6 @@ typedef abi_ulong tb_page_addr_t;
 typedef ram_addr_t tb_page_addr_t;
 #endif
 
-/* is_jmp field values */
-#define DISAS_NEXT    0 /* next instruction can be analyzed */
-#define DISAS_JUMP    1 /* only pc was modified dynamically */
-#define DISAS_UPDATE  2 /* cpu state was modified dynamically */
-#define DISAS_TB_JUMP 3 /* only pc was modified statically */
-#define DISAS_NORETURN 4 /* the tb has already been exited */
-
 #include "qemu/log.h"
 
 void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb);
diff --git a/include/exec/translator.h b/include/exec/translator.h
new file mode 100644
index 0000000..b51b8f8
--- /dev/null
+++ b/include/exec/translator.h
@@ -0,0 +1,40 @@
+/*
+ * Generic intermediate code generation.
+ *
+ * Copyright (C) 2016-2017 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef EXEC__TRANSLATOR_H
+#define EXEC__TRANSLATOR_H
+
+/**
+ * DisasJumpType:
+ * @DISAS_NEXT: Next instruction in program order.
+ * @DISAS_TOO_MANY: Too many instructions translated.
+ * @DISAS_NORETURN: Following code is dead.
+ * @DISAS_TARGET_*: Start of target-specific conditions.
+ *
+ * What instruction to disassemble next.
+ */
+typedef enum DisasJumpType {
+    DISAS_NEXT,
+    DISAS_TOO_MANY,
+    DISAS_NORETURN,
+    DISAS_TARGET_0,
+    DISAS_TARGET_1,
+    DISAS_TARGET_2,
+    DISAS_TARGET_3,
+    DISAS_TARGET_4,
+    DISAS_TARGET_5,
+    DISAS_TARGET_6,
+    DISAS_TARGET_7,
+    DISAS_TARGET_8,
+    DISAS_TARGET_9,
+    DISAS_TARGET_10,
+    DISAS_TARGET_11,
+} DisasJumpType;
+
+#endif  /* EXEC__TRANSLATOR_H */
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 08ff0b3..cca3c37 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -1,6 +1,9 @@
 #ifndef TARGET_ARM_TRANSLATE_H
 #define TARGET_ARM_TRANSLATE_H
 
+#include "exec/translator.h"
+
+
 /* internal defines */
 typedef struct DisasContext {
     target_ulong pc;
@@ -119,26 +122,28 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
     s->insn_start_idx = 0;
 }
 
-/* target-specific extra values for is_jmp */
+/* is_jmp field values */
+#define DISAS_JUMP      DISAS_TARGET_0 /* only pc was modified dynamically */
+#define DISAS_UPDATE    DISAS_TARGET_1 /* cpu state was modified dynamically */
 /* 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 5
-#define DISAS_SWI 6
+#define DISAS_WFI       DISAS_TARGET_2
+#define DISAS_SWI       DISAS_TARGET_3
 /* WFE */
-#define DISAS_WFE 7
-#define DISAS_HVC 8
-#define DISAS_SMC 9
-#define DISAS_YIELD 10
+#define DISAS_WFE       DISAS_TARGET_4
+#define DISAS_HVC       DISAS_TARGET_5
+#define DISAS_SMC       DISAS_TARGET_6
+#define DISAS_YIELD     DISAS_TARGET_7
 /* 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_8
 /* 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_9
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);
diff --git a/target/cris/translate.c b/target/cris/translate.c
index 12b96eb..38a999e 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -31,6 +31,7 @@
 #include "exec/helper-proto.h"
 #include "mmu.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
 #include "crisv32-decode.h"
 
 #include "exec/helper-gen.h"
@@ -50,7 +51,11 @@
 #define BUG() (gen_BUG(dc, __FILE__, __LINE__))
 #define BUG_ON(x) ({if (x) BUG();})
 
-#define DISAS_SWI 5
+/* is_jmp field values */
+#define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
+#define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
+#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
+#define DISAS_SWI     DISAS_TARGET_3
 
 /* Used by the decoder.  */
 #define EXTRACT_FIELD(src, start, end) \
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3ffbf1b..11bc455 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -24,6 +24,7 @@
 #include "exec/exec-all.h"
 #include "tcg-op.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
@@ -31,8 +32,6 @@
 #include "trace-tcg.h"
 #include "exec/log.h"
 
-#define DISAS_TOO_MANY 5
-
 #define PREFIX_REPZ   0x01
 #define PREFIX_REPNZ  0x02
 #define PREFIX_LOCK   0x04
diff --git a/target/lm32/translate.c b/target/lm32/translate.c
index f68f372..65bc9c0 100644
--- a/target/lm32/translate.c
+++ b/target/lm32/translate.c
@@ -22,6 +22,7 @@
 #include "disas/disas.h"
 #include "exec/helper-proto.h"
 #include "exec/exec-all.h"
+#include "exec/translator.h"
 #include "tcg-op.h"
 
 #include "exec/cpu_ldst.h"
@@ -47,6 +48,11 @@
 
 #define MEM_INDEX 0
 
+/* is_jmp field values */
+#define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
+#define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
+#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
+
 static TCGv_env cpu_env;
 static TCGv cpu_R[32];
 static TCGv cpu_pc;
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 9161df2..d980c5e 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -25,6 +25,7 @@
 #include "tcg-op.h"
 #include "qemu/log.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
@@ -173,7 +174,11 @@ static void do_writebacks(DisasContext *s)
     }
 }
 
-#define DISAS_JUMP_NEXT 4
+/* is_jmp field values */
+#define DISAS_JUMP      DISAS_TARGET_0 /* only pc was modified dynamically */
+#define DISAS_UPDATE    DISAS_TARGET_1 /* cpu state was modified dynamically */
+#define DISAS_TB_JUMP   DISAS_TARGET_2 /* only pc was modified statically */
+#define DISAS_JUMP_NEXT DISAS_TARGET_3
 
 #if defined(CONFIG_USER_ONLY)
 #define IS_USER(s) 1
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index a24373c..bd43a42 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -27,6 +27,7 @@
 #include "microblaze-decode.h"
 #include "exec/cpu_ldst.h"
 #include "exec/helper-gen.h"
+#include "exec/translator.h"
 
 #include "trace-tcg.h"
 #include "exec/log.h"
@@ -46,6 +47,11 @@
 #define EXTRACT_FIELD(src, start, end) \
             (((src) >> start) & ((1 << (end - start + 1)) - 1))
 
+/* is_jmp field values */
+#define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
+#define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
+#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
+
 static TCGv env_debug;
 static TCGv_env cpu_env;
 static TCGv cpu_R[32];
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 8b97d65..6b09618 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -29,6 +29,12 @@
 #include "exec/helper-gen.h"
 #include "exec/log.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
+
+/* is_jmp field values */
+#define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
+#define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
+#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
 
 #define INSTRUCTION_FLG(func, flags) { (func), (flags) }
 #define INSTRUCTION(func)                  \
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index a014131..112db1a 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -27,6 +27,7 @@
 #include "qemu/log.h"
 #include "qemu/bitops.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
@@ -37,6 +38,11 @@
 #define LOG_DIS(str, ...) \
     qemu_log_mask(CPU_LOG_TB_IN_ASM, "%08x: " str, dc->pc, ## __VA_ARGS__)
 
+/* is_jmp field values */
+#define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
+#define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
+#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
+
 typedef struct DisasContext {
     TranslationBlock *tb;
     target_ulong pc;
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index cd8c38d..6ed3837 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -76,7 +76,8 @@ typedef struct {
     } u;
 } DisasCompare;
 
-#define DISAS_EXCP 4
+/* is_jmp field values */
+#define DISAS_EXCP DISAS_TARGET_0
 
 #ifdef DEBUG_INLINE_BRANCHES
 static uint64_t inline_branch_hit[CC_OP_MAX];
diff --git a/target/unicore32/translate.c b/target/unicore32/translate.c
index 8f30cff..6c094d5 100644
--- a/target/unicore32/translate.c
+++ b/target/unicore32/translate.c
@@ -16,6 +16,7 @@
 #include "tcg-op.h"
 #include "qemu/log.h"
 #include "exec/cpu_ldst.h"
+#include "exec/translator.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
@@ -45,9 +46,13 @@ typedef struct DisasContext {
 #define IS_USER(s)      1
 #endif
 
+/* is_jmp field values */
+#define DISAS_JUMP    DISAS_TARGET_0 /* only pc was modified dynamically */
+#define DISAS_UPDATE  DISAS_TARGET_1 /* cpu state was modified dynamically */
+#define DISAS_TB_JUMP DISAS_TARGET_2 /* only pc was modified statically */
 /* These instructions trap after executing, so defer them until after the
    conditional executions state has been updated.  */
-#define DISAS_SYSCALL 5
+#define DISAS_SYSCALL DISAS_TARGET_3
 
 static TCGv_env cpu_env;
 static TCGv_i32 cpu_R[32];
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index f3f0ff5..d7bf07e 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -38,6 +38,7 @@
 #include "sysemu/sysemu.h"
 #include "exec/cpu_ldst.h"
 #include "exec/semihost.h"
+#include "exec/translator.h"
 
 #include "exec/helper-proto.h"
 #include "exec/helper-gen.h"
@@ -46,6 +47,9 @@
 #include "exec/log.h"
 
 
+/* is_jmp field values */
+#define DISAS_UPDATE  DISAS_TARGET_0 /* cpu state was modified dynamically */
+
 typedef struct DisasContext {
     const XtensaConfig *config;
     TranslationBlock *tb;
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 06/34] target/arm: Delay check for magic kernel page
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (4 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 05/34] target: [tcg] Use a generic enum for DISAS_ values Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 21:27   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 07/34] target/arm: Set is_jmp properly after single-stepping Richard Henderson
                   ` (28 subsequent siblings)
  34 siblings, 1 reply; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

There's nothing magic about the exception that we generate in order
to execute the magic kernel page.  We can and should allow gdb to
set a breakpoint at this location.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index fea76fb..2ae68ce 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11930,17 +11930,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
                            0);
         num_insns++;
 
-#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 = DISAS_NORETURN;
-            break;
-        }
-#endif
-
         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
             CPUBreakpoint *bp;
             QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
@@ -11972,6 +11961,17 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
             gen_io_start();
         }
 
+#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 = DISAS_NORETURN;
+            break;
+        }
+#endif
+
         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
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 07/34] target/arm: Set is_jmp properly after single-stepping
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (5 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 06/34] target/arm: Delay check for magic kernel page Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 21:37   ` Emilio G. Cota
  2017-07-21 22:39   ` Lluís Vilanova
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 08/34] tcg: Add generic translation framework Richard Henderson
                   ` (27 subsequent siblings)
  34 siblings, 2 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

We have generated an exception, so use DISAS_NORETURN.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate-a64.c | 1 +
 target/arm/translate.c     | 4 +++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 342ff7c..657684b 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11285,6 +11285,7 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
                         dc->is_jmp = DISAS_UPDATE;
                     } else {
                         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
+                        dc->is_jmp = DISAS_NORETURN;
                         /* The address covered by the breakpoint must be
                            included in [tb->pc, tb->pc + tb->size) in order
                            to for it to be properly cleared -- thus we
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 2ae68ce..83e5491 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11942,6 +11942,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
                         dc->is_jmp = DISAS_UPDATE;
                     } else {
                         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
+                        dc->is_jmp = DISAS_NORETURN;
                         /* The address covered by the breakpoint must be
                            included in [tb->pc, tb->pc + tb->size) in order
                            to for it to be properly cleared -- thus we
@@ -11986,7 +11987,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
             assert(num_insns == 1);
             gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
                           default_exception_el(dc));
-            goto done_generating;
+            dc->is_jmp = DISAS_NORETURN;
+            break;
         }
 
         if (dc->thumb) {
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 08/34] tcg: Add generic translation framework
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (6 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 07/34] target/arm: Set is_jmp properly after single-stepping Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 22:49   ` Lluís Vilanova
  2017-07-21 23:38   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 09/34] target/i386: [tcg] Port to DisasContextBase Richard Henderson
                   ` (26 subsequent siblings)
  34 siblings, 2 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Message-Id: <150002073981.22386.9870422422367410100.stgit@frigg.lan>
[rth: Moved max_insns adjustment from tb_start to init_disas_context.
Removed pc_next return from translate_insn.
Removed tcg_check_temp_count from generic loop.
Moved gen_io_end to exactly match gen_io_start.
Use qemu_log instead of error_report for temporary leaks.
Moved TB size/icount assignments before disas_log.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 include/exec/translator.h | 101 +++++++++++++++++++++++++++++++++++
 accel/tcg/translator.c    | 133 ++++++++++++++++++++++++++++++++++++++++++++++
 accel/tcg/Makefile.objs   |   1 +
 3 files changed, 235 insertions(+)
 create mode 100644 accel/tcg/translator.c

diff --git a/include/exec/translator.h b/include/exec/translator.h
index b51b8f8..aa84376 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -10,6 +10,19 @@
 #ifndef EXEC__TRANSLATOR_H
 #define EXEC__TRANSLATOR_H
 
+/*
+ * Include this header from a target-specific file, and add a
+ *
+ *     DisasContextBase base;
+ *
+ * member in your target-specific DisasContext.
+ */
+
+
+#include "exec/exec-all.h"
+#include "tcg/tcg.h"
+
+
 /**
  * DisasJumpType:
  * @DISAS_NEXT: Next instruction in program order.
@@ -37,4 +50,92 @@ typedef enum DisasJumpType {
     DISAS_TARGET_11,
 } 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 the target-specific portions of DisasContext struct.
+ *      The generic DisasContextBase has already been initialized.
+ *      Return max_insns, modified as necessary by db->tb->flags.
+ *
+ * @tb_start:
+ *      Emit any code required before the start of the main loop,
+ *      after the generic gen_tb_start().
+ *
+ * @insn_start:
+ *      Emit the tcg_gen_insn_start opcode.
+ *
+ * @breakpoint_check:
+ *      When called, the breakpoint has already been checked to match the PC,
+ *      but the target may decide the breakpoint missed the address
+ *      (e.g., due to conditions encoded in their flags).  Return true to
+ *      indicate that the breakpoint did hit, in which case no more breakpoints
+ *      are checked.  If the breakpoint did hit, emit any code required to
+ *      signal the exception, and set db->is_jmp as necessary to terminate
+ *      the main loop.
+ *
+ * @translate_insn:
+ *      Disassemble one instruction and set db->pc_next for the start
+ *      of the following instruction.  Set db->is_jmp as necessary to
+ *      terminate the main loop.
+ *
+ * @tb_stop:
+ *      Emit any opcodes required to exit the TB, based on db->is_jmp.
+ *
+ * @disas_log:
+ *      Print instruction disassembly to log.
+ */
+typedef struct TranslatorOps {
+    int (*init_disas_context)(DisasContextBase *db, CPUState *cpu,
+                              int max_insns);
+    void (*tb_start)(DisasContextBase *db, CPUState *cpu);
+    void (*insn_start)(DisasContextBase *db, CPUState *cpu);
+    bool (*breakpoint_check)(DisasContextBase *db, CPUState *cpu,
+                             const CPUBreakpoint *bp);
+    void (*translate_insn)(DisasContextBase *db, CPUState *cpu);
+    void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
+    void (*disas_log)(const DisasContextBase *db, CPUState *cpu);
+} TranslatorOps;
+
+/**
+ * translator_loop:
+ * @ops: Target-specific operations.
+ * @db: Disassembly context.
+ * @cpu: Target vCPU.
+ * @tb: Translation block.
+ *
+ * Generic translator loop.
+ *
+ * Translation will stop in the following cases (in order):
+ * - When set by #TranslatorOps::insn_start.
+ * - When set by #TranslatorOps::translate_insn.
+ * - When the TCG operation buffer is full.
+ * - When single-stepping is enabled (system-wide or on the current vCPU).
+ * - When too many instructions have been translated.
+ */
+void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
+                     CPUState *cpu, TranslationBlock *tb);
+
+void translator_loop_temp_check(DisasContextBase *db);
+
 #endif  /* EXEC__TRANSLATOR_H */
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
new file mode 100644
index 0000000..cb7ba96
--- /dev/null
+++ b/accel/tcg/translator.c
@@ -0,0 +1,133 @@
+/*
+ * Generic intermediate code generation.
+ *
+ * Copyright (C) 2016-2017 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "cpu.h"
+#include "tcg/tcg.h"
+#include "tcg/tcg-op.h"
+#include "exec/exec-all.h"
+#include "exec/gen-icount.h"
+#include "exec/log.h"
+#include "exec/translator.h"
+
+void translator_loop_temp_check(DisasContextBase *db)
+{
+    if (tcg_check_temp_count()) {
+        qemu_log("warning: TCG temporary leaks before "
+                 TARGET_FMT_lx "\n", db->pc_next);
+    }
+}
+
+void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
+                     CPUState *cpu, TranslationBlock *tb)
+{
+    int max_insns;
+
+    /* Initialize DisasContext */
+    db->tb = tb;
+    db->pc_first = tb->pc;
+    db->pc_next = db->pc_first;
+    db->is_jmp = DISAS_NEXT;
+    db->num_insns = 0;
+    db->singlestep_enabled = cpu->singlestep_enabled;
+
+    /* 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;
+    }
+
+    max_insns = ops->init_disas_context(db, cpu, max_insns);
+    tcg_debug_assert(db->is_jmp == DISAS_NEXT);  /* no early exit */
+
+    /* Reset the temp count so that we can identify leaks */
+    tcg_clear_temp_count();
+
+    /* Start translating.  */
+    gen_tb_start(db->tb);
+    ops->tb_start(db, cpu);
+    tcg_debug_assert(db->is_jmp == DISAS_NEXT);  /* no early exit */
+
+    while (true) {
+        db->num_insns++;
+        ops->insn_start(db, cpu);
+        tcg_debug_assert(db->is_jmp == DISAS_NEXT);  /* no early exit */
+
+        /* Pass breakpoint hits to target for further processing */
+        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
+            CPUBreakpoint *bp;
+            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
+                if (bp->pc == db->pc_next) {
+                    if (ops->breakpoint_check(db, cpu, bp)) {
+                        break;
+                    }
+                }
+            }
+            /* The breakpoint_check hook may use DISAS_TOO_MANY to indicate
+               that only one more instruction is to be executed.  Otherwise
+               it should use DISAS_NORETURN when generating an exception,
+               but may use a DISAS_TARGET_* value for Something Else.  */
+            if (db->is_jmp > DISAS_TOO_MANY) {
+                break;
+            }
+        }
+
+        /* Disassemble one instruction.  The translate_insn hook should
+           update db->pc_next and db->is_jmp to indicate what should be
+           done next -- either exiting this loop or locate the start of
+           the next instruction.  */
+        if (db->num_insns == max_insns && (db->tb->cflags & CF_LAST_IO)) {
+            /* Accept I/O on the last instruction.  */
+            gen_io_start();
+            ops->translate_insn(db, cpu);
+            gen_io_end();
+        } else {
+            ops->translate_insn(db, cpu);
+        }
+
+        /* Stop translation if translate_insn so indicated.  */
+        if (db->is_jmp != DISAS_NEXT) {
+            break;
+        }
+
+        /* Stop translation if the output buffer is full,
+           or we have executed all of the allowed instructions.  */
+        if (tcg_op_buf_full() || db->num_insns >= max_insns) {
+            db->is_jmp = DISAS_TOO_MANY;
+            break;
+        }
+    }
+
+    /* Emit code to exit the TB, as indicated by db->is_jmp.  */
+    ops->tb_stop(db, cpu);
+    gen_tb_end(db->tb, db->num_insns);
+
+    /* The disas_log hook may use these values rather than recompute.  */
+    db->tb->size = db->pc_next - db->pc_first;
+    db->tb->icount = db->num_insns;
+
+#ifdef DEBUG_DISAS
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
+        && qemu_log_in_addr_range(db->pc_first)) {
+        qemu_log_lock();
+        qemu_log("----------------\n");
+        ops->disas_log(db, cpu);
+        qemu_log("\n");
+        qemu_log_unlock();
+    }
+#endif
+}
diff --git a/accel/tcg/Makefile.objs b/accel/tcg/Makefile.objs
index 70cd474..22642e6 100644
--- a/accel/tcg/Makefile.objs
+++ b/accel/tcg/Makefile.objs
@@ -1,3 +1,4 @@
 obj-$(CONFIG_SOFTMMU) += tcg-all.o
 obj-$(CONFIG_SOFTMMU) += cputlb.o
 obj-y += cpu-exec.o cpu-exec-common.o translate-all.o
+obj-y += translator.o
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 09/34] target/i386: [tcg] Port to DisasContextBase
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (7 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 08/34] tcg: Add generic translation framework Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 10/34] target/i386: [tcg] Port to init_disas_context Richard Henderson
                   ` (25 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002098212.22386.17313318023406046314.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/i386/translate.c | 140 ++++++++++++++++++++++++------------------------
 1 file changed, 69 insertions(+), 71 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 11bc455..7825593 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -95,6 +95,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 +104,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 +124,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 +1117,7 @@ static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
 
 static inline void gen_ins(DisasContext *s, TCGMemOp ot)
 {
-    if (s->tb->cflags & CF_USE_ICOUNT) {
+    if (s->base.tb->cflags & CF_USE_ICOUNT) {
         gen_io_start();
     }
     gen_string_movl_A0_EDI(s);
@@ -1134,14 +1132,14 @@ static inline void gen_ins(DisasContext *s, TCGMemOp ot)
     gen_op_movl_T0_Dshift(ot);
     gen_op_add_reg_T0(s->aflag, R_EDI);
     gen_bpt_io(s, cpu_tmp2_i32, ot);
-    if (s->tb->cflags & CF_USE_ICOUNT) {
+    if (s->base.tb->cflags & CF_USE_ICOUNT) {
         gen_io_end();
     }
 }
 
 static inline void gen_outs(DisasContext *s, TCGMemOp ot)
 {
-    if (s->tb->cflags & CF_USE_ICOUNT) {
+    if (s->base.tb->cflags & CF_USE_ICOUNT) {
         gen_io_start();
     }
     gen_string_movl_A0_ESI(s);
@@ -1154,7 +1152,7 @@ static inline void gen_outs(DisasContext *s, TCGMemOp ot)
     gen_op_movl_T0_Dshift(ot);
     gen_op_add_reg_T0(s->aflag, R_ESI);
     gen_bpt_io(s, cpu_tmp2_i32, ot);
-    if (s->tb->cflags & CF_USE_ICOUNT) {
+    if (s->base.tb->cflags & CF_USE_ICOUNT) {
         gen_io_end();
     }
 }
@@ -2137,7 +2135,7 @@ static inline int insn_const_size(TCGMemOp ot)
 static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
 {
 #ifndef CONFIG_USER_ONLY
-    return (pc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK) ||
+    return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) ||
            (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
 #else
     return true;
@@ -2152,8 +2150,8 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
         /* jump to same page: we can use a direct jump */
         tcg_gen_goto_tb(tb_num);
         gen_jmp_im(eip);
-        tcg_gen_exit_tb((uintptr_t)s->tb + tb_num);
-        s->is_jmp = DISAS_NORETURN;
+        tcg_gen_exit_tb((uintptr_t)s->base.tb + tb_num);
+        s->base.is_jmp = DISAS_NORETURN;
     } else {
         /* jump to another page */
         gen_jmp_im(eip);
@@ -2244,12 +2242,12 @@ 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_TOO_MANY;
+            s->base.is_jmp = DISAS_TOO_MANY;
         }
     } else {
         gen_op_movl_seg_T0_vm(seg_reg);
         if (seg_reg == R_SS) {
-            s->is_jmp = DISAS_TOO_MANY;
+            s->base.is_jmp = DISAS_TOO_MANY;
         }
     }
 }
@@ -2422,7 +2420,7 @@ static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
     gen_update_cc_op(s);
     gen_jmp_im(cur_eip);
     gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
-    s->is_jmp = DISAS_NORETURN;
+    s->base.is_jmp = DISAS_NORETURN;
 }
 
 /* Generate #UD for the current instruction.  The assumption here is that
@@ -2460,7 +2458,7 @@ static void gen_interrupt(DisasContext *s, int intno,
     gen_jmp_im(cur_eip);
     gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
                                tcg_const_i32(next_eip - cur_eip));
-    s->is_jmp = DISAS_NORETURN;
+    s->base.is_jmp = DISAS_NORETURN;
 }
 
 static void gen_debug(DisasContext *s, target_ulong cur_eip)
@@ -2468,7 +2466,7 @@ static void gen_debug(DisasContext *s, target_ulong cur_eip)
     gen_update_cc_op(s);
     gen_jmp_im(cur_eip);
     gen_helper_debug(cpu_env);
-    s->is_jmp = DISAS_NORETURN;
+    s->base.is_jmp = DISAS_NORETURN;
 }
 
 static void gen_set_hflag(DisasContext *s, uint32_t mask)
@@ -2524,10 +2522,10 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, TCGv jr)
         gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
     }
 
-    if (s->tb->flags & HF_RF_MASK) {
+    if (s->base.tb->flags & HF_RF_MASK) {
         gen_helper_reset_rf(cpu_env);
     }
-    if (s->singlestep_enabled) {
+    if (s->base.singlestep_enabled) {
         gen_helper_debug(cpu_env);
     } else if (recheck_tf) {
         gen_helper_rechecking_single_step(cpu_env);
@@ -2543,7 +2541,7 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, TCGv jr)
     } else {
         tcg_gen_exit_tb(0);
     }
-    s->is_jmp = DISAS_NORETURN;
+    s->base.is_jmp = DISAS_NORETURN;
 }
 
 static inline void
@@ -4416,7 +4414,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
     }
 }
 
-/* convert one instruction. s->is_jmp is set if the translation must
+/* convert one instruction. s->base.is_jmp is set if the translation must
    be stopped. Return the next pc value */
 static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                                target_ulong pc_start)
@@ -5376,7 +5374,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_movl_seg_T0(s, reg);
         gen_pop_update(s, ot);
         /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp.  */
-        if (s->is_jmp) {
+        if (s->base.is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             if (reg == R_SS) {
                 s->tf = 0;
@@ -5391,7 +5389,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         ot = gen_pop_T0(s);
         gen_movl_seg_T0(s, (b >> 3) & 7);
         gen_pop_update(s, ot);
-        if (s->is_jmp) {
+        if (s->base.is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             gen_eob(s);
         }
@@ -5442,7 +5440,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
         gen_movl_seg_T0(s, reg);
         /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp.  */
-        if (s->is_jmp) {
+        if (s->base.is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             if (reg == R_SS) {
                 s->tf = 0;
@@ -5651,7 +5649,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         gen_movl_seg_T0(s, op);
         /* then put the data */
         gen_op_mov_reg_v(ot, reg, cpu_T1);
-        if (s->is_jmp) {
+        if (s->base.is_jmp) {
             gen_jmp_im(s->pc - s->cs_base);
             gen_eob(s);
         }
@@ -6307,7 +6305,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
             gen_ins(s, ot);
-            if (s->tb->cflags & CF_USE_ICOUNT) {
+            if (s->base.tb->cflags & CF_USE_ICOUNT) {
                 gen_jmp(s, s->pc - s->cs_base);
             }
         }
@@ -6322,7 +6320,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
         } else {
             gen_outs(s, ot);
-            if (s->tb->cflags & CF_USE_ICOUNT) {
+            if (s->base.tb->cflags & CF_USE_ICOUNT) {
                 gen_jmp(s, s->pc - s->cs_base);
             }
         }
@@ -6338,14 +6336,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         tcg_gen_movi_tl(cpu_T0, val);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_start();
 	}
         tcg_gen_movi_i32(cpu_tmp2_i32, val);
         gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
         gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
         gen_bpt_io(s, cpu_tmp2_i32, ot);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6359,14 +6357,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                      svm_is_rep(prefixes));
         gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
 
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_start();
 	}
         tcg_gen_movi_i32(cpu_tmp2_i32, val);
         tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
         gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
         gen_bpt_io(s, cpu_tmp2_i32, ot);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6377,14 +6375,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
         tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
         gen_check_io(s, ot, pc_start - s->cs_base,
                      SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_start();
 	}
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
         gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
         gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
         gen_bpt_io(s, cpu_tmp2_i32, ot);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6397,14 +6395,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                      svm_is_rep(prefixes));
         gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
 
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_start();
 	}
         tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
         tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
         gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
         gen_bpt_io(s, cpu_tmp2_i32, ot);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -6943,7 +6941,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_NORETURN;
+            s->base.is_jmp = DISAS_NORETURN;
         }
         break;
     case 0x9b: /* fwait */
@@ -7112,11 +7110,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
     case 0x131: /* rdtsc */
         gen_update_cc_op(s);
         gen_jmp_im(pc_start - s->cs_base);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_start();
 	}
         gen_helper_rdtsc(cpu_env);
-        if (s->tb->cflags & CF_USE_ICOUNT) {
+        if (s->base.tb->cflags & CF_USE_ICOUNT) {
             gen_io_end();
             gen_jmp(s, s->pc - s->cs_base);
         }
@@ -7188,7 +7186,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_NORETURN;
+            s->base.is_jmp = DISAS_NORETURN;
         }
         break;
     case 0x100:
@@ -7371,7 +7369,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_NORETURN;
+            s->base.is_jmp = DISAS_NORETURN;
             break;
 
         case 0xd9: /* VMMCALL */
@@ -7571,11 +7569,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             }
             gen_update_cc_op(s);
             gen_jmp_im(pc_start - s->cs_base);
-            if (s->tb->cflags & CF_USE_ICOUNT) {
+            if (s->base.tb->cflags & CF_USE_ICOUNT) {
                 gen_io_start();
             }
             gen_helper_rdtscp(cpu_env);
-            if (s->tb->cflags & CF_USE_ICOUNT) {
+            if (s->base.tb->cflags & CF_USE_ICOUNT) {
                 gen_io_end();
                 gen_jmp(s, s->pc - s->cs_base);
             }
@@ -7940,24 +7938,24 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
                 gen_update_cc_op(s);
                 gen_jmp_im(pc_start - s->cs_base);
                 if (b & 2) {
-                    if (s->tb->cflags & CF_USE_ICOUNT) {
+                    if (s->base.tb->cflags & CF_USE_ICOUNT) {
                         gen_io_start();
                     }
                     gen_op_mov_v_reg(ot, cpu_T0, rm);
                     gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
                                          cpu_T0);
-                    if (s->tb->cflags & CF_USE_ICOUNT) {
+                    if (s->base.tb->cflags & CF_USE_ICOUNT) {
                         gen_io_end();
                     }
                     gen_jmp_im(s->pc - s->cs_base);
                     gen_eob(s);
                 } else {
-                    if (s->tb->cflags & CF_USE_ICOUNT) {
+                    if (s->base.tb->cflags & CF_USE_ICOUNT) {
                         gen_io_start();
                     }
                     gen_helper_read_crN(cpu_T0, cpu_env, tcg_const_i32(reg));
                     gen_op_mov_reg_v(ot, rm, cpu_T0);
-                    if (s->tb->cflags & CF_USE_ICOUNT) {
+                    if (s->base.tb->cflags & CF_USE_ICOUNT) {
                         gen_io_end();
                     }
                 }
@@ -8383,15 +8381,13 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
     CPUX86State *env = cs->env_ptr;
     DisasContext dc1, *dc = &dc1;
-    target_ulong pc_ptr;
     uint32_t flags;
-    target_ulong pc_start;
     target_ulong cs_base;
     int num_insns;
     int max_insns;
 
     /* generate intermediate code */
-    pc_start = tb->pc;
+    dc->base.pc_first = tb->pc;
     cs_base = tb->cs_base;
     flags = tb->flags;
 
@@ -8404,11 +8400,11 @@ void gen_intermediate_code(CPUState *cs, 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->base.singlestep_enabled = cs->singlestep_enabled;
     dc->cc_op = CC_OP_DYNAMIC;
     dc->cc_op_dirty = false;
     dc->cs_base = cs_base;
-    dc->tb = tb;
+    dc->base.tb = tb;
     dc->popl_esp_hack = 0;
     /* select memory access functions */
     dc->mem_index = 0;
@@ -8458,8 +8454,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
     cpu_ptr1 = tcg_temp_new_ptr();
     cpu_cc_srcT = tcg_temp_local_new();
 
-    dc->is_jmp = DISAS_NEXT;
-    pc_ptr = pc_start;
+    dc->base.is_jmp = DISAS_NEXT;
+    dc->base.pc_next = dc->base.pc_first;
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
@@ -8471,37 +8467,38 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 
     gen_tb_start(tb);
     for(;;) {
-        tcg_gen_insn_start(pc_ptr, dc->cc_op);
+        tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
         num_insns++;
 
         /* If RF is set, suppress an internally generated breakpoint.  */
-        if (unlikely(cpu_breakpoint_test(cs, pc_ptr,
+        if (unlikely(cpu_breakpoint_test(cs, dc->base.pc_next,
                                          tb->flags & HF_RF_MASK
                                          ? BP_GDB : BP_ANY))) {
-            gen_debug(dc, pc_ptr - dc->cs_base);
+            gen_debug(dc, dc->base.pc_next - dc->cs_base);
             /* The address covered by the breakpoint must be included in
                [tb->pc, tb->pc + tb->size) in order to for it to be
                properly cleared -- thus we increment the PC here so that
                the logic setting tb->size below does the right thing.  */
-            pc_ptr += 1;
+            dc->base.pc_next += 1;
             goto done_generating;
         }
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
         }
 
-        pc_ptr = disas_insn(env, dc, pc_ptr);
+        dc->base.pc_next = disas_insn(env, dc, dc->base.pc_next);
         /* stop translation if indicated */
-        if (dc->is_jmp)
+        if (dc->base.is_jmp) {
             break;
+        }
         /* if single step mode, we generate only one instruction and
            generate an exception */
         /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
            the flag and abort the translation to give the irqs a
            change to be happen */
-        if (dc->tf || dc->singlestep_enabled ||
+        if (dc->tf || dc->base.singlestep_enabled ||
             (flags & HF_INHIBIT_IRQ_MASK)) {
-            gen_jmp_im(pc_ptr - dc->cs_base);
+            gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
@@ -8512,23 +8509,23 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
            because an exception hasn't stopped this code.
          */
         if ((tb->cflags & CF_USE_ICOUNT)
-            && ((pc_ptr & TARGET_PAGE_MASK)
-                != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
-                || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
-            gen_jmp_im(pc_ptr - dc->cs_base);
+            && ((dc->base.pc_next & TARGET_PAGE_MASK)
+                != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
+                || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) {
+            gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
         /* if too long translation, stop generation too */
         if (tcg_op_buf_full() ||
-            (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
+            (dc->base.pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32) ||
             num_insns >= max_insns) {
-            gen_jmp_im(pc_ptr - dc->cs_base);
+            gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
         if (singlestep) {
-            gen_jmp_im(pc_ptr - dc->cs_base);
+            gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
@@ -8540,24 +8537,25 @@ done_generating:
 
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
-        && qemu_log_in_addr_range(pc_start)) {
+        && qemu_log_in_addr_range(dc->base.pc_first)) {
         int disas_flags;
         qemu_log_lock();
         qemu_log("----------------\n");
-        qemu_log("IN: %s\n", lookup_symbol(pc_start));
+        qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
 #ifdef TARGET_X86_64
         if (dc->code64)
             disas_flags = 2;
         else
 #endif
             disas_flags = !dc->code32;
-        log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags);
+        log_target_disas(cs, dc->base.pc_first, dc->base.pc_next - dc->base.pc_first,
+                         disas_flags);
         qemu_log("\n");
         qemu_log_unlock();
     }
 #endif
 
-    tb->size = pc_ptr - pc_start;
+    tb->size = dc->base.pc_next - dc->base.pc_first;
     tb->icount = num_insns;
 }
 
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 10/34] target/i386: [tcg] Port to init_disas_context
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (8 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 09/34] target/i386: [tcg] Port to DisasContextBase Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 21:54   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 11/34] target/i386: [tcg] Port to insn_start Richard Henderson
                   ` (24 subsequent siblings)
  34 siblings, 1 reply; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002122448.22386.16854673576827449259.stgit@frigg.lan>
[rth: Adjust for max_insns interface change.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/i386/translate.c | 46 +++++++++++++++++++++++++++-------------------
 1 file changed, 27 insertions(+), 19 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 7825593..651abca 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8376,20 +8376,13 @@ void tcg_x86_init(void)
     }
 }
 
-/* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
+static int i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu,
+                                      int max_insns)
 {
-    CPUX86State *env = cs->env_ptr;
-    DisasContext dc1, *dc = &dc1;
-    uint32_t flags;
-    target_ulong cs_base;
-    int num_insns;
-    int max_insns;
-
-    /* generate intermediate code */
-    dc->base.pc_first = tb->pc;
-    cs_base = tb->cs_base;
-    flags = tb->flags;
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    CPUX86State *env = cpu->env_ptr;
+    uint32_t flags = dc->base.tb->flags;
+    target_ulong cs_base = dc->base.tb->cs_base;
 
     dc->pe = (flags >> HF_PE_SHIFT) & 1;
     dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
@@ -8400,11 +8393,9 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
     dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
     dc->iopl = (flags >> IOPL_SHIFT) & 3;
     dc->tf = (flags >> TF_SHIFT) & 1;
-    dc->base.singlestep_enabled = cs->singlestep_enabled;
     dc->cc_op = CC_OP_DYNAMIC;
     dc->cc_op_dirty = false;
     dc->cs_base = cs_base;
-    dc->base.tb = tb;
     dc->popl_esp_hack = 0;
     /* select memory access functions */
     dc->mem_index = 0;
@@ -8422,7 +8413,7 @@ void gen_intermediate_code(CPUState *cs, 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 || dc->base.singlestep_enabled ||
                     (flags & HF_INHIBIT_IRQ_MASK));
     /* Do not optimize repz jumps at all in icount mode, because
        rep movsS instructions are execured with different paths
@@ -8434,7 +8425,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
        record/replay modes and there will always be an
        additional step for ecx=0 when icount is enabled.
      */
-    dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT);
+    dc->repz_opt = !dc->jmp_opt && !(dc->base.tb->cflags & CF_USE_ICOUNT);
 #if 0
     /* check addseg logic */
     if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
@@ -8454,9 +8445,24 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
     cpu_ptr1 = tcg_temp_new_ptr();
     cpu_cc_srcT = tcg_temp_local_new();
 
+    return max_insns;
+}
+
+/* generate intermediate code for basic block 'tb'.  */
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
+{
+    CPUX86State *env = cs->env_ptr;
+    DisasContext dc1, *dc = &dc1;
+    int num_insns;
+    int max_insns;
+
+    /* generate intermediate code */
+    dc->base.singlestep_enabled = cs->singlestep_enabled;
+    dc->base.tb = tb;
     dc->base.is_jmp = DISAS_NEXT;
+    dc->base.pc_first = tb->pc;
     dc->base.pc_next = dc->base.pc_first;
-    num_insns = 0;
+
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
         max_insns = CF_COUNT_MASK;
@@ -8464,7 +8470,9 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
     if (max_insns > TCG_MAX_INSNS) {
         max_insns = TCG_MAX_INSNS;
     }
+    max_insns = i386_tr_init_disas_context(&dc->base, cs, max_insns);
 
+    num_insns = 0;
     gen_tb_start(tb);
     for(;;) {
         tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
@@ -8497,7 +8505,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
            the flag and abort the translation to give the irqs a
            change to be happen */
         if (dc->tf || dc->base.singlestep_enabled ||
-            (flags & HF_INHIBIT_IRQ_MASK)) {
+            (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
             gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 11/34] target/i386: [tcg] Port to insn_start
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (9 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 10/34] target/i386: [tcg] Port to init_disas_context Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 12/34] target/i386: [tcg] Port to breakpoint_check Richard Henderson
                   ` (23 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002146647.22386.13380064201042141261.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/i386/translate.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 651abca..6e1243a 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8448,6 +8448,13 @@ static int i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu,
     return max_insns;
 }
 
+static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
@@ -8475,7 +8482,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
     num_insns = 0;
     gen_tb_start(tb);
     for(;;) {
-        tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
+        i386_tr_insn_start(&dc->base, cs);
         num_insns++;
 
         /* If RF is set, suppress an internally generated breakpoint.  */
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 12/34] target/i386: [tcg] Port to breakpoint_check
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (10 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 11/34] target/i386: [tcg] Port to insn_start Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 13/34] target/i386: [tcg] Port to translate_insn Richard Henderson
                   ` (22 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Message-Id: <150002170871.22386.2172835658104140576.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/i386/translate.c | 46 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 34 insertions(+), 12 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 6e1243a..a009710 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8455,6 +8455,26 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
     tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
 }
 
+static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
+                                     const CPUBreakpoint *bp)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    /* If RF is set, suppress an internally generated breakpoint.  */
+    int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
+    if (bp->flags & flags) {
+        gen_debug(dc, dc->base.pc_next - dc->cs_base);
+        dc->base.is_jmp = DISAS_NORETURN;
+        /* The address covered by the breakpoint must be included in
+           [tb->pc, tb->pc + tb->size) in order to for it to be
+           properly cleared -- thus we increment the PC here so that
+           the logic setting tb->size below does the right thing.  */
+        dc->base.pc_next += 1;
+        return true;
+    } else {
+        return false;
+    }
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
@@ -8485,18 +8505,21 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
         i386_tr_insn_start(&dc->base, cs);
         num_insns++;
 
-        /* If RF is set, suppress an internally generated breakpoint.  */
-        if (unlikely(cpu_breakpoint_test(cs, dc->base.pc_next,
-                                         tb->flags & HF_RF_MASK
-                                         ? BP_GDB : BP_ANY))) {
-            gen_debug(dc, dc->base.pc_next - dc->cs_base);
-            /* The address covered by the breakpoint must be included in
-               [tb->pc, tb->pc + tb->size) in order to for it to be
-               properly cleared -- thus we increment the PC here so that
-               the logic setting tb->size below does the right thing.  */
-            dc->base.pc_next += 1;
-            goto done_generating;
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            CPUBreakpoint *bp;
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
+                if (bp->pc == dc->base.pc_next) {
+                    if (i386_tr_breakpoint_check(&dc->base, cs, bp)) {
+                        break;
+                    }
+                }
+            }
+
+            if (dc->base.is_jmp == DISAS_NORETURN) {
+                break;
+            }
         }
+
         if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
             gen_io_start();
         }
@@ -8547,7 +8570,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
     }
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
-done_generating:
     gen_tb_end(tb, num_insns);
 
 #ifdef DEBUG_DISAS
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 13/34] target/i386: [tcg] Port to translate_insn
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (11 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 12/34] target/i386: [tcg] Port to breakpoint_check Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 14/34] target/i386: [tcg] Port to tb_stop Richard Henderson
                   ` (21 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Message-Id: <150002195074.22386.16195894320027075398.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/i386/translate.c | 66 +++++++++++++++++++++++++++++++------------------
 1 file changed, 42 insertions(+), 24 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index a009710..d350699 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4416,15 +4416,16 @@ 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(DisasContext *s, CPUState *cpu)
 {
+    CPUX86State *env = cpu->env_ptr;
     int b, prefixes;
     int shift;
     TCGMemOp ot, aflag, dflag;
     int modrm, reg, rm, mod, op, opreg, val;
     target_ulong next_eip, tval;
     int rex_w, rex_r;
+    target_ulong pc_start = s->base.pc_next;
 
     s->pc_start = s->pc = pc_start;
     prefixes = 0;
@@ -8475,10 +8476,46 @@ static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
     }
 }
 
+static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    target_ulong pc_next = disas_insn(dc, cpu);
+
+    if (dc->tf || (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
+        /* if single step mode, we generate only one instruction and
+           generate an exception */
+        /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
+           the flag and abort the translation to give the irqs a
+           chance to happen */
+        gen_jmp_im(pc_next - dc->cs_base);
+        gen_eob(dc);
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    } else if ((dc->base.tb->cflags & CF_USE_ICOUNT)
+               && ((dc->base.pc_next & TARGET_PAGE_MASK)
+                   != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1)
+                       & TARGET_PAGE_MASK)
+                   || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) {
+        /* Do not cross the boundary of the pages in icount mode,
+           it can cause an exception. Do it only when boundary is
+           crossed by the first instruction in the block.
+           If current instruction already crossed the bound - it's ok,
+           because an exception hasn't stopped this code.
+         */
+        gen_jmp_im(pc_next - dc->cs_base);
+        gen_eob(dc);
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
+        gen_jmp_im(pc_next - dc->cs_base);
+        gen_eob(dc);
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    }
+
+    dc->base.pc_next = pc_next;
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
-    CPUX86State *env = cs->env_ptr;
     DisasContext dc1, *dc = &dc1;
     int num_insns;
     int max_insns;
@@ -8524,39 +8561,20 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
             gen_io_start();
         }
 
-        dc->base.pc_next = disas_insn(env, dc, dc->base.pc_next);
+        i386_tr_translate_insn(&dc->base, cs);
         /* stop translation if indicated */
         if (dc->base.is_jmp) {
             break;
         }
         /* if single step mode, we generate only one instruction and
            generate an exception */
-        /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
-           the flag and abort the translation to give the irqs a
-           change to be happen */
-        if (dc->tf || dc->base.singlestep_enabled ||
-            (dc->base.tb->flags & HF_INHIBIT_IRQ_MASK)) {
-            gen_jmp_im(dc->base.pc_next - dc->cs_base);
-            gen_eob(dc);
-            break;
-        }
-        /* Do not cross the boundary of the pages in icount mode,
-           it can cause an exception. Do it only when boundary is
-           crossed by the first instruction in the block.
-           If current instruction already crossed the bound - it's ok,
-           because an exception hasn't stopped this code.
-         */
-        if ((tb->cflags & CF_USE_ICOUNT)
-            && ((dc->base.pc_next & TARGET_PAGE_MASK)
-                != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
-                || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) {
+        if (dc->base.singlestep_enabled) {
             gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
             break;
         }
         /* if too long translation, stop generation too */
         if (tcg_op_buf_full() ||
-            (dc->base.pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32) ||
             num_insns >= max_insns) {
             gen_jmp_im(dc->base.pc_next - dc->cs_base);
             gen_eob(dc);
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 14/34] target/i386: [tcg] Port to tb_stop
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (12 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 13/34] target/i386: [tcg] Port to translate_insn Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 15/34] target/i386: [tcg] Port to disas_log Richard Henderson
                   ` (20 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-Id: <150002219289.22386.17959138704858928730.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 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 d350699..8238533 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8487,8 +8487,6 @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
         /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
            the flag and abort the translation to give the irqs a
            chance to happen */
-        gen_jmp_im(pc_next - dc->cs_base);
-        gen_eob(dc);
         dc->base.is_jmp = DISAS_TOO_MANY;
     } else if ((dc->base.tb->cflags & CF_USE_ICOUNT)
                && ((dc->base.pc_next & TARGET_PAGE_MASK)
@@ -8501,18 +8499,24 @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, 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);
         dc->base.is_jmp = DISAS_TOO_MANY;
     } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
-        gen_jmp_im(pc_next - dc->cs_base);
-        gen_eob(dc);
         dc->base.is_jmp = DISAS_TOO_MANY;
     }
 
     dc->base.pc_next = pc_next;
 }
 
+static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    if (dc->base.is_jmp == DISAS_TOO_MANY) {
+        gen_jmp_im(dc->base.pc_next - dc->cs_base);
+        gen_eob(dc);
+    }
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
@@ -8569,23 +8573,21 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
         /* if single step mode, we generate only one instruction and
            generate an exception */
         if (dc->base.singlestep_enabled) {
-            gen_jmp_im(dc->base.pc_next - dc->cs_base);
-            gen_eob(dc);
+            dc->base.is_jmp = DISAS_TOO_MANY;
             break;
         }
         /* if too long translation, stop generation too */
         if (tcg_op_buf_full() ||
             num_insns >= max_insns) {
-            gen_jmp_im(dc->base.pc_next - dc->cs_base);
-            gen_eob(dc);
+            dc->base.is_jmp = DISAS_TOO_MANY;
             break;
         }
         if (singlestep) {
-            gen_jmp_im(dc->base.pc_next - dc->cs_base);
-            gen_eob(dc);
+            dc->base.is_jmp = DISAS_TOO_MANY;
             break;
         }
     }
+    i386_tr_tb_stop(&dc->base, cs);
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
     gen_tb_end(tb, num_insns);
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 15/34] target/i386: [tcg] Port to disas_log
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (13 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 14/34] target/i386: [tcg] Port to tb_stop Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 16/34] target/i386: [tcg] Port to generic translation framework Richard Henderson
                   ` (19 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-Id: <150002243497.22386.8888053391875656102.stgit@frigg.lan>
[rth: Move tb->size computation and use that result.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/i386/translate.c | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 8238533..8e7212c 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8517,6 +8517,21 @@ static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
     }
 }
 
+static void i386_tr_disas_log(const DisasContextBase *dcbase,
+                              CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    int disas_flags = !dc->code32;
+
+    qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
+#ifdef TARGET_X86_64
+    if (dc->code64) {
+        disas_flags = 2;
+    }
+#endif
+    log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size, disas_flags);
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
@@ -8592,28 +8607,19 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
         gen_io_end();
     gen_tb_end(tb, num_insns);
 
+    tb->size = dc->base.pc_next - dc->base.pc_first;
+    tb->icount = num_insns;
+
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
         && qemu_log_in_addr_range(dc->base.pc_first)) {
-        int disas_flags;
         qemu_log_lock();
         qemu_log("----------------\n");
-        qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
-#ifdef TARGET_X86_64
-        if (dc->code64)
-            disas_flags = 2;
-        else
-#endif
-            disas_flags = !dc->code32;
-        log_target_disas(cs, dc->base.pc_first, dc->base.pc_next - dc->base.pc_first,
-                         disas_flags);
+        i386_tr_disas_log(&dc->base, cs);
         qemu_log("\n");
         qemu_log_unlock();
     }
 #endif
-
-    tb->size = dc->base.pc_next - dc->base.pc_first;
-    tb->icount = num_insns;
 }
 
 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 16/34] target/i386: [tcg] Port to generic translation framework
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (14 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 15/34] target/i386: [tcg] Port to disas_log Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 17/34] target/arm: [tcg] Port to DisasContextBase Richard Henderson
                   ` (18 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Tested-by: Emilio G. Cota <cota@braap.org>
Message-Id: <150002267714.22386.5095442346868988808.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/i386/translate.c | 106 +++++++++---------------------------------------
 1 file changed, 19 insertions(+), 87 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 8e7212c..2bd667e 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -8449,6 +8449,10 @@ static int i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu,
     return max_insns;
 }
 
+static void i386_tr_tb_start(DisasContextBase *db, CPUState *cpu)
+{
+}
+
 static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
 {
     DisasContext *dc = container_of(dcbase, DisasContext, base);
@@ -8468,7 +8472,7 @@ static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
         /* The address covered by the breakpoint must be included in
            [tb->pc, tb->pc + tb->size) in order to for it to be
            properly cleared -- thus we increment the PC here so that
-           the logic setting tb->size below does the right thing.  */
+           the generic logic setting tb->size later does the right thing.  */
         dc->base.pc_next += 1;
         return true;
     } else {
@@ -8532,94 +8536,22 @@ static void i386_tr_disas_log(const DisasContextBase *dcbase,
     log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size, disas_flags);
 }
 
-/* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
-{
-    DisasContext dc1, *dc = &dc1;
-    int num_insns;
-    int max_insns;
-
-    /* generate intermediate code */
-    dc->base.singlestep_enabled = cs->singlestep_enabled;
-    dc->base.tb = tb;
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.pc_first = tb->pc;
-    dc->base.pc_next = dc->base.pc_first;
-
-    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;
-    }
-    max_insns = i386_tr_init_disas_context(&dc->base, cs, max_insns);
-
-    num_insns = 0;
-    gen_tb_start(tb);
-    for(;;) {
-        i386_tr_insn_start(&dc->base, cs);
-        num_insns++;
-
-        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
-            CPUBreakpoint *bp;
-            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
-                if (bp->pc == dc->base.pc_next) {
-                    if (i386_tr_breakpoint_check(&dc->base, cs, bp)) {
-                        break;
-                    }
-                }
-            }
-
-            if (dc->base.is_jmp == DISAS_NORETURN) {
-                break;
-            }
-        }
-
-        if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
-        }
-
-        i386_tr_translate_insn(&dc->base, cs);
-        /* stop translation if indicated */
-        if (dc->base.is_jmp) {
-            break;
-        }
-        /* if single step mode, we generate only one instruction and
-           generate an exception */
-        if (dc->base.singlestep_enabled) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-            break;
-        }
-        /* if too long translation, stop generation too */
-        if (tcg_op_buf_full() ||
-            num_insns >= max_insns) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-            break;
-        }
-        if (singlestep) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-            break;
-        }
-    }
-    i386_tr_tb_stop(&dc->base, cs);
-    if (tb->cflags & CF_LAST_IO)
-        gen_io_end();
-    gen_tb_end(tb, num_insns);
+static const TranslatorOps i386_tr_ops = {
+    .init_disas_context = i386_tr_init_disas_context,
+    .tb_start           = i386_tr_tb_start,
+    .insn_start         = i386_tr_insn_start,
+    .breakpoint_check   = i386_tr_breakpoint_check,
+    .translate_insn     = i386_tr_translate_insn,
+    .tb_stop            = i386_tr_tb_stop,
+    .disas_log          = i386_tr_disas_log,
+};
 
-    tb->size = dc->base.pc_next - dc->base.pc_first;
-    tb->icount = num_insns;
+/* generate intermediate code for basic block 'tb'.  */
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
+{
+    DisasContext dc;
 
-#ifdef DEBUG_DISAS
-    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
-        && qemu_log_in_addr_range(dc->base.pc_first)) {
-        qemu_log_lock();
-        qemu_log("----------------\n");
-        i386_tr_disas_log(&dc->base, cs);
-        qemu_log("\n");
-        qemu_log_unlock();
-    }
-#endif
+    translator_loop(&i386_tr_ops, &dc.base, cpu, tb);
 }
 
 void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 17/34] target/arm: [tcg] Port to DisasContextBase
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (15 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 16/34] target/i386: [tcg] Port to generic translation framework Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 18/34] target/arm: [tcg] Port to init_disas_context Richard Henderson
                   ` (17 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002291931.22386.11441154993010495674.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.h     |  11 +++--
 target/arm/translate-a64.c | 117 ++++++++++++++++++++++----------------------
 target/arm/translate.c     | 118 ++++++++++++++++++++++-----------------------
 3 files changed, 122 insertions(+), 124 deletions(-)

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

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

* [Qemu-devel] [PATCH v14 18/34] target/arm: [tcg] Port to init_disas_context
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (16 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 17/34] target/arm: [tcg] Port to DisasContextBase Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 19/34] target/arm: [tcg, a64] " Richard Henderson
                   ` (16 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002316201.22386.12115078843605656029.stgit@frigg.lan>
[rth: Adjust for max_insns interface change.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.c | 88 ++++++++++++++++++++++++++++----------------------
 1 file changed, 50 insertions(+), 38 deletions(-)

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

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

* [Qemu-devel] [PATCH v14 19/34] target/arm: [tcg, a64] Port to init_disas_context
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (17 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 18/34] target/arm: [tcg] Port to init_disas_context Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 20/34] target/arm: [tcg] Port to tb_start Richard Henderson
                   ` (15 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002340430.22386.10889954302345646107.stgit@frigg.lan>
[rth: Adjust for max_insns interface change.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate-a64.c | 38 ++++++++++++++++++++++++--------------
 1 file changed, 24 insertions(+), 14 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 57dbf8c..e9bea91 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11190,21 +11190,12 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
     free_tmp_a64(s);
 }
 
-void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
-                               TranslationBlock *tb)
+static int aarch64_tr_init_disas_context(DisasContextBase *dcbase,
+                                         CPUState *cpu, int max_insns)
 {
-    CPUARMState *env = cs->env_ptr;
-    ARMCPU *cpu = arm_env_get_cpu(env);
     DisasContext *dc = container_of(dcbase, DisasContext, base);
-    target_ulong next_page_start;
-    int max_insns;
-
-    dc->base.tb = tb;
-    dc->base.pc_first = dc->base.tb->pc;
-    dc->base.pc_next = dc->base.pc_first;
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.num_insns = 0;
-    dc->base.singlestep_enabled = cs->singlestep_enabled;
+    CPUARMState *env = cpu->env_ptr;
+    ARMCPU *arm_cpu = arm_env_get_cpu(env);
 
     dc->pc = dc->base.pc_first;
     dc->condjmp = 0;
@@ -11230,7 +11221,7 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
     dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
     dc->vec_len = 0;
     dc->vec_stride = 0;
-    dc->cp_regs = cpu->cp_regs;
+    dc->cp_regs = arm_cpu->cp_regs;
     dc->features = env->features;
 
     /* Single step state. The code-generation logic here is:
@@ -11255,6 +11246,24 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
 
     init_tmp_a64_array(dc);
 
+    return max_insns;
+}
+
+void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
+                               TranslationBlock *tb)
+{
+    CPUARMState *env = cs->env_ptr;
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    target_ulong next_page_start;
+    int max_insns;
+
+    dc->base.tb = tb;
+    dc->base.pc_first = dc->base.tb->pc;
+    dc->base.pc_next = dc->base.pc_first;
+    dc->base.is_jmp = DISAS_NEXT;
+    dc->base.num_insns = 0;
+    dc->base.singlestep_enabled = cs->singlestep_enabled;
+
     next_page_start = (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     max_insns = dc->base.tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
@@ -11263,6 +11272,7 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
     if (max_insns > TCG_MAX_INSNS) {
         max_insns = TCG_MAX_INSNS;
     }
+    max_insns = aarch64_tr_init_disas_context(&dc->base, cs, max_insns);
 
     gen_tb_start(tb);
 
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 20/34] target/arm: [tcg] Port to tb_start
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (18 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 19/34] target/arm: [tcg, a64] " Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 21/34] target/arm: [tcg] Port to insn_start Richard Henderson
                   ` (14 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002364681.22386.1701754996184325808.stgit@frigg.lan>
[rth: Adjust for tb_start interface change.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 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 de9c456..f5d69db 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11855,6 +11855,49 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase,
     return max_insns;
 }
 
+static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    /* A note on handling of the condexec (IT) bits:
+     *
+     * We want to avoid the overhead of having to write the updated condexec
+     * bits back to the CPUARMState for every instruction in an IT block. So:
+     * (1) if the condexec bits are not already zero then we write
+     * zero back into the CPUARMState now. This avoids complications trying
+     * to do it at the end of the block. (For example if we don't do this
+     * it's hard to identify whether we can safely skip writing condexec
+     * at the end of the TB, which we definitely want to do for the case
+     * where a TB doesn't do anything with the IT state at all.)
+     * (2) if we are going to leave the TB then we call gen_set_condexec()
+     * which will write the correct value into CPUARMState if zero is wrong.
+     * This is done both for leaving the TB at the end, and for leaving
+     * it because of an exception we know will happen, which is done in
+     * gen_exception_insn(). The latter is necessary because we need to
+     * leave the TB with the PC/IT state just prior to execution of the
+     * instruction which caused the exception.
+     * (3) if we leave the TB unexpectedly (eg a data abort on a load)
+     * then the CPUARMState will be wrong and we need to reset it.
+     * This is handled in the same way as restoration of the
+     * PC in these situations; we save the value of the condexec bits
+     * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
+     * then uses this to restore them after an exception.
+     *
+     * Note that there are no instructions which can read the condexec
+     * bits, and none which can write non-static values to them, so
+     * we don't need to care about whether CPUARMState is correct in the
+     * middle of a TB.
+     */
+
+    /* Reset the conditional execution bits immediately. This avoids
+       complications trying to do it at the end of the block.  */
+    if (dc->condexec_mask || dc->condexec_cond) {
+        TCGv_i32 tmp = tcg_temp_new_i32();
+        tcg_gen_movi_i32(tmp, 0);
+        store_cpu_field(tmp, condexec_bits);
+    }
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
@@ -11894,45 +11937,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
     gen_tb_start(tb);
 
     tcg_clear_temp_count();
+    arm_tr_tb_start(&dc->base, cs);
 
-    /* A note on handling of the condexec (IT) bits:
-     *
-     * We want to avoid the overhead of having to write the updated condexec
-     * bits back to the CPUARMState for every instruction in an IT block. So:
-     * (1) if the condexec bits are not already zero then we write
-     * zero back into the CPUARMState now. This avoids complications trying
-     * to do it at the end of the block. (For example if we don't do this
-     * it's hard to identify whether we can safely skip writing condexec
-     * at the end of the TB, which we definitely want to do for the case
-     * where a TB doesn't do anything with the IT state at all.)
-     * (2) if we are going to leave the TB then we call gen_set_condexec()
-     * which will write the correct value into CPUARMState if zero is wrong.
-     * This is done both for leaving the TB at the end, and for leaving
-     * it because of an exception we know will happen, which is done in
-     * gen_exception_insn(). The latter is necessary because we need to
-     * leave the TB with the PC/IT state just prior to execution of the
-     * instruction which caused the exception.
-     * (3) if we leave the TB unexpectedly (eg a data abort on a load)
-     * then the CPUARMState will be wrong and we need to reset it.
-     * This is handled in the same way as restoration of the
-     * PC in these situations; we save the value of the condexec bits
-     * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
-     * then uses this to restore them after an exception.
-     *
-     * Note that there are no instructions which can read the condexec
-     * bits, and none which can write non-static values to them, so
-     * we don't need to care about whether CPUARMState is correct in the
-     * middle of a TB.
-     */
-
-    /* Reset the conditional execution bits immediately. This avoids
-       complications trying to do it at the end of the block.  */
-    if (dc->condexec_mask || dc->condexec_cond)
-      {
-        TCGv_i32 tmp = tcg_temp_new_i32();
-        tcg_gen_movi_i32(tmp, 0);
-        store_cpu_field(tmp, condexec_bits);
-      }
     do {
         dc->base.num_insns++;
         dc->insn_start_idx = tcg_op_buf_count();
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 21/34] target/arm: [tcg] Port to insn_start
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (19 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 20/34] target/arm: [tcg] Port to tb_start Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 22/34] target/arm: [tcg, a64] " Richard Henderson
                   ` (13 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002388959.22386.12439646324427589940.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index f5d69db..5e09682 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11898,6 +11898,16 @@ static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
     }
 }
 
+static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    dc->insn_start_idx = tcg_op_buf_count();
+    tcg_gen_insn_start(dc->pc,
+                       (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
+                       0);
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
@@ -11941,10 +11951,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 
     do {
         dc->base.num_insns++;
-        dc->insn_start_idx = tcg_op_buf_count();
-        tcg_gen_insn_start(dc->pc,
-                           (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
-                           0);
+        arm_tr_insn_start(&dc->base, cs);
 
         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
             CPUBreakpoint *bp;
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 22/34] target/arm: [tcg, a64] Port to insn_start
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (20 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 21/34] target/arm: [tcg] Port to insn_start Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 23/34] target/arm: [tcg, a64] Port to breakpoint_check Richard Henderson
                   ` (12 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002413187.22386.156315485813606121.stgit@frigg.lan>
[rth: Use DISAS_TOO_MANY for "execute only one more" after bp.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate-a64.c | 11 +++++++--
 target/arm/translate.c     | 56 +++++++++++++++++++++++++++++-----------------
 2 files changed, 44 insertions(+), 23 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index e9bea91..dca5825 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11249,6 +11249,14 @@ static int aarch64_tr_init_disas_context(DisasContextBase *dcbase,
     return max_insns;
 }
 
+static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    dc->insn_start_idx = tcg_op_buf_count();
+    tcg_gen_insn_start(dc->pc, 0, 0);
+}
+
 void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
                                TranslationBlock *tb)
 {
@@ -11280,8 +11288,7 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
 
     do {
         dc->base.num_insns++;
-        dc->insn_start_idx = tcg_op_buf_count();
-        tcg_gen_insn_start(dc->pc, 0, 0);
+        aarch64_tr_insn_start(&dc->base, cs);
 
         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
             CPUBreakpoint *bp;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 5e09682..15bd9e7 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11908,6 +11908,33 @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
                        0);
 }
 
+static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
+                                    const CPUBreakpoint *bp)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    if (bp->flags & BP_CPU) {
+        gen_set_condexec(dc);
+        gen_set_pc_im(dc, dc->pc);
+        gen_helper_check_breakpoints(cpu_env);
+        /* End the TB early; it's likely not going to be executed */
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    } 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;
+        dc->base.is_jmp = DISAS_NORETURN;
+    }
+
+    return true;
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
@@ -11956,29 +11983,15 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
         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_set_condexec(dc);
-                        gen_set_pc_im(dc, dc->pc);
-                        gen_helper_check_breakpoints(cpu_env);
-                        /* End the TB early; it's likely not going to be executed */
-                        dc->base.is_jmp = DISAS_UPDATE;
-                    } else {
-                        gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
-                        dc->base.is_jmp = DISAS_NORETURN;
-                        /* The address covered by the breakpoint must be
-                           included in [tb->pc, tb->pc + tb->size) in order
-                           to for it to be properly cleared -- thus we
-                           increment the PC here so that the logic setting
-                           tb->size below does the right thing.  */
-                        /* TODO: Advance PC by correct instruction length to
-                         * avoid disassembler error messages */
-                        dc->pc += 2;
-                        goto done_generating;
+                if (bp->pc == dc->base.pc_next) {
+                    if (arm_tr_breakpoint_check(&dc->base, cs, bp)) {
+                        break;
                     }
-                    break;
                 }
             }
+            if (dc->base.is_jmp > DISAS_TOO_MANY) {
+                break;
+            }
         }
 
         if (dc->base.num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
@@ -12100,6 +12113,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
             gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
             break;
         case DISAS_NEXT:
+        case DISAS_TOO_MANY:
         case DISAS_UPDATE:
             gen_set_pc_im(dc, dc->pc);
             /* fall through */
@@ -12120,6 +12134,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
          */
         switch(dc->base.is_jmp) {
         case DISAS_NEXT:
+        case DISAS_TOO_MANY:
             gen_goto_tb(dc, 1, dc->pc);
             break;
         case DISAS_UPDATE:
@@ -12173,7 +12188,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
         }
     }
 
-done_generating:
     gen_tb_end(tb, dc->base.num_insns);
 
 #ifdef DEBUG_DISAS
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 23/34] target/arm: [tcg, a64] Port to breakpoint_check
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (21 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 22/34] target/arm: [tcg, a64] " Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 22:12   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 24/34] target/arm: [tcg] Port to translate_insn Richard Henderson
                   ` (11 subsequent siblings)
  34 siblings, 1 reply; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-Id: <150002461630.22386.14827196109258040543.stgit@frigg.lan>
[rth: Use DISAS_TOO_MANY for "execute only one more" after bp.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate-a64.c | 49 +++++++++++++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index dca5825..1541bf0 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11257,6 +11257,30 @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
     tcg_gen_insn_start(dc->pc, 0, 0);
 }
 
+static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
+                                        const CPUBreakpoint *bp)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    if (bp->flags & BP_CPU) {
+        gen_a64_set_pc_im(dc->pc);
+        gen_helper_check_breakpoints(cpu_env);
+        /* End the TB early; it likely won't be executed */
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    } 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;
+        dc->base.is_jmp = DISAS_NORETURN;
+    }
+
+    return true;
+}
+
 void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
                                TranslationBlock *tb)
 {
@@ -11293,26 +11317,15 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
             CPUBreakpoint *bp;
             QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
-                if (bp->pc == dc->pc) {
-                    if (bp->flags & BP_CPU) {
-                        gen_a64_set_pc_im(dc->pc);
-                        gen_helper_check_breakpoints(cpu_env);
-                        /* End the TB early; it likely won't be executed */
-                        dc->base.is_jmp = DISAS_UPDATE;
-                    } else {
-                        gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
-                        dc->base.is_jmp = DISAS_NORETURN;
-                        /* The address covered by the breakpoint must be
-                           included in [dc->base.tb->pc, dc->base.tb->pc + dc->base.tb->size) in order
-                           to for it to be properly cleared -- thus we
-                           increment the PC here so that the logic setting
-                           dc->base.tb->size below does the right thing.  */
-                        dc->pc += 4;
-                        goto done_generating;
+                if (bp->pc == dc->base.pc_next) {
+                    if (aarch64_tr_breakpoint_check(&dc->base, cs, bp)) {
+                        break;
                     }
-                    break;
                 }
             }
+            if (dc->base.is_jmp > DISAS_TOO_MANY) {
+                break;
+            }
         }
 
         if (dc->base.num_insns == max_insns && (dc->base.tb->cflags & CF_LAST_IO)) {
@@ -11383,6 +11396,7 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
     } else {
         switch (dc->base.is_jmp) {
         case DISAS_NEXT:
+        case DISAS_TOO_MANY:
             gen_goto_tb(dc, 1, dc->pc);
             break;
         default:
@@ -11420,7 +11434,6 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
         }
     }
 
-done_generating:
     gen_tb_end(tb, dc->base.num_insns);
 
 #ifdef DEBUG_DISAS
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 24/34] target/arm: [tcg] Port to translate_insn
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (22 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 23/34] target/arm: [tcg, a64] Port to breakpoint_check Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 22:24   ` Emilio G. Cota
  2017-07-21 23:20   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 25/34] target/arm: [tcg, a64] " Richard Henderson
                   ` (10 subsequent siblings)
  34 siblings, 2 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Message-Id: <150002485863.22386.13949856269576226529.stgit@frigg.lan>
[rth: Adjust for translate_insn interface change.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.h |   1 +
 target/arm/translate.c | 165 +++++++++++++++++++++++++++----------------------
 2 files changed, 91 insertions(+), 75 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index 4cbf7cd..65e0c74 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -9,6 +9,7 @@ typedef struct DisasContext {
     DisasContextBase base;
 
     target_ulong pc;
+    target_ulong next_page_start;
     uint32_t insn;
     /* Nonzero if this instruction has been conditionally skipped.  */
     int condjmp;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 15bd9e7..ae1ed5f 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11842,6 +11842,8 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase,
     dc->is_ldex = false;
     dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
 
+    dc->next_page_start =
+        (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
 
     cpu_F0s = tcg_temp_new_i32();
     cpu_F1s = tcg_temp_new_i32();
@@ -11935,14 +11937,93 @@ static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
     return true;
 }
 
+static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    CPUARMState *env = cpu->env_ptr;
+
+#ifdef CONFIG_USER_ONLY
+        /* Intercept jump to the magic kernel page.  */
+        if (dc->pc >= 0xffff0000) {
+            /* We always get here via a jump, so know we are not in a
+               conditional execution block.  */
+            gen_exception_internal(EXCP_KERNEL_TRAP);
+            dc->base.is_jmp = DISAS_NORETURN;
+            return;
+        }
+#endif
+
+    if (dc->ss_active && !dc->pstate_ss) {
+        /* Singlestep state is Active-pending.
+         * If we're in this state at the start of a TB then either
+         *  a) we just took an exception to an EL which is being debugged
+         *     and this is the first insn in the exception handler
+         *  b) debug exceptions were masked and we just unmasked them
+         *     without changing EL (eg by clearing PSTATE.D)
+         * In either case we're going to take a swstep exception in the
+         * "did not step an insn" case, and so the syndrome ISV and EX
+         * bits should be zero.
+         */
+        assert(dc->base.num_insns == 1);
+        gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
+                      default_exception_el(dc));
+        dc->base.is_jmp = DISAS_NORETURN;
+        return;
+    }
+
+    if (dc->thumb) {
+        disas_thumb_insn(env, dc);
+        if (dc->condexec_mask) {
+            dc->condexec_cond = (dc->condexec_cond & 0xe)
+                | ((dc->condexec_mask >> 4) & 1);
+            dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
+            if (dc->condexec_mask == 0) {
+                dc->condexec_cond = 0;
+            }
+        }
+    } else {
+        unsigned int insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
+        dc->pc += 4;
+        disas_arm_insn(dc, insn);
+    }
+
+    if (dc->condjmp && !dc->base.is_jmp) {
+        gen_set_label(dc->condlabel);
+        dc->condjmp = 0;
+    }
+
+    if (dc->base.is_jmp == DISAS_NEXT) {
+        /* Translation stops when a conditional branch is encountered.
+         * Otherwise the subsequent code could get translated several times.
+         * Also stop translation when a page boundary is reached.  This
+         * ensures prefetch aborts occur at the right place.  */
+
+        if (is_singlestepping(dc)) {
+            dc->base.is_jmp = DISAS_TOO_MANY;
+        } 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).
+             */
+            dc->base.is_jmp = DISAS_TOO_MANY;
+        }
+    }
+
+    dc->base.pc_next = dc->pc;
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
-    CPUARMState *env = cs->env_ptr;
     DisasContext dc1, *dc = &dc1;
-    target_ulong next_page_start;
     int max_insns;
-    bool end_of_page;
 
     /* generate intermediate code */
 
@@ -11961,7 +12042,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
     dc->base.num_insns = 0;
     dc->base.singlestep_enabled = cs->singlestep_enabled;
 
-    next_page_start = (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
     max_insns = tb->cflags & CF_COUNT_MASK;
     if (max_insns == 0) {
         max_insns = CF_COUNT_MASK;
@@ -11998,83 +12078,18 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
             gen_io_start();
         }
 
-#ifdef CONFIG_USER_ONLY
-        /* Intercept jump to the magic kernel page.  */
-        if (dc->pc >= 0xffff0000) {
-            /* We always get here via a jump, so know we are not in a
-               conditional execution block.  */
-            gen_exception_internal(EXCP_KERNEL_TRAP);
-            dc->base.is_jmp = DISAS_NORETURN;
-            break;
-        }
-#endif
-
-        if (dc->ss_active && !dc->pstate_ss) {
-            /* Singlestep state is Active-pending.
-             * If we're in this state at the start of a TB then either
-             *  a) we just took an exception to an EL which is being debugged
-             *     and this is the first insn in the exception handler
-             *  b) debug exceptions were masked and we just unmasked them
-             *     without changing EL (eg by clearing PSTATE.D)
-             * In either case we're going to take a swstep exception in the
-             * "did not step an insn" case, and so the syndrome ISV and EX
-             * bits should be zero.
-             */
-            assert(dc->base.num_insns == 1);
-            gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
-                          default_exception_el(dc));
-            dc->base.is_jmp = DISAS_NORETURN;
-            break;
-        }
-
-        if (dc->thumb) {
-            disas_thumb_insn(env, dc);
-            if (dc->condexec_mask) {
-                dc->condexec_cond = (dc->condexec_cond & 0xe)
-                                   | ((dc->condexec_mask >> 4) & 1);
-                dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
-                if (dc->condexec_mask == 0) {
-                    dc->condexec_cond = 0;
-                }
-            }
-        } else {
-            unsigned int insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
-            dc->pc += 4;
-            disas_arm_insn(dc, insn);
-        }
-
-        if (dc->condjmp && !dc->base.is_jmp) {
-            gen_set_label(dc->condlabel);
-            dc->condjmp = 0;
-        }
+        arm_tr_translate_insn(&dc->base, cs);
 
         if (tcg_check_temp_count()) {
             fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
                     dc->pc);
         }
 
-        /* Translation stops when a conditional branch is encountered.
-         * Otherwise the subsequent code could get translated several times.
-         * Also stop translation when a page boundary is reached.  This
-         * ensures prefetch aborts occur at the right place.  */
-
-        /* We want to stop the TB if the next insn starts in a new page,
-         * or if it spans between this page and the next. This means that
-         * if we're looking at the last halfword in the page we need to
-         * see if it's a 16-bit Thumb insn (which will fit in this TB)
-         * or a 32-bit Thumb insn (which won't).
-         * This is to avoid generating a silly TB with a single 16-bit insn
-         * in it at the end of this page (which would execute correctly
-         * but isn't very efficient).
-         */
-        end_of_page = (dc->pc >= next_page_start) ||
-            ((dc->pc >= next_page_start - 3) && insn_crosses_page(env, dc));
-
-    } while (!dc->base.is_jmp && !tcg_op_buf_full() &&
-             !is_singlestepping(dc) &&
-             !singlestep &&
-             !end_of_page &&
-             dc->base.num_insns < max_insns);
+        if (!dc->base.is_jmp && (tcg_op_buf_full() || singlestep ||
+                            dc->base.num_insns >= max_insns)) {
+            dc->base.is_jmp = DISAS_TOO_MANY;
+        }
+    } while (!dc->base.is_jmp);
 
     if (tb->cflags & CF_LAST_IO) {
         if (dc->condjmp) {
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 25/34] target/arm: [tcg, a64] Port to translate_insn
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (23 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 24/34] target/arm: [tcg] Port to translate_insn Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 22:28   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 26/34] target/arm: [tcg] Port to tb_stop Richard Henderson
                   ` (9 subsequent siblings)
  34 siblings, 1 reply; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Message-Id: <150002510079.22386.10164419868911710218.stgit@frigg.lan>
[rth: Adjust for translate_insn interface change.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate-a64.c | 71 ++++++++++++++++++++++++++++------------------
 1 file changed, 43 insertions(+), 28 deletions(-)

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

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

* [Qemu-devel] [PATCH v14 26/34] target/arm: [tcg] Port to tb_stop
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (24 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 25/34] target/arm: [tcg, a64] " Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 22:41   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 27/34] target/arm: [tcg, a64] " Richard Henderson
                   ` (8 subsequent siblings)
  34 siblings, 1 reply; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Message-Id: <150002534291.22386.13499916738708680298.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.c | 162 ++++++++++++++++++++++++++-----------------------
 1 file changed, 85 insertions(+), 77 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index ae1ed5f..a934641 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -12019,85 +12019,13 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
     dc->base.pc_next = dc->pc;
 }
 
-/* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
+static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
 {
-    DisasContext dc1, *dc = &dc1;
-    int max_insns;
-
-    /* generate intermediate code */
-
-    /* The A64 decoder has its own top level loop, because it doesn't need
-     * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
-     */
-    if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
-        gen_intermediate_code_a64(&dc->base, cs, tb);
-        return;
-    }
-
-    dc->base.tb = tb;
-    dc->base.pc_first = dc->base.tb->pc;
-    dc->base.pc_next = dc->base.pc_first;
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.num_insns = 0;
-    dc->base.singlestep_enabled = cs->singlestep_enabled;
-
-    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;
-    }
-    max_insns = arm_tr_init_disas_context(&dc->base, cs, max_insns);
-
-    gen_tb_start(tb);
-
-    tcg_clear_temp_count();
-    arm_tr_tb_start(&dc->base, cs);
-
-    do {
-        dc->base.num_insns++;
-        arm_tr_insn_start(&dc->base, cs);
-
-        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
-            CPUBreakpoint *bp;
-            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
-                if (bp->pc == dc->base.pc_next) {
-                    if (arm_tr_breakpoint_check(&dc->base, cs, bp)) {
-                        break;
-                    }
-                }
-            }
-            if (dc->base.is_jmp > DISAS_TOO_MANY) {
-                break;
-            }
-        }
-
-        if (dc->base.num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
-        }
-
-        arm_tr_translate_insn(&dc->base, cs);
-
-        if (tcg_check_temp_count()) {
-            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
-                    dc->pc);
-        }
-
-        if (!dc->base.is_jmp && (tcg_op_buf_full() || singlestep ||
-                            dc->base.num_insns >= max_insns)) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-        }
-    } while (!dc->base.is_jmp);
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
 
-    if (tb->cflags & CF_LAST_IO) {
-        if (dc->condjmp) {
-            /* FIXME:  This can theoretically happen with self-modifying
-               code.  */
-            cpu_abort(cs, "IO on conditional branch instruction");
-        }
-        gen_io_end();
+    if (dc->base.tb->cflags & CF_LAST_IO && dc->condjmp) {
+        /* FIXME: This can theoretically happen with self-modifying code. */
+        cpu_abort(cpu, "IO on conditional branch instruction");
     }
 
     /* At this stage dc->condjmp will only be set when the skipped
@@ -12135,6 +12063,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
         default:
             /* FIXME: Single stepping a WFI insn will not halt the CPU. */
             gen_singlestep_exception(dc);
+            break;
         case DISAS_NORETURN:
             break;
         }
@@ -12202,6 +12131,85 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
             gen_goto_tb(dc, 1, dc->pc);
         }
     }
+}
+
+/* generate intermediate code for basic block 'tb'.  */
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
+{
+    DisasContext dc1, *dc = &dc1;
+    int max_insns;
+
+    /* generate intermediate code */
+
+    /* The A64 decoder has its own top level loop, because it doesn't need
+     * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
+     */
+    if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
+        gen_intermediate_code_a64(&dc->base, cs, tb);
+        return;
+    }
+
+    dc->base.tb = tb;
+    dc->base.pc_first = dc->base.tb->pc;
+    dc->base.pc_next = dc->base.pc_first;
+    dc->base.is_jmp = DISAS_NEXT;
+    dc->base.num_insns = 0;
+    dc->base.singlestep_enabled = cs->singlestep_enabled;
+
+    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;
+    }
+    max_insns = arm_tr_init_disas_context(&dc->base, cs, max_insns);
+
+    gen_tb_start(tb);
+
+    tcg_clear_temp_count();
+    arm_tr_tb_start(&dc->base, cs);
+
+    do {
+        dc->base.num_insns++;
+        arm_tr_insn_start(&dc->base, cs);
+
+        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+            CPUBreakpoint *bp;
+            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
+                if (bp->pc == dc->base.pc_next) {
+                    if (arm_tr_breakpoint_check(&dc->base, cs, bp)) {
+                        break;
+                    }
+                }
+            }
+            if (dc->base.is_jmp > DISAS_TOO_MANY) {
+                break;
+            }
+        }
+
+        if (dc->base.num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+
+        arm_tr_translate_insn(&dc->base, cs);
+
+        if (tcg_check_temp_count()) {
+            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
+                    dc->pc);
+        }
+
+        if (!dc->base.is_jmp && (tcg_op_buf_full() || singlestep ||
+                            dc->base.num_insns >= max_insns)) {
+            dc->base.is_jmp = DISAS_TOO_MANY;
+        }
+    } while (!dc->base.is_jmp);
+
+    if (dc->base.tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+
+    arm_tr_tb_stop(&dc->base, cs);
 
     gen_tb_end(tb, dc->base.num_insns);
 
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 27/34] target/arm: [tcg, a64] Port to tb_stop
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (25 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 26/34] target/arm: [tcg] Port to tb_stop Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 22:47   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 28/34] target/arm: [tcg] Port to disas_log Richard Henderson
                   ` (7 subsequent siblings)
  34 siblings, 1 reply; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-Id: <150002558503.22386.1149037590886263349.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate-a64.c | 127 ++++++++++++++++++++++++---------------------
 1 file changed, 67 insertions(+), 60 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index a92a3ec..588f048 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11317,6 +11317,72 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
     dc->base.pc_next = dc->pc;
 }
 
+static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    if (unlikely(dc->base.singlestep_enabled || dc->ss_active)) {
+        /* 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).
+         */
+        switch (dc->base.is_jmp) {
+        default:
+            gen_a64_set_pc_im(dc->pc);
+            /* fall through */
+        case DISAS_JUMP:
+            if (dc->base.singlestep_enabled) {
+                gen_exception_internal(EXCP_DEBUG);
+            } else {
+                gen_step_complete_exception(dc);
+            }
+            break;
+        case DISAS_NORETURN:
+            break;
+        }
+    } else {
+        switch (dc->base.is_jmp) {
+        case DISAS_NEXT:
+        case DISAS_TOO_MANY:
+            gen_goto_tb(dc, 1, dc->pc);
+            break;
+        default:
+        case DISAS_UPDATE:
+            gen_a64_set_pc_im(dc->pc);
+            /* fall through */
+        case DISAS_JUMP:
+            tcg_gen_lookup_and_goto_ptr(cpu_pc);
+            break;
+        case DISAS_EXIT:
+            tcg_gen_exit_tb(0);
+            break;
+        case DISAS_NORETURN:
+        case DISAS_SWI:
+            break;
+        case DISAS_WFE:
+            gen_a64_set_pc_im(dc->pc);
+            gen_helper_wfe(cpu_env);
+            break;
+        case DISAS_YIELD:
+            gen_a64_set_pc_im(dc->pc);
+            gen_helper_yield(cpu_env);
+            break;
+        case DISAS_WFI:
+            /* This is a special case because we don't want to just halt the CPU
+             * if trying to debug across a WFI.
+             */
+            gen_a64_set_pc_im(dc->pc);
+            gen_helper_wfi(cpu_env);
+            /* The helper doesn't necessarily throw an exception, but we
+             * must go back to the main loop to check for interrupts anyway.
+             */
+            tcg_gen_exit_tb(0);
+            break;
+        }
+    }
+}
+
 void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
                                TranslationBlock *tb)
 {
@@ -11388,66 +11454,7 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
         gen_io_end();
     }
 
-    if (unlikely(cs->singlestep_enabled || dc->ss_active)) {
-        /* 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).
-         */
-        switch (dc->base.is_jmp) {
-        default:
-            gen_a64_set_pc_im(dc->pc);
-            /* fall through */
-        case DISAS_JUMP:
-            if (cs->singlestep_enabled) {
-                gen_exception_internal(EXCP_DEBUG);
-            } else {
-                gen_step_complete_exception(dc);
-            }
-            break;
-        case DISAS_NORETURN:
-            break;
-        }
-    } else {
-        switch (dc->base.is_jmp) {
-        case DISAS_NEXT:
-        case DISAS_TOO_MANY:
-            gen_goto_tb(dc, 1, dc->pc);
-            break;
-        default:
-        case DISAS_UPDATE:
-            gen_a64_set_pc_im(dc->pc);
-            /* fall through */
-        case DISAS_JUMP:
-            tcg_gen_lookup_and_goto_ptr(cpu_pc);
-            break;
-        case DISAS_EXIT:
-            tcg_gen_exit_tb(0);
-            break;
-        case DISAS_NORETURN:
-        case DISAS_SWI:
-            break;
-        case DISAS_WFE:
-            gen_a64_set_pc_im(dc->pc);
-            gen_helper_wfe(cpu_env);
-            break;
-        case DISAS_YIELD:
-            gen_a64_set_pc_im(dc->pc);
-            gen_helper_yield(cpu_env);
-            break;
-        case DISAS_WFI:
-            /* This is a special case because we don't want to just halt the CPU
-             * if trying to debug across a WFI.
-             */
-            gen_a64_set_pc_im(dc->pc);
-            gen_helper_wfi(cpu_env);
-            /* The helper doesn't necessarily throw an exception, but we
-             * must go back to the main loop to check for interrupts anyway.
-             */
-            tcg_gen_exit_tb(0);
-            break;
-        }
-    }
+    aarch64_tr_tb_stop(&dc->base, cs);
 
     gen_tb_end(tb, dc->base.num_insns);
 
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 28/34] target/arm: [tcg] Port to disas_log
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (26 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 27/34] target/arm: [tcg, a64] " Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 29/34] target/arm: [tcg, a64] " Richard Henderson
                   ` (6 subsequent siblings)
  34 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002582711.22386.191527630537864599.stgit@frigg.lan>
[rth: Move tb->size computation and use that result.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index a934641..4ea5f70 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -12133,6 +12133,15 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
     }
 }
 
+static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
+    log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size,
+                     dc->thumb | (dc->sctlr_b << 1));
+}
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 {
@@ -12213,20 +12222,19 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
 
     gen_tb_end(tb, dc->base.num_insns);
 
+    tb->size = dc->pc - dc->base.pc_first;
+    tb->icount = dc->base.num_insns;
+
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
         qemu_log_in_addr_range(dc->base.pc_first)) {
         qemu_log_lock();
         qemu_log("----------------\n");
-        qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
-        log_target_disas(cs, dc->base.pc_first, dc->pc - dc->base.pc_first,
-                         dc->thumb | (dc->sctlr_b << 1));
+        arm_tr_disas_log(&dc->base, cs);
         qemu_log("\n");
         qemu_log_unlock();
     }
 #endif
-    tb->size = dc->pc - dc->base.pc_first;
-    tb->icount = dc->base.num_insns;
 }
 
 static const char *cpu_mode_names[16] = {
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 29/34] target/arm: [tcg, a64] Port to disas_log
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (27 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 28/34] target/arm: [tcg] Port to disas_log Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 22:50   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 30/34] target/arm: [tcg] Port to generic translation framework Richard Henderson
                   ` (5 subsequent siblings)
  34 siblings, 1 reply; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Message-Id: <150002606914.22386.15524101311003685068.stgit@frigg.lan>
[rth: Move tb->size computation and use that result.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate-a64.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 588f048..6259ed0 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11383,6 +11383,16 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
     }
 }
 
+static void aarch64_tr_disas_log(const DisasContextBase *dcbase,
+                                      CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+
+    qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
+    log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size,
+                     4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
+}
+
 void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
                                TranslationBlock *tb)
 {
@@ -11458,18 +11468,17 @@ void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
 
     gen_tb_end(tb, dc->base.num_insns);
 
+    dc->base.tb->size = dc->pc - dc->base.pc_first;
+    dc->base.tb->icount = dc->base.num_insns;
+
 #ifdef DEBUG_DISAS
     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
         qemu_log_in_addr_range(dc->base.pc_first)) {
         qemu_log_lock();
         qemu_log("----------------\n");
-        qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
-        log_target_disas(cs, dc->base.pc_first, dc->pc - dc->base.pc_first,
-                         4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
+        aarch64_tr_disas_log(&dc->base, cs);
         qemu_log("\n");
         qemu_log_unlock();
     }
 #endif
-    dc->base.tb->size = dc->pc - dc->base.pc_first;
-    dc->base.tb->icount = dc->base.num_insns;
 }
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 30/34] target/arm: [tcg] Port to generic translation framework
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (28 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 29/34] target/arm: [tcg, a64] " Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 23:02   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 31/34] target/arm: [a64] Move page and ss checks to init_disas_context Richard Henderson
                   ` (4 subsequent siblings)
  34 siblings, 1 reply; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

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

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Message-Id: <150002631325.22386.10348327185029496649.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.h     |   8 +---
 target/arm/translate-a64.c | 107 ++++++++-----------------------------------
 target/arm/translate.c     | 110 ++++++++++-----------------------------------
 3 files changed, 42 insertions(+), 183 deletions(-)

diff --git a/target/arm/translate.h b/target/arm/translate.h
index 65e0c74..73a42ae 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -147,21 +147,15 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
 
 #ifdef TARGET_AARCH64
 void a64_translate_init(void);
-void gen_intermediate_code_a64(DisasContextBase *db, CPUState *cpu,
-                               TranslationBlock *tb);
 void gen_a64_set_pc_im(uint64_t val);
 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
                             fprintf_function cpu_fprintf, int flags);
+extern const TranslatorOps aarch64_translator_ops;
 #else
 static inline void a64_translate_init(void)
 {
 }
 
-static inline void gen_intermediate_code_a64(DisasContextBase *db, CPUState *cpu,
-                                             TranslationBlock *tb)
-{
-}
-
 static inline void gen_a64_set_pc_im(uint64_t val)
 {
 }
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 6259ed0..1aa4c14 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11252,6 +11252,11 @@ static int aarch64_tr_init_disas_context(DisasContextBase *dcbase,
     return max_insns;
 }
 
+static void aarch64_tr_tb_start(DisasContextBase *db, CPUState *cpu)
+{
+    tcg_clear_temp_count();
+}
+
 static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
 {
     DisasContext *dc = container_of(dcbase, DisasContext, base);
@@ -11315,6 +11320,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
     }
 
     dc->base.pc_next = dc->pc;
+    translator_loop_temp_check(&dc->base);
 }
 
 static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
@@ -11381,6 +11387,9 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
             break;
         }
     }
+
+    /* Functions above can change dc->pc, so re-align db->pc_next */
+    dc->base.pc_next = dc->pc;
 }
 
 static void aarch64_tr_disas_log(const DisasContextBase *dcbase,
@@ -11393,92 +11402,12 @@ static void aarch64_tr_disas_log(const DisasContextBase *dcbase,
                      4 | (bswap_code(dc->sctlr_b) ? 2 : 0));
 }
 
-void gen_intermediate_code_a64(DisasContextBase *dcbase, CPUState *cs,
-                               TranslationBlock *tb)
-{
-    DisasContext *dc = container_of(dcbase, DisasContext, base);
-    int max_insns;
-
-    dc->base.tb = tb;
-    dc->base.pc_first = dc->base.tb->pc;
-    dc->base.pc_next = dc->base.pc_first;
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.num_insns = 0;
-    dc->base.singlestep_enabled = cs->singlestep_enabled;
-
-    max_insns = dc->base.tb->cflags & CF_COUNT_MASK;
-    if (max_insns == 0) {
-        max_insns = CF_COUNT_MASK;
-    }
-    if (max_insns > TCG_MAX_INSNS) {
-        max_insns = TCG_MAX_INSNS;
-    }
-    max_insns = aarch64_tr_init_disas_context(&dc->base, cs, max_insns);
-
-    gen_tb_start(tb);
-
-    tcg_clear_temp_count();
-
-    do {
-        dc->base.num_insns++;
-        aarch64_tr_insn_start(&dc->base, cs);
-
-        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
-            CPUBreakpoint *bp;
-            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
-                if (bp->pc == dc->base.pc_next) {
-                    if (aarch64_tr_breakpoint_check(&dc->base, cs, bp)) {
-                        break;
-                    }
-                }
-            }
-            if (dc->base.is_jmp > DISAS_TOO_MANY) {
-                break;
-            }
-        }
-
-        if (dc->base.num_insns == max_insns && (dc->base.tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
-        }
-
-        aarch64_tr_translate_insn(&dc->base, cs);
-
-        if (tcg_check_temp_count()) {
-            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
-                    dc->pc);
-        }
-
-        if (!dc->base.is_jmp && (tcg_op_buf_full() || cs->singlestep_enabled ||
-                            singlestep || dc->base.num_insns >= max_insns)) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-        }
-
-        /* Translation stops when a conditional branch is encountered.
-         * Otherwise the subsequent code could get translated several times.
-         * Also stop translation when a page boundary is reached.  This
-         * ensures prefetch aborts occur at the right place.
-         */
-    } while (!dc->base.is_jmp);
-
-    if (dc->base.tb->cflags & CF_LAST_IO) {
-        gen_io_end();
-    }
-
-    aarch64_tr_tb_stop(&dc->base, cs);
-
-    gen_tb_end(tb, dc->base.num_insns);
-
-    dc->base.tb->size = dc->pc - dc->base.pc_first;
-    dc->base.tb->icount = dc->base.num_insns;
-
-#ifdef DEBUG_DISAS
-    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
-        qemu_log_in_addr_range(dc->base.pc_first)) {
-        qemu_log_lock();
-        qemu_log("----------------\n");
-        aarch64_tr_disas_log(&dc->base, cs);
-        qemu_log("\n");
-        qemu_log_unlock();
-    }
-#endif
-}
+const TranslatorOps aarch64_translator_ops = {
+    .init_disas_context = aarch64_tr_init_disas_context,
+    .tb_start           = aarch64_tr_tb_start,
+    .insn_start         = aarch64_tr_insn_start,
+    .breakpoint_check   = aarch64_tr_breakpoint_check,
+    .translate_insn     = aarch64_tr_translate_insn,
+    .tb_stop            = aarch64_tr_tb_stop,
+    .disas_log          = aarch64_tr_disas_log,
+};
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 4ea5f70..4b1230b 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11897,7 +11897,9 @@ static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
         TCGv_i32 tmp = tcg_temp_new_i32();
         tcg_gen_movi_i32(tmp, 0);
         store_cpu_field(tmp, condexec_bits);
+        tcg_temp_free_i32(tmp);
     }
+    tcg_clear_temp_count();
 }
 
 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
@@ -12017,6 +12019,7 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
     }
 
     dc->base.pc_next = dc->pc;
+    translator_loop_temp_check(&dc->base);
 }
 
 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
@@ -12131,6 +12134,9 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
             gen_goto_tb(dc, 1, dc->pc);
         }
     }
+
+    /* Functions above can change dc->pc, so re-align db->pc_next */
+    dc->base.pc_next = dc->pc;
 }
 
 static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
@@ -12142,99 +12148,29 @@ static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
                      dc->thumb | (dc->sctlr_b << 1));
 }
 
+static const TranslatorOps arm_translator_ops = {
+    .init_disas_context = arm_tr_init_disas_context,
+    .tb_start           = arm_tr_tb_start,
+    .insn_start         = arm_tr_insn_start,
+    .breakpoint_check   = arm_tr_breakpoint_check,
+    .translate_insn     = arm_tr_translate_insn,
+    .tb_stop            = arm_tr_tb_stop,
+    .disas_log          = arm_tr_disas_log,
+};
+
 /* generate intermediate code for basic block 'tb'.  */
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
-    DisasContext dc1, *dc = &dc1;
-    int max_insns;
+    DisasContext dc;
+    const TranslatorOps *ops = &arm_translator_ops;
 
-    /* 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.
-     */
+#ifdef TARGET_AARCH64
     if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
-        gen_intermediate_code_a64(&dc->base, cs, tb);
-        return;
-    }
-
-    dc->base.tb = tb;
-    dc->base.pc_first = dc->base.tb->pc;
-    dc->base.pc_next = dc->base.pc_first;
-    dc->base.is_jmp = DISAS_NEXT;
-    dc->base.num_insns = 0;
-    dc->base.singlestep_enabled = cs->singlestep_enabled;
-
-    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;
-    }
-    max_insns = arm_tr_init_disas_context(&dc->base, cs, max_insns);
-
-    gen_tb_start(tb);
-
-    tcg_clear_temp_count();
-    arm_tr_tb_start(&dc->base, cs);
-
-    do {
-        dc->base.num_insns++;
-        arm_tr_insn_start(&dc->base, cs);
-
-        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
-            CPUBreakpoint *bp;
-            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
-                if (bp->pc == dc->base.pc_next) {
-                    if (arm_tr_breakpoint_check(&dc->base, cs, bp)) {
-                        break;
-                    }
-                }
-            }
-            if (dc->base.is_jmp > DISAS_TOO_MANY) {
-                break;
-            }
-        }
-
-        if (dc->base.num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
-            gen_io_start();
-        }
-
-        arm_tr_translate_insn(&dc->base, cs);
-
-        if (tcg_check_temp_count()) {
-            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
-                    dc->pc);
-        }
-
-        if (!dc->base.is_jmp && (tcg_op_buf_full() || singlestep ||
-                            dc->base.num_insns >= max_insns)) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-        }
-    } while (!dc->base.is_jmp);
-
-    if (dc->base.tb->cflags & CF_LAST_IO) {
-        gen_io_end();
-    }
-
-    arm_tr_tb_stop(&dc->base, cs);
-
-    gen_tb_end(tb, dc->base.num_insns);
-
-    tb->size = dc->pc - dc->base.pc_first;
-    tb->icount = dc->base.num_insns;
-
-#ifdef DEBUG_DISAS
-    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) &&
-        qemu_log_in_addr_range(dc->base.pc_first)) {
-        qemu_log_lock();
-        qemu_log("----------------\n");
-        arm_tr_disas_log(&dc->base, cs);
-        qemu_log("\n");
-        qemu_log_unlock();
+        ops = &aarch64_translator_ops;
     }
 #endif
+
+    translator_loop(ops, &dc.base, cpu, tb);
 }
 
 static const char *cpu_mode_names[16] = {
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 31/34] target/arm: [a64] Move page and ss checks to init_disas_context
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (29 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 30/34] target/arm: [tcg] Port to generic translation framework Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 23:14   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 32/34] target/arm: Move ss check " Richard Henderson
                   ` (3 subsequent siblings)
  34 siblings, 1 reply; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

Since AArch64 uses a fixed-width ISA, we can pre-compute the number of
insns remaining on the page.  Also, we can check for single-step once.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate-a64.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 1aa4c14..41e5cc3 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -11196,6 +11196,7 @@ static int aarch64_tr_init_disas_context(DisasContextBase *dcbase,
     DisasContext *dc = container_of(dcbase, DisasContext, base);
     CPUARMState *env = cpu->env_ptr;
     ARMCPU *arm_cpu = arm_env_get_cpu(env);
+    int bound;
 
     dc->pc = dc->base.pc_first;
     dc->condjmp = 0;
@@ -11244,8 +11245,14 @@ static int aarch64_tr_init_disas_context(DisasContextBase *dcbase,
     dc->is_ldex = false;
     dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
 
-    dc->next_page_start =
-        (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+    /* Bound the number of insns to execute to those left on the page.  */
+    bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
+
+    /* If architectural single step active, limit to 1.  */
+    if (dc->ss_active) {
+        bound = 1;
+    }
+    max_insns = MIN(max_insns, bound);
 
     init_tmp_a64_array(dc);
 
@@ -11313,12 +11320,6 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
         disas_a64_insn(env, dc);
     }
 
-    if (dc->base.is_jmp == DISAS_NEXT) {
-        if (dc->ss_active || dc->pc >= dc->next_page_start) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-        }
-    }
-
     dc->base.pc_next = dc->pc;
     translator_loop_temp_check(&dc->base);
 }
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 32/34] target/arm: Move ss check to init_disas_context
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (30 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 31/34] target/arm: [a64] Move page and ss checks to init_disas_context Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 23:17   ` Emilio G. Cota
  2017-07-22  9:07   ` Lluís Vilanova
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 33/34] target/arm: Split out thumb_tr_translate_insn Richard Henderson
                   ` (2 subsequent siblings)
  34 siblings, 2 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

We can check for single-step just once.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 4b1230b..ebe1c1a 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11845,6 +11845,11 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase,
     dc->next_page_start =
         (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
 
+    /* If architectural single step active, limit to 1.  */
+    if (is_singlestepping(dc)) {
+        max_insns = 1;
+    }
+
     cpu_F0s = tcg_temp_new_i32();
     cpu_F1s = tcg_temp_new_i32();
     cpu_F0d = tcg_temp_new_i64();
@@ -12000,11 +12005,9 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
          * Also stop translation when a page boundary is reached.  This
          * ensures prefetch aborts occur at the right place.  */
 
-        if (is_singlestepping(dc)) {
-            dc->base.is_jmp = DISAS_TOO_MANY;
-        } else if ((dc->pc >= dc->next_page_start) ||
-                   ((dc->pc >= dc->next_page_start - 3) &&
-                    insn_crosses_page(env, dc))) {
+        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
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 33/34] target/arm: Split out thumb_tr_translate_insn
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (31 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 32/34] target/arm: Move ss check " Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 23:24   ` Emilio G. Cota
  2017-07-22  0:35   ` Emilio G. Cota
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 34/34] target/arm: Perform per-insn cross-page check only for Thumb Richard Henderson
  2017-07-15 10:15 ` [Qemu-devel] [PATCH v14 00/34] Generic translation framework no-reply
  34 siblings, 2 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

We need not check for ARM vs Thumb state in order to dispatch
disassembly of every instruction.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.c | 134 +++++++++++++++++++++++++++++++------------------
 1 file changed, 86 insertions(+), 48 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index ebe1c1a..d7c3c10 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11944,20 +11944,17 @@ static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
     return true;
 }
 
-static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
+static bool arm_pre_translate_insn(DisasContext *dc)
 {
-    DisasContext *dc = container_of(dcbase, DisasContext, base);
-    CPUARMState *env = cpu->env_ptr;
-
 #ifdef CONFIG_USER_ONLY
-        /* Intercept jump to the magic kernel page.  */
-        if (dc->pc >= 0xffff0000) {
-            /* We always get here via a jump, so know we are not in a
-               conditional execution block.  */
-            gen_exception_internal(EXCP_KERNEL_TRAP);
-            dc->base.is_jmp = DISAS_NORETURN;
-            return;
-        }
+    /* Intercept jump to the magic kernel page.  */
+    if (dc->pc >= 0xffff0000) {
+        /* We always get here via a jump, so know we are not in a
+           conditional execution block.  */
+        gen_exception_internal(EXCP_KERNEL_TRAP);
+        dc->base.is_jmp = DISAS_NORETURN;
+        return true;
+    }
 #endif
 
     if (dc->ss_active && !dc->pstate_ss) {
@@ -11975,54 +11972,82 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
         gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
                       default_exception_el(dc));
         dc->base.is_jmp = DISAS_NORETURN;
-        return;
+        return true;
     }
 
-    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);
+    return false;
+}
+
+static void arm_post_translate_insn(CPUARMState *env, DisasContext *dc)
+{
+    /* 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).
+     */
+    if (dc->base.is_jmp == DISAS_NEXT
+        && (dc->pc >= dc->next_page_start
+            || (dc->pc >= dc->next_page_start - 3
+                && insn_crosses_page(env, dc)))) {
+        dc->base.is_jmp = DISAS_TOO_MANY;
     }
 
     if (dc->condjmp && !dc->base.is_jmp) {
         gen_set_label(dc->condlabel);
         dc->condjmp = 0;
     }
+    dc->base.pc_next = dc->pc;
+    translator_loop_temp_check(&dc->base);
+}
 
-    if (dc->base.is_jmp == DISAS_NEXT) {
-        /* 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 (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).
-             */
-            dc->base.is_jmp = DISAS_TOO_MANY;
+static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    CPUARMState *env = cpu->env_ptr;
+    unsigned int insn;
+
+    if (arm_pre_translate_insn(dc)) {
+        return;
+    }
+
+    insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
+    dc->pc += 4;
+    disas_arm_insn(dc, insn);
+
+    arm_post_translate_insn(env, dc);
+}
+
+static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
+{
+    DisasContext *dc = container_of(dcbase, DisasContext, base);
+    CPUARMState *env = cpu->env_ptr;
+
+    if (arm_pre_translate_insn(dc)) {
+        return;
+    }
+
+    disas_thumb_insn(env, dc);
+
+    /* Advance the Thumb condexec condition.  */
+    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;
         }
     }
 
-    dc->base.pc_next = dc->pc;
-    translator_loop_temp_check(&dc->base);
+    arm_post_translate_insn(env, dc);
 }
 
 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
@@ -12161,12 +12186,25 @@ static const TranslatorOps arm_translator_ops = {
     .disas_log          = arm_tr_disas_log,
 };
 
+static const TranslatorOps thumb_translator_ops = {
+    .init_disas_context = arm_tr_init_disas_context,
+    .tb_start           = arm_tr_tb_start,
+    .insn_start         = arm_tr_insn_start,
+    .breakpoint_check   = arm_tr_breakpoint_check,
+    .translate_insn     = thumb_tr_translate_insn,
+    .tb_stop            = arm_tr_tb_stop,
+    .disas_log          = arm_tr_disas_log,
+};
+
 /* generate intermediate code for basic block 'tb'.  */
 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
 {
     DisasContext dc;
     const TranslatorOps *ops = &arm_translator_ops;
 
+    if (ARM_TBFLAG_THUMB(tb->flags)) {
+        ops = &thumb_translator_ops;
+    }
 #ifdef TARGET_AARCH64
     if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
         ops = &aarch64_translator_ops;
-- 
2.9.4

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

* [Qemu-devel] [PATCH v14 34/34] target/arm: Perform per-insn cross-page check only for Thumb
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (32 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 33/34] target/arm: Split out thumb_tr_translate_insn Richard Henderson
@ 2017-07-15  9:42 ` Richard Henderson
  2017-07-21 23:29   ` Emilio G. Cota
  2017-07-15 10:15 ` [Qemu-devel] [PATCH v14 00/34] Generic translation framework no-reply
  34 siblings, 1 reply; 67+ messages in thread
From: Richard Henderson @ 2017-07-15  9:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: vilanova, cota, alex.bennee, crosthwaite.peter, pbonzini

ARM is a fixed-length ISA and we can compute the page crossing
condition exactly once during init_disas_context.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target/arm/translate.c | 57 +++++++++++++++++++++++++++++---------------------
 1 file changed, 33 insertions(+), 24 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index d7c3c10..5b6368f 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11850,6 +11850,13 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase,
         max_insns = 1;
     }
 
+    /* ARM is a fixed-length ISA.  Bound the number of insns to execute
+       to those left on the page.  */
+    if (!dc->thumb) {
+        int bound = (dc->next_page_start - dc->base.pc_first) / 4;
+        max_insns = MIN(max_insns, bound);
+    }
+
     cpu_F0s = tcg_temp_new_i32();
     cpu_F1s = tcg_temp_new_i32();
     cpu_F0d = tcg_temp_new_i64();
@@ -11978,29 +11985,8 @@ static bool arm_pre_translate_insn(DisasContext *dc)
     return false;
 }
 
-static void arm_post_translate_insn(CPUARMState *env, DisasContext *dc)
+static void arm_post_translate_insn(DisasContext *dc)
 {
-    /* 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).
-     */
-    if (dc->base.is_jmp == DISAS_NEXT
-        && (dc->pc >= dc->next_page_start
-            || (dc->pc >= dc->next_page_start - 3
-                && insn_crosses_page(env, dc)))) {
-        dc->base.is_jmp = DISAS_TOO_MANY;
-    }
-
     if (dc->condjmp && !dc->base.is_jmp) {
         gen_set_label(dc->condlabel);
         dc->condjmp = 0;
@@ -12023,7 +12009,10 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
     dc->pc += 4;
     disas_arm_insn(dc, insn);
 
-    arm_post_translate_insn(env, dc);
+    /* ARM is a fixed-length ISA.  We performed the cross-page check
+       in init_disas_context by adjusting max_insns.  */
+
+    arm_post_translate_insn(dc);
 }
 
 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
@@ -12047,7 +12036,27 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
         }
     }
 
-    arm_post_translate_insn(env, dc);
+    /* Thumb is a variable-length ISA.  Stop translation when the next insn
+     * will touch a new page.  This ensures that 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).
+     */
+    if (dc->base.is_jmp == DISAS_NEXT
+        && (dc->pc >= dc->next_page_start
+            || (dc->pc >= dc->next_page_start - 3
+                && insn_crosses_page(env, dc)))) {
+        dc->base.is_jmp = DISAS_TOO_MANY;
+    }
+
+    arm_post_translate_insn(dc);
 }
 
 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
-- 
2.9.4

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

* Re: [Qemu-devel] [PATCH v14 00/34] Generic translation framework
  2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
                   ` (33 preceding siblings ...)
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 34/34] target/arm: Perform per-insn cross-page check only for Thumb Richard Henderson
@ 2017-07-15 10:15 ` no-reply
  34 siblings, 0 replies; 67+ messages in thread
From: no-reply @ 2017-07-15 10:15 UTC (permalink / raw)
  To: rth
  Cc: famz, qemu-devel, pbonzini, cota, alex.bennee, vilanova,
	crosthwaite.peter

Hi,

This series seems to have some coding style problems. See output below for
more information:

Message-id: 20170715094243.28371-1-rth@twiddle.net
Subject: [Qemu-devel] [PATCH v14 00/34] Generic translation framework
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 - [tag update]      patchew/20170710204521.2058-1-rth@twiddle.net -> patchew/20170710204521.2058-1-rth@twiddle.net
 * [new tag]         patchew/20170715094243.28371-1-rth@twiddle.net -> patchew/20170715094243.28371-1-rth@twiddle.net
Switched to a new branch 'test'
3f2e70e target/arm: Perform per-insn cross-page check only for Thumb
24e9350 target/arm: Split out thumb_tr_translate_insn
253dd0d target/arm: Move ss check to init_disas_context
9a77e52 target/arm: [a64] Move page and ss checks to init_disas_context
a6cbc9a target/arm: [tcg] Port to generic translation framework
3d38ce2 target/arm: [tcg, a64] Port to disas_log
eddb40e target/arm: [tcg] Port to disas_log
4c33728 target/arm: [tcg, a64] Port to tb_stop
6904495 target/arm: [tcg] Port to tb_stop
874d408 target/arm: [tcg, a64] Port to translate_insn
b6bd28d target/arm: [tcg] Port to translate_insn
d575933 target/arm: [tcg, a64] Port to breakpoint_check
d79e9e5 target/arm: [tcg, a64] Port to insn_start
a34da7a target/arm: [tcg] Port to insn_start
8e6770c target/arm: [tcg] Port to tb_start
f63f314 target/arm: [tcg, a64] Port to init_disas_context
c81fcd4 target/arm: [tcg] Port to init_disas_context
9749b3e target/arm: [tcg] Port to DisasContextBase
3b0e4b5 target/i386: [tcg] Port to generic translation framework
f9ed7a5 target/i386: [tcg] Port to disas_log
97fb814 target/i386: [tcg] Port to tb_stop
7ec9c0c target/i386: [tcg] Port to translate_insn
5b58ae7 target/i386: [tcg] Port to breakpoint_check
68bf26a target/i386: [tcg] Port to insn_start
6e70ea1 target/i386: [tcg] Port to init_disas_context
0c3d720 target/i386: [tcg] Port to DisasContextBase
2272588 tcg: Add generic translation framework
b5a537a target/arm: Set is_jmp properly after single-stepping
7fd4bd1 target/arm: Delay check for magic kernel page
23dbe85 target: [tcg] Use a generic enum for DISAS_ values
54b4f6d target/arm: Use DISAS_NORETURN
c2e1dc3 target/i386: Use generic DISAS_* enumerators
2900a33 tcg: Add generic DISAS_NORETURN
42d07ca Pass generic CPUState to gen_intermediate_code()

=== OUTPUT BEGIN ===
Checking PATCH 1/34: Pass generic CPUState to gen_intermediate_code()...
WARNING: line over 80 characters
#125: FILE: target/arm/translate.h:158:
+static inline void gen_intermediate_code_a64(CPUState *cpu, TranslationBlock *tb)

total: 0 errors, 1 warnings, 303 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 2/34: tcg: Add generic DISAS_NORETURN...
Checking PATCH 3/34: target/i386: Use generic DISAS_* enumerators...
Checking PATCH 4/34: target/arm: Use DISAS_NORETURN...
Checking PATCH 5/34: target: [tcg] Use a generic enum for DISAS_ values...
Checking PATCH 6/34: target/arm: Delay check for magic kernel page...
Checking PATCH 7/34: target/arm: Set is_jmp properly after single-stepping...
Checking PATCH 8/34: tcg: Add generic translation framework...
Checking PATCH 9/34: target/i386: [tcg] Port to DisasContextBase...
WARNING: line over 80 characters
#487: FILE: target/i386/translate.c:8513:
+                != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)

WARNING: line over 80 characters
#527: FILE: target/i386/translate.c:8551:
+        log_target_disas(cs, dc->base.pc_first, dc->base.pc_next - dc->base.pc_first,

total: 0 errors, 2 warnings, 478 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 10/34: target/i386: [tcg] Port to init_disas_context...
Checking PATCH 11/34: target/i386: [tcg] Port to insn_start...
Checking PATCH 12/34: target/i386: [tcg] Port to breakpoint_check...
Checking PATCH 13/34: target/i386: [tcg] Port to translate_insn...
Checking PATCH 14/34: target/i386: [tcg] Port to tb_stop...
Checking PATCH 15/34: target/i386: [tcg] Port to disas_log...
Checking PATCH 16/34: target/i386: [tcg] Port to generic translation framework...
Checking PATCH 17/34: target/arm: [tcg] Port to DisasContextBase...
WARNING: line over 80 characters
#55: FILE: target/arm/translate-a64.c:351:
+    if (s->base.singlestep_enabled || s->ss_active || (s->base.tb->cflags & CF_LAST_IO)) {

WARNING: line over 80 characters
#222: FILE: target/arm/translate-a64.c:11223:
+    dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags));

ERROR: line over 90 characters
#278: FILE: target/arm/translate-a64.c:11289:
+                           included in [dc->base.tb->pc, dc->base.tb->pc + dc->base.tb->size) in order

WARNING: line over 80 characters
#291: FILE: target/arm/translate-a64.c:11301:
+        if (dc->base.num_insns == max_insns && (dc->base.tb->cflags & CF_LAST_IO)) {

ERROR: space required before the open parenthesis '('
#781: FILE: target/arm/translate.c:12096:
+        switch(dc->base.is_jmp) {

WARNING: line over 80 characters
#854: FILE: target/arm/translate.h:159:
+static inline void gen_intermediate_code_a64(DisasContextBase *db, CPUState *cpu,

total: 2 errors, 4 warnings, 762 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 18/34: target/arm: [tcg] Port to init_disas_context...
WARNING: line over 80 characters
#75: FILE: target/arm/translate.c:11810:
+    dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags));

total: 0 errors, 1 warnings, 128 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 19/34: target/arm: [tcg, a64] Port to init_disas_context...
Checking PATCH 20/34: target/arm: [tcg] Port to tb_start...
Checking PATCH 21/34: target/arm: [tcg] Port to insn_start...
Checking PATCH 22/34: target/arm: [tcg, a64] Port to insn_start...
Checking PATCH 23/34: target/arm: [tcg, a64] Port to breakpoint_check...
Checking PATCH 24/34: target/arm: [tcg] Port to translate_insn...
Checking PATCH 25/34: target/arm: [tcg, a64] Port to translate_insn...
Checking PATCH 26/34: target/arm: [tcg] Port to tb_stop...
Checking PATCH 27/34: target/arm: [tcg, a64] Port to tb_stop...
Checking PATCH 28/34: target/arm: [tcg] Port to disas_log...
Checking PATCH 29/34: target/arm: [tcg, a64] Port to disas_log...
Checking PATCH 30/34: target/arm: [tcg] Port to generic translation framework...
Checking PATCH 31/34: target/arm: [a64] Move page and ss checks to init_disas_context...
Checking PATCH 32/34: target/arm: Move ss check to init_disas_context...
Checking PATCH 33/34: target/arm: Split out thumb_tr_translate_insn...
Checking PATCH 34/34: target/arm: Perform per-insn cross-page check only for Thumb...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

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

* Re: [Qemu-devel] [PATCH v14 01/34] Pass generic CPUState to gen_intermediate_code()
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 01/34] Pass generic CPUState to gen_intermediate_code() Richard Henderson
@ 2017-07-17 22:56   ` Emilio G. Cota
  0 siblings, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-17 22:56 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:10 -1000, Richard Henderson wrote:
> From: Lluís Vilanova <vilanova@ac.upc.edu>
> 
> 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>
> Reviewed-by: Alex Benneé <alex.benee@linaro.org>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 02/34] tcg: Add generic DISAS_NORETURN
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 02/34] tcg: Add generic DISAS_NORETURN Richard Henderson
@ 2017-07-21 21:25   ` Emilio G. Cota
  2017-07-21 22:32   ` Lluís Vilanova
  1 sibling, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 21:25 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:11 -1000, Richard Henderson wrote:
> This will allow some amount of cleanup to happen before
> switching the backends over to enum DisasJumpType.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 03/34] target/i386: Use generic DISAS_* enumerators
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 03/34] target/i386: Use generic DISAS_* enumerators Richard Henderson
@ 2017-07-21 21:25   ` Emilio G. Cota
  2017-07-21 22:35   ` Lluís Vilanova
  1 sibling, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 21:25 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:12 -1000, Richard Henderson wrote:
> This target is not sophisticated in its use of cleanups at the
> end of the translation loop.  For the most part, any condition
> that exits the TB is dealt with by emitting the exiting opcode
> right then and there.  Therefore the only is_jmp indicator that
> is needed is DISAS_NORETURN.
> 
> For two stack segment modifying cases, we have not yet exited
> the TB (therefore DISAS_NORETURN feels wrong), but intend to exit.
> The caller of gen_movl_seg_T0 currently checks for any non-zero
> value, therefore DISAS_TOO_MANY seems acceptable for that usage.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 04/34] target/arm: Use DISAS_NORETURN
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 04/34] target/arm: Use DISAS_NORETURN Richard Henderson
@ 2017-07-21 21:25   ` Emilio G. Cota
  2017-07-21 22:38   ` Emilio G. Cota
  1 sibling, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 21:25 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:13 -1000, Richard Henderson wrote:
> Fold DISAS_EXC and DISAS_TB_JUMP into DISAS_NORETURN.
> 
> In both cases all following code is dead.  In the first
> case because we have exited the TB via exception; in the
> second case because we have exited the TB via goto_tb
> and its associated machinery.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 06/34] target/arm: Delay check for magic kernel page
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 06/34] target/arm: Delay check for magic kernel page Richard Henderson
@ 2017-07-21 21:27   ` Emilio G. Cota
  0 siblings, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 21:27 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:15 -1000, Richard Henderson wrote:
> There's nothing magic about the exception that we generate in order
> to execute the magic kernel page.  We can and should allow gdb to
> set a breakpoint at this location.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 07/34] target/arm: Set is_jmp properly after single-stepping
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 07/34] target/arm: Set is_jmp properly after single-stepping Richard Henderson
@ 2017-07-21 21:37   ` Emilio G. Cota
  2017-07-22 10:39     ` Richard Henderson
  2017-07-21 22:39   ` Lluís Vilanova
  1 sibling, 1 reply; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 21:37 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:16 -1000, Richard Henderson wrote:
> We have generated an exception, so use DISAS_NORETURN.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  target/arm/translate-a64.c | 1 +
>  target/arm/translate.c     | 4 +++-
>  2 files changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 342ff7c..657684b 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -11285,6 +11285,7 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
>                          dc->is_jmp = DISAS_UPDATE;
>                      } else {
>                          gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
> +                        dc->is_jmp = DISAS_NORETURN;
>                          /* The address covered by the breakpoint must be
>                             included in [tb->pc, tb->pc + tb->size) in order
>                             to for it to be properly cleared -- thus we
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 2ae68ce..83e5491 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -11942,6 +11942,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
>                          dc->is_jmp = DISAS_UPDATE;
>                      } else {
>                          gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
> +                        dc->is_jmp = DISAS_NORETURN;

gen_exception_internal_insn already sets dc->is_jmp to DISAS_NORETURN,
as per patch 04/34:
@@ -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 = DISAS_NORETURN;
 }

This applies to both arm and a64.

Why do we need to set is_jmp again, then?

		E.

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

* Re: [Qemu-devel] [PATCH v14 10/34] target/i386: [tcg] Port to init_disas_context
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 10/34] target/i386: [tcg] Port to init_disas_context Richard Henderson
@ 2017-07-21 21:54   ` Emilio G. Cota
  0 siblings, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 21:54 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:19 -1000, Richard Henderson wrote:
> From: Lluís Vilanova <vilanova@ac.upc.edu>
> 
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Reviewed-by: Richard Henderson <rth@twiddle.net>
> Reviewed-by: Alex Benneé <alex.benee@linaro.org>
> Message-Id: <150002122448.22386.16854673576827449259.stgit@frigg.lan>
> [rth: Adjust for max_insns interface change.]
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 23/34] target/arm: [tcg, a64] Port to breakpoint_check
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 23/34] target/arm: [tcg, a64] Port to breakpoint_check Richard Henderson
@ 2017-07-21 22:12   ` Emilio G. Cota
  0 siblings, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 22:12 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:32 -1000, Richard Henderson wrote:
> From: Lluís Vilanova <vilanova@ac.upc.edu>
> 
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Reviewed-by: Richard Henderson <rth@twiddle.net>
> Message-Id: <150002461630.22386.14827196109258040543.stgit@frigg.lan>
> [rth: Use DISAS_TOO_MANY for "execute only one more" after bp.]
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 24/34] target/arm: [tcg] Port to translate_insn
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 24/34] target/arm: [tcg] Port to translate_insn Richard Henderson
@ 2017-07-21 22:24   ` Emilio G. Cota
  2017-07-21 23:20   ` Emilio G. Cota
  1 sibling, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 22:24 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:33 -1000, Richard Henderson wrote:
> From: Lluís Vilanova <vilanova@ac.upc.edu>
> 
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Message-Id: <150002485863.22386.13949856269576226529.stgit@frigg.lan>
> [rth: Adjust for translate_insn interface change.]
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 25/34] target/arm: [tcg, a64] Port to translate_insn
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 25/34] target/arm: [tcg, a64] " Richard Henderson
@ 2017-07-21 22:28   ` Emilio G. Cota
  0 siblings, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 22:28 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:34 -1000, Richard Henderson wrote:
> From: Lluís Vilanova <vilanova@ac.upc.edu>
> 
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Message-Id: <150002510079.22386.10164419868911710218.stgit@frigg.lan>
> [rth: Adjust for translate_insn interface change.]
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 02/34] tcg: Add generic DISAS_NORETURN
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 02/34] tcg: Add generic DISAS_NORETURN Richard Henderson
  2017-07-21 21:25   ` Emilio G. Cota
@ 2017-07-21 22:32   ` Lluís Vilanova
  1 sibling, 0 replies; 67+ messages in thread
From: Lluís Vilanova @ 2017-07-21 22:32 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, cota, alex.bennee, crosthwaite.peter, pbonzini

Richard Henderson writes:

> This will allow some amount of cleanup to happen before
> switching the backends over to enum DisasJumpType.

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

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


> ---
>  include/exec/exec-all.h | 1 +
>  1 file changed, 1 insertion(+)

> diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
> index 48d9d11..6760078 100644
> --- a/include/exec/exec-all.h
> +++ b/include/exec/exec-all.h
> @@ -40,6 +40,7 @@ typedef ram_addr_t tb_page_addr_t;
>  #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 */
> +#define DISAS_NORETURN 4 /* the tb has already been exited */
 
>  #include "qemu/log.h"
 
> -- 
> 2.9.4

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

* Re: [Qemu-devel] [PATCH v14 03/34] target/i386: Use generic DISAS_* enumerators
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 03/34] target/i386: Use generic DISAS_* enumerators Richard Henderson
  2017-07-21 21:25   ` Emilio G. Cota
@ 2017-07-21 22:35   ` Lluís Vilanova
  2017-07-22 10:31     ` Richard Henderson
  1 sibling, 1 reply; 67+ messages in thread
From: Lluís Vilanova @ 2017-07-21 22:35 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, pbonzini, cota, alex.bennee, crosthwaite.peter

Richard Henderson writes:

> This target is not sophisticated in its use of cleanups at the
> end of the translation loop.  For the most part, any condition
> that exits the TB is dealt with by emitting the exiting opcode
> right then and there.  Therefore the only is_jmp indicator that
> is needed is DISAS_NORETURN.

> For two stack segment modifying cases, we have not yet exited
> the TB (therefore DISAS_NORETURN feels wrong), but intend to exit.
> The caller of gen_movl_seg_T0 currently checks for any non-zero
> value, therefore DISAS_TOO_MANY seems acceptable for that usage.

> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  target/i386/translate.c | 28 +++++++++++++++-------------
>  1 file changed, 15 insertions(+), 13 deletions(-)

> diff --git a/target/i386/translate.c b/target/i386/translate.c
> index cab9e32..3ffbf1b 100644
> --- a/target/i386/translate.c
> +++ b/target/i386/translate.c
> @@ -31,6 +31,7 @@
>  #include "trace-tcg.h"
>  #include "exec/log.h"
 
> +#define DISAS_TOO_MANY 5

Why is this one not added as a generic define too (like DISAS_NORETURN in prev
patch)?


Thanks,
  Lluis

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

* Re: [Qemu-devel] [PATCH v14 04/34] target/arm: Use DISAS_NORETURN
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 04/34] target/arm: Use DISAS_NORETURN Richard Henderson
  2017-07-21 21:25   ` Emilio G. Cota
@ 2017-07-21 22:38   ` Emilio G. Cota
  1 sibling, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 22:38 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:13 -1000, Richard Henderson wrote:
> Fold DISAS_EXC and DISAS_TB_JUMP into DISAS_NORETURN.
> 
> In both cases all following code is dead.  In the first
> case because we have exited the TB via exception; in the
> second case because we have exited the TB via goto_tb
> and its associated machinery.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  target/arm/translate.h     |  8 ++------
>  target/arm/translate-a64.c | 37 ++++++++++++++++++++-----------------
>  target/arm/translate.c     | 15 ++++++++-------
>  3 files changed, 30 insertions(+), 30 deletions(-)
> 
(snip)
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index e80cc35..fea76fb 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
(snip)
> @@ -12081,6 +12081,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
>          default:
>              /* FIXME: Single stepping a WFI insn will not halt the CPU. */
>              gen_singlestep_exception(dc);
> +        case DISAS_NORETURN:
> +            break;

Missing '/* fall-through */' above 'case DISAS_NORETURN'. Or just 'break' as
we otherwise end up doing in patch 26.

		E.

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

* Re: [Qemu-devel] [PATCH v14 07/34] target/arm: Set is_jmp properly after single-stepping
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 07/34] target/arm: Set is_jmp properly after single-stepping Richard Henderson
  2017-07-21 21:37   ` Emilio G. Cota
@ 2017-07-21 22:39   ` Lluís Vilanova
  1 sibling, 0 replies; 67+ messages in thread
From: Lluís Vilanova @ 2017-07-21 22:39 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, pbonzini, cota, alex.bennee, crosthwaite.peter

Richard Henderson writes:

> We have generated an exception, so use DISAS_NORETURN.

Shouldn't this be folded into patch 4?

Thanks,
  Lluis


> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  target/arm/translate-a64.c | 1 +
>  target/arm/translate.c     | 4 +++-
>  2 files changed, 4 insertions(+), 1 deletion(-)

> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 342ff7c..657684b 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -11285,6 +11285,7 @@ void gen_intermediate_code_a64(CPUState *cs, TranslationBlock *tb)
dc-> is_jmp = DISAS_UPDATE;
>                      } else {
>                          gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
> +                        dc->is_jmp = DISAS_NORETURN;
>                          /* The address covered by the breakpoint must be
>                             included in [tb->pc, tb->pc + tb->size) in order
>                             to for it to be properly cleared -- thus we
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 2ae68ce..83e5491 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -11942,6 +11942,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
dc-> is_jmp = DISAS_UPDATE;
>                      } else {
>                          gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
> +                        dc->is_jmp = DISAS_NORETURN;
>                          /* The address covered by the breakpoint must be
>                             included in [tb->pc, tb->pc + tb->size) in order
>                             to for it to be properly cleared -- thus we
> @@ -11986,7 +11987,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
>              assert(num_insns == 1);
>              gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
>                            default_exception_el(dc));
> -            goto done_generating;
> +            dc->is_jmp = DISAS_NORETURN;
> +            break;
>          }
 
>          if (dc->thumb) {
> -- 
> 2.9.4

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

* Re: [Qemu-devel] [PATCH v14 26/34] target/arm: [tcg] Port to tb_stop
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 26/34] target/arm: [tcg] Port to tb_stop Richard Henderson
@ 2017-07-21 22:41   ` Emilio G. Cota
  0 siblings, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 22:41 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:35 -1000, Richard Henderson wrote:
> From: Lluís Vilanova <vilanova@ac.upc.edu>
> 
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Message-Id: <150002534291.22386.13499916738708680298.stgit@frigg.lan>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
(snip)
> @@ -12135,6 +12063,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
>          default:
>              /* FIXME: Single stepping a WFI insn will not halt the CPU. */
>              gen_singlestep_exception(dc);
> +            break;
>          case DISAS_NORETURN:
>              break;
>          }

See my comment to patch 4.

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 27/34] target/arm: [tcg, a64] Port to tb_stop
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 27/34] target/arm: [tcg, a64] " Richard Henderson
@ 2017-07-21 22:47   ` Emilio G. Cota
  0 siblings, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 22:47 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:36 -1000, Richard Henderson wrote:
> From: Lluís Vilanova <vilanova@ac.upc.edu>
> 
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Reviewed-by: Richard Henderson <rth@twiddle.net>
> Message-Id: <150002558503.22386.1149037590886263349.stgit@frigg.lan>
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 08/34] tcg: Add generic translation framework
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 08/34] tcg: Add generic translation framework Richard Henderson
@ 2017-07-21 22:49   ` Lluís Vilanova
  2017-07-21 23:38   ` Emilio G. Cota
  1 sibling, 0 replies; 67+ messages in thread
From: Lluís Vilanova @ 2017-07-21 22:49 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, cota, alex.bennee, crosthwaite.peter, pbonzini

Richard Henderson writes:

> From: Lluís Vilanova <vilanova@ac.upc.edu>
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Message-Id: <150002073981.22386.9870422422367410100.stgit@frigg.lan>
> [rth: Moved max_insns adjustment from tb_start to init_disas_context.
> Removed pc_next return from translate_insn.
> Removed tcg_check_temp_count from generic loop.
> Moved gen_io_end to exactly match gen_io_start.
> Use qemu_log instead of error_report for temporary leaks.
> Moved TB size/icount assignments before disas_log.]
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  include/exec/translator.h | 101 +++++++++++++++++++++++++++++++++++
>  accel/tcg/translator.c    | 133 ++++++++++++++++++++++++++++++++++++++++++++++
>  accel/tcg/Makefile.objs   |   1 +
>  3 files changed, 235 insertions(+)
>  create mode 100644 accel/tcg/translator.c

> diff --git a/include/exec/translator.h b/include/exec/translator.h
> index b51b8f8..aa84376 100644
> --- a/include/exec/translator.h
> +++ b/include/exec/translator.h
> @@ -10,6 +10,19 @@
>  #ifndef EXEC__TRANSLATOR_H
>  #define EXEC__TRANSLATOR_H
 
> +/*
> + * Include this header from a target-specific file, and add a
> + *
> + *     DisasContextBase base;
> + *
> + * member in your target-specific DisasContext.
> + */
> +
> +
> +#include "exec/exec-all.h"
> +#include "tcg/tcg.h"
> +
> +
>  /**
>   * DisasJumpType:
>   * @DISAS_NEXT: Next instruction in program order.
> @@ -37,4 +50,92 @@ typedef enum DisasJumpType {
>      DISAS_TARGET_11,
>  } 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 the target-specific portions of DisasContext struct.
> + *      The generic DisasContextBase has already been initialized.
> + *      Return max_insns, modified as necessary by db->tb->flags.
> + *
> + * @tb_start:
> + *      Emit any code required before the start of the main loop,
> + *      after the generic gen_tb_start().
> + *
> + * @insn_start:
> + *      Emit the tcg_gen_insn_start opcode.
> + *
> + * @breakpoint_check:
> + *      When called, the breakpoint has already been checked to match the PC,
> + *      but the target may decide the breakpoint missed the address
> + *      (e.g., due to conditions encoded in their flags).  Return true to
> + *      indicate that the breakpoint did hit, in which case no more breakpoints
> + *      are checked.  If the breakpoint did hit, emit any code required to
> + *      signal the exception, and set db->is_jmp as necessary to terminate
> + *      the main loop.
> + *
> + * @translate_insn:
> + *      Disassemble one instruction and set db->pc_next for the start
> + *      of the following instruction.  Set db->is_jmp as necessary to
> + *      terminate the main loop.
> + *
> + * @tb_stop:
> + *      Emit any opcodes required to exit the TB, based on db->is_jmp.
> + *
> + * @disas_log:
> + *      Print instruction disassembly to log.
> + */
> +typedef struct TranslatorOps {
> +    int (*init_disas_context)(DisasContextBase *db, CPUState *cpu,
> +                              int max_insns);
> +    void (*tb_start)(DisasContextBase *db, CPUState *cpu);
> +    void (*insn_start)(DisasContextBase *db, CPUState *cpu);
> +    bool (*breakpoint_check)(DisasContextBase *db, CPUState *cpu,
> +                             const CPUBreakpoint *bp);
> +    void (*translate_insn)(DisasContextBase *db, CPUState *cpu);
> +    void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
> +    void (*disas_log)(const DisasContextBase *db, CPUState *cpu);
> +} TranslatorOps;
> +
> +/**
> + * translator_loop:
> + * @ops: Target-specific operations.
> + * @db: Disassembly context.
> + * @cpu: Target vCPU.
> + * @tb: Translation block.
> + *
> + * Generic translator loop.
> + *
> + * Translation will stop in the following cases (in order):
> + * - When et by #TranslatorOps::insn_start.

Seems untrue; there's a tcg_debug_assert, so this should now probably be
breakpoint_check() instead.

> + * - When set by #TranslatorOps::translate_insn.
> + * - When the TCG operation buffer is full.
> + * - When single-stepping is enabled (system-wide or on the current vCPU).
> + * - When too many instructions have been translated.
> + */
> +void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
> +                     CPUState *cpu, TranslationBlock *tb);

For the "When set by #TranslatorOps:..." I'd also talk about setting is_jmp for
that, and describe the type of stop that different is_jmp values produce
(TOO_MANY is "delayed" and NORETURN is "immediate" when set in
breakpoint_check; all values are "immediate" when set in translate_insn()).


Thanks,
  Lluis

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

* Re: [Qemu-devel] [PATCH v14 29/34] target/arm: [tcg, a64] Port to disas_log
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 29/34] target/arm: [tcg, a64] " Richard Henderson
@ 2017-07-21 22:50   ` Emilio G. Cota
  0 siblings, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 22:50 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:38 -1000, Richard Henderson wrote:
> From: Lluís Vilanova <vilanova@ac.upc.edu>
> 
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Reviewed-by: Richard Henderson <rth@twiddle.net>
> Message-Id: <150002606914.22386.15524101311003685068.stgit@frigg.lan>
> [rth: Move tb->size computation and use that result.]
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 30/34] target/arm: [tcg] Port to generic translation framework
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 30/34] target/arm: [tcg] Port to generic translation framework Richard Henderson
@ 2017-07-21 23:02   ` Emilio G. Cota
  2017-07-22  0:05     ` Emilio G. Cota
  0 siblings, 1 reply; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 23:02 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:39 -1000, Richard Henderson wrote:
> From: Lluís Vilanova <vilanova@ac.upc.edu>
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Message-Id: <150002631325.22386.10348327185029496649.stgit@frigg.lan>
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  target/arm/translate.h     |   8 +---
>  target/arm/translate-a64.c | 107 ++++++++-----------------------------------
>  target/arm/translate.c     | 110 ++++++++++-----------------------------------
>  3 files changed, 42 insertions(+), 183 deletions(-)

(snip)
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 4ea5f70..4b1230b 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -11897,7 +11897,9 @@ static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
>          TCGv_i32 tmp = tcg_temp_new_i32();
>          tcg_gen_movi_i32(tmp, 0);
>          store_cpu_field(tmp, condexec_bits);
> +        tcg_temp_free_i32(tmp);

This seems unrelated to the patch. Perhaps a better place to add
this fix would be patch 20, with a mention to it in the commit log.
Or just keep it here, but mention it in the commit log.

Otherwise,

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

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

* Re: [Qemu-devel] [PATCH v14 31/34] target/arm: [a64] Move page and ss checks to init_disas_context
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 31/34] target/arm: [a64] Move page and ss checks to init_disas_context Richard Henderson
@ 2017-07-21 23:14   ` Emilio G. Cota
  0 siblings, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 23:14 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:40 -1000, Richard Henderson wrote:
> Since AArch64 uses a fixed-width ISA, we can pre-compute the number of
> insns remaining on the page.  Also, we can check for single-step once.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

Pity, if it wasn't for thumb, we could get rid of dc->next_page_start.

		E.

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

* Re: [Qemu-devel] [PATCH v14 32/34] target/arm: Move ss check to init_disas_context
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 32/34] target/arm: Move ss check " Richard Henderson
@ 2017-07-21 23:17   ` Emilio G. Cota
  2017-07-22  9:07   ` Lluís Vilanova
  1 sibling, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 23:17 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:41 -1000, Richard Henderson wrote:
> We can check for single-step just once.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 24/34] target/arm: [tcg] Port to translate_insn
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 24/34] target/arm: [tcg] Port to translate_insn Richard Henderson
  2017-07-21 22:24   ` Emilio G. Cota
@ 2017-07-21 23:20   ` Emilio G. Cota
  1 sibling, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 23:20 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:33 -1000, Richard Henderson wrote:
> From: Lluís Vilanova <vilanova@ac.upc.edu>
> 
> Incrementally paves the way towards using the generic instruction translation
> loop.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Message-Id: <150002485863.22386.13949856269576226529.stgit@frigg.lan>
> [rth: Adjust for translate_insn interface change.]
> Signed-off-by: Richard Henderson <rth@twiddle.net>
(snip)
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -11842,6 +11842,8 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase,
>      dc->is_ldex = false;
>      dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
>  
> +    dc->next_page_start =
> +        (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
>  
>      cpu_F0s = tcg_temp_new_i32();
>      cpu_F1s = tcg_temp_new_i32();
> @@ -11935,14 +11937,93 @@ static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
>      return true;
>  }
>  
> +static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
> +{
> +    DisasContext *dc = container_of(dcbase, DisasContext, base);
> +    CPUARMState *env = cpu->env_ptr;
> +
> +#ifdef CONFIG_USER_ONLY
> +        /* Intercept jump to the magic kernel page.  */
> +        if (dc->pc >= 0xffff0000) {
> +            /* We always get here via a jump, so know we are not in a
> +               conditional execution block.  */
> +            gen_exception_internal(EXCP_KERNEL_TRAP);
> +            dc->base.is_jmp = DISAS_NORETURN;
> +            return;
> +        }
> +#endif

Nit: Indent this properly here to avoid the indent fix in patch 33.

		E.

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

* Re: [Qemu-devel] [PATCH v14 33/34] target/arm: Split out thumb_tr_translate_insn
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 33/34] target/arm: Split out thumb_tr_translate_insn Richard Henderson
@ 2017-07-21 23:24   ` Emilio G. Cota
  2017-07-22  0:35   ` Emilio G. Cota
  1 sibling, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 23:24 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:42 -1000, Richard Henderson wrote:
> We need not check for ARM vs Thumb state in order to dispatch
> disassembly of every instruction.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  target/arm/translate.c | 134 +++++++++++++++++++++++++++++++------------------
>  1 file changed, 86 insertions(+), 48 deletions(-)
> 
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index ebe1c1a..d7c3c10 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -11944,20 +11944,17 @@ static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
>      return true;
>  }
>  
> -static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
> +static bool arm_pre_translate_insn(DisasContext *dc)
>  {
> -    DisasContext *dc = container_of(dcbase, DisasContext, base);
> -    CPUARMState *env = cpu->env_ptr;
> -
>  #ifdef CONFIG_USER_ONLY
> -        /* Intercept jump to the magic kernel page.  */
> -        if (dc->pc >= 0xffff0000) {
> -            /* We always get here via a jump, so know we are not in a
> -               conditional execution block.  */
> -            gen_exception_internal(EXCP_KERNEL_TRAP);
> -            dc->base.is_jmp = DISAS_NORETURN;
> -            return;
> -        }
> +    /* Intercept jump to the magic kernel page.  */
> +    if (dc->pc >= 0xffff0000) {
> +        /* We always get here via a jump, so know we are not in a
> +           conditional execution block.  */
> +        gen_exception_internal(EXCP_KERNEL_TRAP);
> +        dc->base.is_jmp = DISAS_NORETURN;
> +        return true;
> +    }

See my comment in patch 24 about this.

Other than that, this is neat.
Reviewed-by: Emilio G. Cota <cota@braap.org>

		E.

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

* Re: [Qemu-devel] [PATCH v14 34/34] target/arm: Perform per-insn cross-page check only for Thumb
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 34/34] target/arm: Perform per-insn cross-page check only for Thumb Richard Henderson
@ 2017-07-21 23:29   ` Emilio G. Cota
  0 siblings, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 23:29 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:43 -1000, Richard Henderson wrote:
> ARM is a fixed-length ISA and we can compute the page crossing
> condition exactly once during init_disas_context.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 08/34] tcg: Add generic translation framework
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 08/34] tcg: Add generic translation framework Richard Henderson
  2017-07-21 22:49   ` Lluís Vilanova
@ 2017-07-21 23:38   ` Emilio G. Cota
  1 sibling, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-21 23:38 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:17 -1000, Richard Henderson wrote:
> From: Lluís Vilanova <vilanova@ac.upc.edu>
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> Message-Id: <150002073981.22386.9870422422367410100.stgit@frigg.lan>
> [rth: Moved max_insns adjustment from tb_start to init_disas_context.
> Removed pc_next return from translate_insn.
> Removed tcg_check_temp_count from generic loop.
> Moved gen_io_end to exactly match gen_io_start.
> Use qemu_log instead of error_report for temporary leaks.
> Moved TB size/icount assignments before disas_log.]
> Signed-off-by: Richard Henderson <rth@twiddle.net>
(snip)
> +void translator_loop_temp_check(DisasContextBase *db)
> +{
> +    if (tcg_check_temp_count()) {
> +        qemu_log("warning: TCG temporary leaks before "
> +                 TARGET_FMT_lx "\n", db->pc_next);
> +    }
> +}

I dislike that we have target code calling tcg_clear_temp_count()
and then calling translator_loop_temp_check().

I suggest we either:
- Add an inline wrapping tcg_clear_temp_count(), calling it something
  like translator_loop_clear_temp_count()
- Just add a comment to this function, e.g.
  '/* pairs with tcg_clear_temp_count() */'

Ignoring that and the update needed to the docs that Lluis mentioned,

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

		E.

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

* Re: [Qemu-devel] [PATCH v14 30/34] target/arm: [tcg] Port to generic translation framework
  2017-07-21 23:02   ` Emilio G. Cota
@ 2017-07-22  0:05     ` Emilio G. Cota
  0 siblings, 0 replies; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-22  0:05 UTC (permalink / raw)
  To: Richard Henderson
  Cc: pbonzini, crosthwaite.peter, alex.bennee, qemu-devel, vilanova

On Fri, Jul 21, 2017 at 19:02:58 -0400, Emilio G. Cota wrote:
> On Fri, Jul 14, 2017 at 23:42:39 -1000, Richard Henderson wrote:
> > From: Lluís Vilanova <vilanova@ac.upc.edu>
> > 
> > Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> > Message-Id: <150002631325.22386.10348327185029496649.stgit@frigg.lan>
> > Signed-off-by: Richard Henderson <rth@twiddle.net>
> > ---
> >  target/arm/translate.h     |   8 +---
> >  target/arm/translate-a64.c | 107 ++++++++-----------------------------------
> >  target/arm/translate.c     | 110 ++++++++++-----------------------------------
> >  3 files changed, 42 insertions(+), 183 deletions(-)
> 
> (snip)
> > diff --git a/target/arm/translate.c b/target/arm/translate.c
> > index 4ea5f70..4b1230b 100644
> > --- a/target/arm/translate.c
> > +++ b/target/arm/translate.c
> > @@ -11897,7 +11897,9 @@ static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
> >          TCGv_i32 tmp = tcg_temp_new_i32();
> >          tcg_gen_movi_i32(tmp, 0);
> >          store_cpu_field(tmp, condexec_bits);
> > +        tcg_temp_free_i32(tmp);
> 
> This seems unrelated to the patch. Perhaps a better place to add
> this fix would be patch 20, with a mention to it in the commit log.
> Or just keep it here, but mention it in the commit log.

Silly me. This must go away, because store_cpu_field already
frees the temp.

		E.

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

* Re: [Qemu-devel] [PATCH v14 33/34] target/arm: Split out thumb_tr_translate_insn
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 33/34] target/arm: Split out thumb_tr_translate_insn Richard Henderson
  2017-07-21 23:24   ` Emilio G. Cota
@ 2017-07-22  0:35   ` Emilio G. Cota
  2017-07-22 11:00     ` Richard Henderson
  1 sibling, 1 reply; 67+ messages in thread
From: Emilio G. Cota @ 2017-07-22  0:35 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On Fri, Jul 14, 2017 at 23:42:42 -1000, Richard Henderson wrote:
> We need not check for ARM vs Thumb state in order to dispatch
> disassembly of every instruction.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  target/arm/translate.c | 134 +++++++++++++++++++++++++++++++------------------
>  1 file changed, 86 insertions(+), 48 deletions(-)
> 
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index ebe1c1a..d7c3c10 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
(snip)
> +static void arm_post_translate_insn(CPUARMState *env, DisasContext *dc)
> +{
> +    /* 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).
> +     */
> +    if (dc->base.is_jmp == DISAS_NEXT
> +        && (dc->pc >= dc->next_page_start
> +            || (dc->pc >= dc->next_page_start - 3
> +                && insn_crosses_page(env, dc)))) {
> +        dc->base.is_jmp = DISAS_TOO_MANY;
>      }
>  
>      if (dc->condjmp && !dc->base.is_jmp) {
>          gen_set_label(dc->condlabel);
>          dc->condjmp = 0;
>      }
> +    dc->base.pc_next = dc->pc;
> +    translator_loop_temp_check(&dc->base);
> +}
>  
> -    if (dc->base.is_jmp == DISAS_NEXT) {
> -        /* 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 (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).
> -             */
> -            dc->base.is_jmp = DISAS_TOO_MANY;

Note that we've moved the above hunk ("if (dc->base.is_jmp == DISAS_NEXT)")
above the "if (dc->condjmp && !dc->base.is_jmp)" one; so when we now set
is_jmp to DISAS_TOO_MANY, dc->condjmp might be wrongly cleared by the
second hunk.

My review missed this, but luckily TCG asserts caught it while booting
debian-arm:

[  OK  ] Started Increase datagram queue length.
systemd[1]: Started Increase datagram queue length.
[  OK  ] Mounted POSIX Message Queue File System.
systemd[1]: Mounted POSIX Message Queue File System.
qemu-system-arm: /data/src/qemu/tcg/tcg-op.c:2584: tcg_gen_goto_tb: Assertion `(tcg_ctx.goto_tb_issue_mask & (1 << idx)) == 0' failed.
Aborted (core dumped)

Keeping the original order fixes it.

		Emilio

--8<--
---
 target/arm/translate.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 77fe6a9..9cbace5 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11979,6 +11979,11 @@ static bool arm_pre_translate_insn(DisasContext *dc)
 
 static void arm_post_translate_insn(CPUARMState *env, DisasContext *dc)
 {
+    if (dc->condjmp && !dc->base.is_jmp) {
+        gen_set_label(dc->condlabel);
+        dc->condjmp = 0;
+    }
+
     /* Translation stops when a conditional branch is encountered.
      * Otherwise the subsequent code could get translated several times.
      * Also stop translation when a page boundary is reached.  This
@@ -12000,10 +12005,6 @@ static void arm_post_translate_insn(CPUARMState *env, DisasContext *dc)
         dc->base.is_jmp = DISAS_TOO_MANY;
     }
 
-    if (dc->condjmp && !dc->base.is_jmp) {
-        gen_set_label(dc->condlabel);
-        dc->condjmp = 0;
-    }
     dc->base.pc_next = dc->pc;
     translator_loop_temp_check(&dc->base);
 }
-- 
2.7.4

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

* Re: [Qemu-devel] [PATCH v14 32/34] target/arm: Move ss check to init_disas_context
  2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 32/34] target/arm: Move ss check " Richard Henderson
  2017-07-21 23:17   ` Emilio G. Cota
@ 2017-07-22  9:07   ` Lluís Vilanova
  1 sibling, 0 replies; 67+ messages in thread
From: Lluís Vilanova @ 2017-07-22  9:07 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, cota, alex.bennee, crosthwaite.peter, pbonzini

Richard Henderson writes:

> We can check for single-step just once.
> Signed-off-by: Richard Henderson <rth@twiddle.net>

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


> ---
>  target/arm/translate.c | 13 ++++++++-----
>  1 file changed, 8 insertions(+), 5 deletions(-)

> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 4b1230b..ebe1c1a 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -11845,6 +11845,11 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase,
dc-> next_page_start =
>          (dc->base.pc_first & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
 
> +    /* If architectural single step active, limit to 1.  */
> +    if (is_singlestepping(dc)) {
> +        max_insns = 1;
> +    }
> +
>      cpu_F0s = tcg_temp_new_i32();
>      cpu_F1s = tcg_temp_new_i32();
>      cpu_F0d = tcg_temp_new_i64();
> @@ -12000,11 +12005,9 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
>           * Also stop translation when a page boundary is reached.  This
>           * ensures prefetch aborts occur at the right place.  */
 
> -        if (is_singlestepping(dc)) {
> -            dc->base.is_jmp = DISAS_TOO_MANY;
> -        } else if ((dc->pc >= dc->next_page_start) ||
> -                   ((dc->pc >= dc->next_page_start - 3) &&
> -                    insn_crosses_page(env, dc))) {
> +        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
> -- 
> 2.9.4

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

* Re: [Qemu-devel] [PATCH v14 03/34] target/i386: Use generic DISAS_* enumerators
  2017-07-21 22:35   ` Lluís Vilanova
@ 2017-07-22 10:31     ` Richard Henderson
  0 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-22 10:31 UTC (permalink / raw)
  To: qemu-devel, pbonzini, cota, alex.bennee, crosthwaite.peter

On 07/21/2017 12:35 PM, Lluís Vilanova wrote:
>> +#define DISAS_TOO_MANY 5
> 
> Why is this one not added as a generic define too (like DISAS_NORETURN in prev
> patch)?

Because I use NORETURN in the arm cleanup, prior to conversion to the enum, 
whereas I do not use TOO_MANY outside the i386 port.  I suppose I could have, 
but at this stage it doesn't really matter, as it only lives 4 more patches til 
the generic enum comes in.


r~

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

* Re: [Qemu-devel] [PATCH v14 07/34] target/arm: Set is_jmp properly after single-stepping
  2017-07-21 21:37   ` Emilio G. Cota
@ 2017-07-22 10:39     ` Richard Henderson
  0 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-22 10:39 UTC (permalink / raw)
  To: Emilio G. Cota
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On 07/21/2017 11:37 AM, Emilio G. Cota wrote:
>>                           gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
>> +                        dc->is_jmp = DISAS_NORETURN;
> 
> gen_exception_internal_insn already sets dc->is_jmp to DISAS_NORETURN,
> as per patch 04/34:
> @@ -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 = DISAS_NORETURN;
>   }
> 
> This applies to both arm and a64.
> 
> Why do we need to set is_jmp again, then?

Because I confused gen_exception_internal, which does not.
I have dropped this patch.


r~

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

* Re: [Qemu-devel] [PATCH v14 33/34] target/arm: Split out thumb_tr_translate_insn
  2017-07-22  0:35   ` Emilio G. Cota
@ 2017-07-22 11:00     ` Richard Henderson
  0 siblings, 0 replies; 67+ messages in thread
From: Richard Henderson @ 2017-07-22 11:00 UTC (permalink / raw)
  To: Emilio G. Cota
  Cc: qemu-devel, vilanova, alex.bennee, crosthwaite.peter, pbonzini

On 07/21/2017 02:35 PM, Emilio G. Cota wrote:
>   static void arm_post_translate_insn(CPUARMState *env, DisasContext *dc)
>   {
> +    if (dc->condjmp && !dc->base.is_jmp) {
> +        gen_set_label(dc->condlabel);
> +        dc->condjmp = 0;
> +    }
> +

Thanks for the catch.

I have merged the !dc->base.is_jmp check with the
following dc->base.is_jmp == DISAS_NEXT.

I hope that's clearer.


r~

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

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

Thread overview: 67+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-15  9:42 [Qemu-devel] [PATCH v14 00/34] Generic translation framework Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 01/34] Pass generic CPUState to gen_intermediate_code() Richard Henderson
2017-07-17 22:56   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 02/34] tcg: Add generic DISAS_NORETURN Richard Henderson
2017-07-21 21:25   ` Emilio G. Cota
2017-07-21 22:32   ` Lluís Vilanova
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 03/34] target/i386: Use generic DISAS_* enumerators Richard Henderson
2017-07-21 21:25   ` Emilio G. Cota
2017-07-21 22:35   ` Lluís Vilanova
2017-07-22 10:31     ` Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 04/34] target/arm: Use DISAS_NORETURN Richard Henderson
2017-07-21 21:25   ` Emilio G. Cota
2017-07-21 22:38   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 05/34] target: [tcg] Use a generic enum for DISAS_ values Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 06/34] target/arm: Delay check for magic kernel page Richard Henderson
2017-07-21 21:27   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 07/34] target/arm: Set is_jmp properly after single-stepping Richard Henderson
2017-07-21 21:37   ` Emilio G. Cota
2017-07-22 10:39     ` Richard Henderson
2017-07-21 22:39   ` Lluís Vilanova
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 08/34] tcg: Add generic translation framework Richard Henderson
2017-07-21 22:49   ` Lluís Vilanova
2017-07-21 23:38   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 09/34] target/i386: [tcg] Port to DisasContextBase Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 10/34] target/i386: [tcg] Port to init_disas_context Richard Henderson
2017-07-21 21:54   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 11/34] target/i386: [tcg] Port to insn_start Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 12/34] target/i386: [tcg] Port to breakpoint_check Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 13/34] target/i386: [tcg] Port to translate_insn Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 14/34] target/i386: [tcg] Port to tb_stop Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 15/34] target/i386: [tcg] Port to disas_log Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 16/34] target/i386: [tcg] Port to generic translation framework Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 17/34] target/arm: [tcg] Port to DisasContextBase Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 18/34] target/arm: [tcg] Port to init_disas_context Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 19/34] target/arm: [tcg, a64] " Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 20/34] target/arm: [tcg] Port to tb_start Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 21/34] target/arm: [tcg] Port to insn_start Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 22/34] target/arm: [tcg, a64] " Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 23/34] target/arm: [tcg, a64] Port to breakpoint_check Richard Henderson
2017-07-21 22:12   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 24/34] target/arm: [tcg] Port to translate_insn Richard Henderson
2017-07-21 22:24   ` Emilio G. Cota
2017-07-21 23:20   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 25/34] target/arm: [tcg, a64] " Richard Henderson
2017-07-21 22:28   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 26/34] target/arm: [tcg] Port to tb_stop Richard Henderson
2017-07-21 22:41   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 27/34] target/arm: [tcg, a64] " Richard Henderson
2017-07-21 22:47   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 28/34] target/arm: [tcg] Port to disas_log Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 29/34] target/arm: [tcg, a64] " Richard Henderson
2017-07-21 22:50   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 30/34] target/arm: [tcg] Port to generic translation framework Richard Henderson
2017-07-21 23:02   ` Emilio G. Cota
2017-07-22  0:05     ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 31/34] target/arm: [a64] Move page and ss checks to init_disas_context Richard Henderson
2017-07-21 23:14   ` Emilio G. Cota
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 32/34] target/arm: Move ss check " Richard Henderson
2017-07-21 23:17   ` Emilio G. Cota
2017-07-22  9:07   ` Lluís Vilanova
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 33/34] target/arm: Split out thumb_tr_translate_insn Richard Henderson
2017-07-21 23:24   ` Emilio G. Cota
2017-07-22  0:35   ` Emilio G. Cota
2017-07-22 11:00     ` Richard Henderson
2017-07-15  9:42 ` [Qemu-devel] [PATCH v14 34/34] target/arm: Perform per-insn cross-page check only for Thumb Richard Henderson
2017-07-21 23:29   ` Emilio G. Cota
2017-07-15 10:15 ` [Qemu-devel] [PATCH v14 00/34] Generic translation framework no-reply

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).