Commit 31c9bd16 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20151007' into staging



Do away with TB retranslation

# gpg: Signature made Wed 07 Oct 2015 10:42:08 BST using RSA key ID 4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"

* remotes/rth/tags/pull-tcg-20151007: (26 commits)
  tcg: Adjust CODE_GEN_AVG_BLOCK_SIZE
  tcg: Check for overflow via highwater mark
  tcg: Allocate a guard page after code_gen_buffer
  tcg: Emit prologue to the beginning of code_gen_buffer
  tcg: Remove tcg_gen_code_search_pc
  tcg: Remove gen_intermediate_code_pc
  tcg: Save insn data and use it in cpu_restore_state_from_tb
  tcg: Pass data argument to restore_state_to_opc
  tcg: Add TCG_MAX_INSNS
  target-*: Drop cpu_gen_code define
  tcg: Merge cpu_gen_code into tb_gen_code
  target-sparc: Add npc state to insn_start
  target-sparc: Remove gen_opc_jump_pc
  target-sparc: Split out gen_branch_n
  target-sparc: Tidy gen_branch_a interface
  target-cris: Mirror gen_opc_pc into insn_start
  target-sh4: Add flags state to insn_start
  target-s390x: Add cc_op state to insn_start
  target-mips: Add delayed branch state to insn_start
  target-i386: Add cc_op state to insn_start
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents ca4e4b82 126d89e8
Loading
Loading
Loading
Loading
+8 −15
Original line number Diff line number Diff line
@@ -62,24 +62,15 @@ typedef struct TranslationBlock TranslationBlock;
#define OPC_BUF_SIZE 640
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)

/* Maximum size a TCG op can expand to.  This is complicated because a
   single op may require several host instructions and register reloads.
   For now take a wild guess at 192 bytes, which should allow at least
   a couple of fixup instructions per argument.  */
#define TCG_MAX_OP_SIZE 192

#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * MAX_OPC_PARAM)

#include "qemu/log.h"

void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb);
void gen_intermediate_code_pc(CPUArchState *env, struct TranslationBlock *tb);
void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb,
                          int pc_pos);
                          target_ulong *data);

void cpu_gen_init(void);
int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb,
                 int *gen_code_size_ptr);
bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc);
void page_size_init(void);

@@ -170,13 +161,14 @@ static inline void tlb_flush_by_mmuidx(CPUState *cpu, ...)
#define CODE_GEN_PHYS_HASH_BITS     15
#define CODE_GEN_PHYS_HASH_SIZE     (1 << CODE_GEN_PHYS_HASH_BITS)

/* estimated block size for TB allocation */
/* XXX: use a per code average code fragment size and modulate it
   according to the host CPU */
/* Estimated block size for TB allocation.  */
/* ??? The following is based on a 2015 survey of x86_64 host output.
   Better would seem to be some sort of dynamically sized TB array,
   adapting to the block sizes actually being produced.  */
#if defined(CONFIG_SOFTMMU)
#define CODE_GEN_AVG_BLOCK_SIZE 128
#define CODE_GEN_AVG_BLOCK_SIZE 400
#else
#define CODE_GEN_AVG_BLOCK_SIZE 64
#define CODE_GEN_AVG_BLOCK_SIZE 150
#endif

#if defined(__arm__) || defined(_ARCH_PPC) \
@@ -201,6 +193,7 @@ struct TranslationBlock {
#define CF_USE_ICOUNT  0x20000

    void *tc_ptr;    /* pointer to the translated code */
    uint8_t *tc_search;  /* pointer to search data */
    /* next matching tb for physical address. */
    struct TranslationBlock *phys_hash_next;
    /* original tb when cflags has CF_NOCACHE */
+16 −0
Original line number Diff line number Diff line
@@ -721,6 +721,7 @@ void cpu_single_step(CPUState *cpu, int enabled);
/* 0x08 currently unused */
#define BP_GDB                0x10
#define BP_CPU                0x20
#define BP_ANY                (BP_GDB | BP_CPU)
#define BP_WATCHPOINT_HIT_READ 0x40
#define BP_WATCHPOINT_HIT_WRITE 0x80
#define BP_WATCHPOINT_HIT (BP_WATCHPOINT_HIT_READ | BP_WATCHPOINT_HIT_WRITE)
@@ -731,6 +732,21 @@ int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags);
void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint);
void cpu_breakpoint_remove_all(CPUState *cpu, int mask);

/* Return true if PC matches an installed breakpoint.  */
static inline bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask)
{
    CPUBreakpoint *bp;

    if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
        QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
            if (bp->pc == pc && (bp->flags & mask)) {
                return true;
            }
        }
    }
    return false;
}

int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
                          int flags, CPUWatchpoint **watchpoint);
int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
+0 −1
Original line number Diff line number Diff line
@@ -287,7 +287,6 @@ struct CPUAlphaState {

#define cpu_list alpha_cpu_list
#define cpu_exec cpu_alpha_exec
#define cpu_gen_code cpu_alpha_gen_code
#define cpu_signal_handler cpu_alpha_signal_handler

#include "exec/cpu-all.h"
+17 −53
Original line number Diff line number Diff line
@@ -2858,18 +2858,14 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
    return ret;
}

static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
                                                  TranslationBlock *tb,
                                                  bool search_pc)
void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
{
    AlphaCPU *cpu = alpha_env_get_cpu(env);
    CPUState *cs = CPU(cpu);
    CPUAlphaState *env = &cpu->env;
    DisasContext ctx, *ctxp = &ctx;
    target_ulong pc_start;
    target_ulong pc_mask;
    uint32_t insn;
    CPUBreakpoint *bp;
    int j, lj = -1;
    ExitStatus ret;
    int num_insns;
    int max_insns;
@@ -2904,6 +2900,9 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
    if (max_insns == 0) {
        max_insns = CF_COUNT_MASK;
    }
    if (max_insns > TCG_MAX_INSNS) {
        max_insns = TCG_MAX_INSNS;
    }

    if (in_superpage(&ctx, pc_start)) {
        pc_mask = (1ULL << 41) - 1;
@@ -2913,35 +2912,17 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,

    gen_tb_start(tb);
    do {
        if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
            QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
                if (bp->pc == ctx.pc) {
        tcg_gen_insn_start(ctx.pc);
        num_insns++;

        if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
            gen_excp(&ctx, EXCP_DEBUG, 0);
            break;
        }
            }
        }
        if (search_pc) {
            j = tcg_op_buf_count();
            if (lj < j) {
                lj++;
                while (lj < j) {
                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
                }
            }
            tcg_ctx.gen_opc_pc[lj] = ctx.pc;
            tcg_ctx.gen_opc_instr_start[lj] = 1;
            tcg_ctx.gen_opc_icount[lj] = num_insns;
        }
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
        if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
            gen_io_start();
        }
        insn = cpu_ldl_code(env, ctx.pc);
        num_insns++;

	if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
            tcg_gen_debug_insn_start(ctx.pc);
        }

        TCGV_UNUSED_I64(ctx.zero);
        TCGV_UNUSED_I64(ctx.sink);
@@ -2997,16 +2978,8 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,

    gen_tb_end(tb, num_insns);

    if (search_pc) {
        j = tcg_op_buf_count();
        lj++;
        while (lj <= j) {
            tcg_ctx.gen_opc_instr_start[lj++] = 0;
        }
    } else {
    tb->size = ctx.pc - pc_start;
    tb->icount = num_insns;
    }

#ifdef DEBUG_DISAS
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -3017,17 +2990,8 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
#endif
}

void gen_intermediate_code (CPUAlphaState *env, struct TranslationBlock *tb)
{
    gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, false);
}

void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb)
{
    gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, true);
}

void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb,
                          target_ulong *data)
{
    env->pc = tcg_ctx.gen_opc_pc[pc_pos];
    env->pc = data[0];
}
+1 −1
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@
struct arm_boot_info;

#define NB_MMU_MODES 7
#define TARGET_INSN_START_EXTRA_WORDS 1

/* We currently assume float and double are IEEE single and double
   precision respectively.
@@ -1600,7 +1601,6 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
#define cpu_init(cpu_model) CPU(cpu_arm_init(cpu_model))

#define cpu_exec cpu_arm_exec
#define cpu_gen_code cpu_arm_gen_code
#define cpu_signal_handler cpu_arm_signal_handler
#define cpu_list arm_cpu_list

Loading