diff mbox

[v6,3/6] target: [tcg] Add generic translation framework

Message ID 149727924970.28532.9346819516051209538.stgit@frigg.lan
State New
Headers show

Commit Message

Lluís Vilanova June 12, 2017, 2:54 p.m. UTC
Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 include/exec/gen-icount.h             |    2 
 include/exec/translate-all_template.h |   73 ++++++++++++
 include/qom/cpu.h                     |   22 ++++
 translate-all_template.h              |  204 +++++++++++++++++++++++++++++++++
 4 files changed, 300 insertions(+), 1 deletion(-)
 create mode 100644 include/exec/translate-all_template.h
 create mode 100644 translate-all_template.h

Comments

Emilio Cota June 15, 2017, 10:19 p.m. UTC | #1
Some minor nits below.

On Mon, Jun 12, 2017 at 17:54:09 +0300, Lluís Vilanova wrote:
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
> +/**
> + * BreakpointHitType:
> + * @BH_MISS: No hit
> + * @BH_HIT_INSN: Hit, but continue translating instruction
> + * @BH_HIT_TB: Hit, stop translating TB
> + *
> + * How to react to a breakpoint hit.
> + */
> +typedef enum BreakpointHitType {
> +    BH_MISS,
> +    BH_HIT_INSN,
> +    BH_HIT_TB,
> +} BreakpointHitType;

BH_MISS reads out loud to "Breakpoint Hit Miss"; that's quite counterintuitive.
Similarly for the others (e.g. "breakpoint Hit Hit -- ??".

Can we just do BP_{MISS,HIT,etc}? Thinking about it, perhaps BP_NONE is
better than BP_MISS.

(snip)
> +/**
> + * 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).
> + * @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 jmp_type;
> +    unsigned int num_insns;
> +    bool singlestep_enabled;
> +} DisasContextBase;

- @pc_next: I'd stick with @pc, it's shorter, it's everywhere already, and
  with the documentation it's very clear what it is for.
- @jmp_type: missing doc :-)

Thanks,

		E.
Emilio Cota June 15, 2017, 11:25 p.m. UTC | #2
On Thu, Jun 15, 2017 at 18:19:11 -0400, Emilio G. Cota wrote:
> (snip)
> > +/**
> > + * 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).
> > + * @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 jmp_type;
> > +    unsigned int num_insns;
> > +    bool singlestep_enabled;
> > +} DisasContextBase;
> 
> - @pc_next: I'd stick with @pc, it's shorter, it's everywhere already, and
>   with the documentation it's very clear what it is for.
> - @jmp_type: missing doc :-)

Also, consider keeping the @is_jmp name instead of renaming it to
@jmp_type. (@jmp would be shorter but it would be confusing though,
e.g. cris has both dc->jmp and dc->is_jmp.)

		E.
Emilio Cota June 17, 2017, 1:09 a.m. UTC | #3
On Thu, Jun 15, 2017 at 19:25:07 -0400, Emilio G. Cota wrote:
> Also, consider keeping the @is_jmp name instead of renaming it to
> @jmp_type. (@jmp would be shorter but it would be confusing though,
> e.g. cris has both dc->jmp and dc->is_jmp.)

It turns out that keeping the original names also makes the diff's
a lot more bearable.

I have a WIP branch with further modifications to your patches; the goal
is to break down the patchset to make it more easily reviewable, which
hopefully will also prevent us from introducing bugs.

You can see the WIP tree at:
  https://github.com/cota/qemu/tree/trloop
Note that I may rebase this branch any time.

Cheers,

		Emilio
Lluís Vilanova June 18, 2017, 2:20 p.m. UTC | #4
Emilio G Cota writes:

> Some minor nits below.
> On Mon, Jun 12, 2017 at 17:54:09 +0300, Lluís Vilanova wrote:
>> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
>> ---
>> +/**
>> + * BreakpointHitType:
>> + * @BH_MISS: No hit
>> + * @BH_HIT_INSN: Hit, but continue translating instruction
>> + * @BH_HIT_TB: Hit, stop translating TB
>> + *
>> + * How to react to a breakpoint hit.
>> + */
>> +typedef enum BreakpointHitType {
>> +    BH_MISS,
>> +    BH_HIT_INSN,
>> +    BH_HIT_TB,
>> +} BreakpointHitType;

> BH_MISS reads out loud to "Breakpoint Hit Miss"; that's quite counterintuitive.
> Similarly for the others (e.g. "breakpoint Hit Hit -- ??".

> Can we just do BP_{MISS,HIT,etc}? Thinking about it, perhaps BP_NONE is
> better than BP_MISS.
[...]

Will do.


Cheers,
  Lluis
Lluís Vilanova June 18, 2017, 2:22 p.m. UTC | #5
Emilio G Cota writes:

> On Thu, Jun 15, 2017 at 18:19:11 -0400, Emilio G. Cota wrote:
>> (snip)
>> > +/**
>> > + * 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).
>> > + * @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 jmp_type;
>> > +    unsigned int num_insns;
>> > +    bool singlestep_enabled;
>> > +} DisasContextBase;
>> 
>> - @pc_next: I'd stick with @pc, it's shorter, it's everywhere already, and
>> with the documentation it's very clear what it is for.
>> - @jmp_type: missing doc :-)

> Also, consider keeping the @is_jmp name instead of renaming it to
> @jmp_type. (@jmp would be shorter but it would be confusing though,
> e.g. cris has both dc->jmp and dc->is_jmp.)

I just figured that this series could also take the chance of trying to rename a
few common variables I'm changing to something more readable.

But if you feel very strongly about keeping the original names (and minimizing
the diffs as you say later), I'll revert the name changes.


Thanks,
  Lluis
Lluís Vilanova June 18, 2017, 2:24 p.m. UTC | #6
Emilio G Cota writes:

> On Thu, Jun 15, 2017 at 19:25:07 -0400, Emilio G. Cota wrote:
>> Also, consider keeping the @is_jmp name instead of renaming it to
>> @jmp_type. (@jmp would be shorter but it would be confusing though,
>> e.g. cris has both dc->jmp and dc->is_jmp.)

> It turns out that keeping the original names also makes the diff's
> a lot more bearable.

> I have a WIP branch with further modifications to your patches; the goal
> is to break down the patchset to make it more easily reviewable, which
> hopefully will also prevent us from introducing bugs.

> You can see the WIP tree at:
>   https://github.com/cota/qemu/tree/trloop
> Note that I may rebase this branch any time.

Ok, I'll do that for both arm and x86.


Thanks a lot,
  Lluis
Lluís Vilanova June 18, 2017, 3:47 p.m. UTC | #7
Lluís Vilanova writes:

> Emilio G Cota writes:
>> On Thu, Jun 15, 2017 at 18:19:11 -0400, Emilio G. Cota wrote:
>>> (snip)
>>> > +/**
>>> > + * 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).
>>> > + * @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 jmp_type;
>>> > +    unsigned int num_insns;
>>> > +    bool singlestep_enabled;
>>> > +} DisasContextBase;
>>> 
>>> - @pc_next: I'd stick with @pc, it's shorter, it's everywhere already, and
>>> with the documentation it's very clear what it is for.
>>> - @jmp_type: missing doc :-)

>> Also, consider keeping the @is_jmp name instead of renaming it to
>> @jmp_type. (@jmp would be shorter but it would be confusing though,
>> e.g. cris has both dc->jmp and dc->is_jmp.)

> I just figured that this series could also take the chance of trying to rename a
> few common variables I'm changing to something more readable.

> But if you feel very strongly about keeping the original names (and minimizing
> the diffs as you say later), I'll revert the name changes.

Also, going through the changes to break them down into smaller pieces, I saw
that TranslationBlock (at least in i386) already has a "pc" member, so using
"pc_next" in DisasContextBase makes it even clearer it's a different variable.

You comments still apply to "is_jmp" vs "jmp_type" though. Unless you or anybody
else feels strongly against it, I'll keep "jmp_type", since I'm already changing
all lines that reference "is_jmp" to use DisasContextBase (instead of
DisasContext).


Thanks,
  Lluis
Lluís Vilanova June 18, 2017, 9:54 p.m. UTC | #8
Lluís Vilanova writes:

> Lluís Vilanova writes:
>> Emilio G Cota writes:
>>> On Thu, Jun 15, 2017 at 18:19:11 -0400, Emilio G. Cota wrote:
>>>> (snip)
>>>> > +/**
>>>> > + * 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).
>>>> > + * @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 jmp_type;
>>>> > +    unsigned int num_insns;
>>>> > +    bool singlestep_enabled;
>>>> > +} DisasContextBase;
>>>> 
>>>> - @pc_next: I'd stick with @pc, it's shorter, it's everywhere already, and
>>>> with the documentation it's very clear what it is for.
>>>> - @jmp_type: missing doc :-)

>>> Also, consider keeping the @is_jmp name instead of renaming it to
>>> @jmp_type. (@jmp would be shorter but it would be confusing though,
>>> e.g. cris has both dc->jmp and dc->is_jmp.)

>> I just figured that this series could also take the chance of trying to rename a
>> few common variables I'm changing to something more readable.

>> But if you feel very strongly about keeping the original names (and minimizing
>> the diffs as you say later), I'll revert the name changes.

> Also, going through the changes to break them down into smaller pieces, I saw
> that TranslationBlock (at least in i386) already has a "pc" member, so using
> "pc_next" in DisasContextBase makes it even clearer it's a different variable.

> You comments still apply to "is_jmp" vs "jmp_type" though. Unless you or anybody
> else feels strongly against it, I'll keep "jmp_type", since I'm already changing
> all lines that reference "is_jmp" to use DisasContextBase (instead of
> DisasContext).

Aha, just checked your proposed patches more closely and it totally makes sense
to keep "is_jmp" to simplify the diffs, so I'll go for that one.

Thanks!
Lluis
Emilio Cota June 19, 2017, 4:10 a.m. UTC | #9
On Mon, Jun 19, 2017 at 00:54:05 +0300, Lluís Vilanova wrote:
> Aha, just checked your proposed patches more closely and it totally makes sense
> to keep "is_jmp" to simplify the diffs, so I'll go for that one.

Also I think it's important to break down the changes to each
architecture into separate patches, otherwise the diff becomes
impossible to read. I went quite a long way with arm/translate.c
on Friday.

		E.
Lluís Vilanova June 19, 2017, 8:37 a.m. UTC | #10
Emilio G Cota writes:

> On Mon, Jun 19, 2017 at 00:54:05 +0300, Lluís Vilanova wrote:
>> Aha, just checked your proposed patches more closely and it totally makes sense
>> to keep "is_jmp" to simplify the diffs, so I'll go for that one.

> Also I think it's important to break down the changes to each
> architecture into separate patches, otherwise the diff becomes
> impossible to read. I went quite a long way with arm/translate.c
> on Friday.

Yes, I'm onto it, thanks :)

Lluis
diff mbox

Patch

diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index 62d462e494..547c979629 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -44,7 +44,7 @@  static inline void gen_tb_start(TranslationBlock *tb)
     tcg_temp_free_i32(count);
 }
 
-static void gen_tb_end(TranslationBlock *tb, int num_insns)
+static inline void gen_tb_end(TranslationBlock *tb, int num_insns)
 {
     if (tb->cflags & CF_USE_ICOUNT) {
         /* Update the num_insn immediate parameter now that we know
diff --git a/include/exec/translate-all_template.h b/include/exec/translate-all_template.h
new file mode 100644
index 0000000000..51c8a43b80
--- /dev/null
+++ b/include/exec/translate-all_template.h
@@ -0,0 +1,73 @@ 
+/*
+ * Generic intermediate code generation.
+ *
+ * Copyright (C) 2016-2017 Lluís Vilanova <vilanova@ac.upc.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef EXEC__TRANSLATE_ALL_TEMPLATE_H
+#define EXEC__TRANSLATE_ALL_TEMPLATE_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"
+
+
+/**
+ * BreakpointHitType:
+ * @BH_MISS: No hit
+ * @BH_HIT_INSN: Hit, but continue translating instruction
+ * @BH_HIT_TB: Hit, stop translating TB
+ *
+ * How to react to a breakpoint hit.
+ */
+typedef enum BreakpointHitType {
+    BH_MISS,
+    BH_HIT_INSN,
+    BH_HIT_TB,
+} BreakpointHitType;
+
+/**
+ * DisasJumpType:
+ * @DJ_NEXT: Next instruction in program order
+ * @DJ_TOO_MANY: Too many instructions executed
+ * @DJ_TARGET: Start of target-specific conditions
+ *
+ * What instruction to disassemble next.
+ */
+typedef enum DisasJumpType {
+    DJ_NEXT,
+    DJ_TOO_MANY,
+    DJ_TARGET,
+} DisasJumpType;
+
+/**
+ * DisasContextBase:
+ * @tb: Translation block for this disassembly.
+ * @pc_first: Address of first guest instruction in this TB.
+ * @pc_next: Address of next guest instruction in this TB (current during
+ *           disassembly).
+ * @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 jmp_type;
+    unsigned int num_insns;
+    bool singlestep_enabled;
+} DisasContextBase;
+
+#endif  /* EXEC__TRANSLATE_ALL_TEMPLATE_H */
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 89ddb686fb..d46e8df756 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -982,6 +982,28 @@  static inline bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask)
     return false;
 }
 
+/* Get first breakpoint matching a PC */
+static inline CPUBreakpoint *cpu_breakpoint_get(CPUState *cpu, vaddr pc,
+                                                CPUBreakpoint *bp)
+{
+    if (likely(bp == NULL)) {
+        if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
+            QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
+                if (bp->pc == pc) {
+                    return bp;
+                }
+            }
+        }
+    } else {
+        QTAILQ_FOREACH_CONTINUE(bp, entry) {
+            if (bp->pc == pc) {
+                return bp;
+            }
+        }
+    }
+    return NULL;
+}
+
 int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
                           int flags, CPUWatchpoint **watchpoint);
 int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
diff --git a/translate-all_template.h b/translate-all_template.h
new file mode 100644
index 0000000000..3e3f0816f7
--- /dev/null
+++ b/translate-all_template.h
@@ -0,0 +1,204 @@ 
+/*
+ * 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 TRANSLATE_ALL_TEMPLATE_H
+#define TRANSLATE_ALL_TEMPLATE_H
+
+/*
+ * Include this header from a target-specific file, which must define the
+ * target-specific functions declared below.
+ *
+ * These must be paired with instructions in "exec/translate-all_template.h".
+ */
+
+
+#include "cpu.h"
+#include "qemu/error-report.h"
+
+
+static void gen_intermediate_code_target_init_disas_context(
+    DisasContext *dc, CPUArchState *env);
+
+static void gen_intermediate_code_target_init_globals(
+    DisasContext *dc, CPUArchState *env);
+
+static void gen_intermediate_code_target_tb_start(
+    DisasContext *dc, CPUArchState *env);
+
+static void gen_intermediate_code_target_insn_start(
+    DisasContext *dc, CPUArchState *env);
+
+static BreakpointHitType gen_intermediate_code_target_breakpoint_hit(
+    DisasContext *dc, CPUArchState *env,
+    const CPUBreakpoint *bp);
+
+static target_ulong gen_intermediate_code_target_disas_insn(
+    DisasContext *dc, CPUArchState *env);
+
+static DisasJumpType gen_intermediate_code_target_stop_check(
+    DisasContext *dc, CPUArchState *env);
+
+static void gen_intermediate_code_target_stop(
+    DisasContext *dc, CPUArchState *env);
+
+static int gen_intermediate_code_target_get_disas_flags(
+    const DisasContext *dc);
+
+
+static inline void gen_intermediate_code_tcg_check(const DisasContext *dc)
+{
+    if (tcg_check_temp_count()) {
+        error_report("warning: TCG temporary leaks before "TARGET_FMT_lx,
+                     dc->base.pc_next);
+    }
+}
+
+void gen_intermediate_code(CPUState *cpu, struct TranslationBlock *tb)
+{
+    CPUArchState *env = cpu->env_ptr;
+    DisasContext dc1, *dc = &dc1;
+    int max_insns;
+
+    /* Initialize DisasContext */
+    dc->base.tb = tb;
+    dc->base.singlestep_enabled = cpu->singlestep_enabled;
+    dc->base.pc_first = tb->pc;
+    dc->base.pc_next = dc->base.pc_first;
+    dc->base.jmp_type = DJ_NEXT;
+    dc->base.num_insns = 0;
+    gen_intermediate_code_target_init_disas_context(dc, env);
+
+    /* Initialize globals */
+    gen_intermediate_code_target_init_globals(dc, env);
+    tcg_clear_temp_count();
+
+    /* Instruction counting */
+    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;
+    }
+    if (dc->base.singlestep_enabled || singlestep) {
+        max_insns = 1;
+    }
+
+    /* Start translating */
+    gen_tb_start(dc->base.tb);
+    gen_intermediate_code_target_tb_start(dc, env);
+
+    while (true) {
+        CPUBreakpoint *bp;
+
+        dc->base.num_insns++;
+        gen_intermediate_code_target_insn_start(dc, env);
+
+        /* Early exit before breakpoint checks */
+        if (unlikely(dc->base.jmp_type != DJ_NEXT)) {
+            break;
+        }
+
+        /* Pass breakpoint hits to target for further processing */
+        bp = NULL;
+        do {
+            bp = cpu_breakpoint_get(cpu, dc->base.pc_next, bp);
+            if (unlikely(bp)) {
+                BreakpointHitType bh =
+                    gen_intermediate_code_target_breakpoint_hit(dc, env, bp);
+                if (bh == BH_HIT_INSN) {
+                    /* Hit, keep translating */
+                    /*
+                     * TODO: if we're never going to have more than one BP in a
+                     *       single address, we can simply use a bool here.
+                     */
+                    break;
+                } else if (bh == BH_HIT_TB) {
+                    goto done_generating;
+                }
+            }
+        } while (bp != NULL);
+
+        /* Accept I/O on last instruction */
+        if (dc->base.num_insns == max_insns &&
+            (dc->base.tb->cflags & CF_LAST_IO)) {
+            gen_io_start();
+        }
+
+        /* Disassemble one instruction */
+        dc->base.pc_next = gen_intermediate_code_target_disas_insn(dc, env);
+
+        /**************************************************/
+        /* Conditions to stop translation                 */
+        /**************************************************/
+
+        /* Disassembly already set a stop condition */
+        if (dc->base.jmp_type >= DJ_TARGET) {
+            break;
+        }
+
+        /* Target-specific conditions */
+        dc->base.jmp_type = gen_intermediate_code_target_stop_check(dc, env);
+        if (dc->base.jmp_type >= DJ_TARGET) {
+            break;
+        }
+
+        /* Too many instructions */
+        if (tcg_op_buf_full() || dc->base.num_insns >= max_insns) {
+            dc->base.jmp_type = DJ_TOO_MANY;
+            break;
+        }
+
+        /*
+         * Check if next instruction is on next page, which can cause an
+         * exception.
+         *
+         * NOTE: Target-specific code must check a single instruction does not
+         *       cross page boundaries; the first in the TB is always allowed to
+         *       cross pages (never goes through this check).
+         */
+        if ((dc->base.pc_first & TARGET_PAGE_MASK)
+            != (dc->base.pc_next & TARGET_PAGE_MASK)) {
+            dc->base.jmp_type = DJ_TOO_MANY;
+            break;
+        }
+
+        gen_intermediate_code_tcg_check(dc);
+    }
+
+    gen_intermediate_code_target_stop(dc, env);
+
+    if (dc->base.tb->cflags & CF_LAST_IO) {
+        gen_io_end();
+    }
+
+done_generating:
+    gen_tb_end(dc->base.tb, dc->base.num_insns);
+
+    gen_intermediate_code_tcg_check(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");
+        qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
+        log_target_disas(cpu, dc->base.pc_first,
+                         dc->base.pc_next - dc->base.pc_first,
+                         gen_intermediate_code_target_get_disas_flags(dc));
+        qemu_log("\n");
+        qemu_log_unlock();
+    }
+#endif
+
+    dc->base.tb->size = dc->base.pc_next - dc->base.pc_first;
+    dc->base.tb->icount = dc->base.num_insns;
+}
+
+#endif  /* TRANSLATE_ALL_TEMPLATE_H */