From 765b842adec4c5a359e69ca08785553599f71496 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 29 Aug 2015 12:37:33 -0700 Subject: [PATCH 01/26] tcg: Rename debug_insn_start to insn_start With an eye toward making it mandatory. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-alpha/translate.c | 2 +- target-arm/translate-a64.c | 2 +- target-arm/translate.c | 2 +- target-cris/translate.c | 4 ++-- target-cris/translate_v10.c | 2 +- target-i386/translate.c | 2 +- target-lm32/translate.c | 2 +- target-m68k/translate.c | 2 +- target-microblaze/translate.c | 2 +- target-mips/translate.c | 2 +- target-moxie/translate.c | 2 +- target-openrisc/translate.c | 2 +- target-ppc/translate.c | 2 +- target-s390x/translate.c | 2 +- target-sh4/translate.c | 2 +- target-sparc/translate.c | 2 +- target-tilegx/translate.c | 2 +- target-unicore32/translate.c | 2 +- target-xtensa/translate.c | 2 +- tcg/tcg-op.h | 6 +++--- tcg/tcg-opc.h | 4 ++-- tcg/tcg.c | 6 +++--- tci.c | 9 --------- 23 files changed, 28 insertions(+), 37 deletions(-) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 2ba5fb80ae..76916f434a 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -2940,7 +2940,7 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu, num_insns++; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(ctx.pc); + tcg_gen_insn_start(ctx.pc); } TCGV_UNUSED_I64(ctx.zero); diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index ec0936cf97..a618711b64 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -11109,7 +11109,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, } if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc->pc); + tcg_gen_insn_start(dc->pc); } if (dc->ss_active && !dc->pstate_ss) { diff --git a/target-arm/translate.c b/target-arm/translate.c index 84a21ace54..b521fc86f8 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -11353,7 +11353,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, gen_io_start(); if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc->pc); + tcg_gen_insn_start(dc->pc); } if (dc->ss_active && !dc->pstate_ss) { diff --git a/target-cris/translate.c b/target-cris/translate.c index d5b54e1ad4..c5a22afa66 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -2995,8 +2995,8 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc) int i; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc->pc); - } + tcg_gen_insn_start(dc->pc); + } /* Load a halfword onto the instruction register. */ dc->ir = cris_fetch(env, dc, dc->pc, 2, 0); diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c index da0b2caf85..12d7dfc45e 100644 --- a/target-cris/translate_v10.c +++ b/target-cris/translate_v10.c @@ -1200,7 +1200,7 @@ static unsigned int crisv10_decoder(CPUCRISState *env, DisasContext *dc) unsigned int insn_len = 2; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) - tcg_gen_debug_insn_start(dc->pc); + tcg_gen_insn_start(dc->pc); /* Load a halfword onto the instruction register. */ dc->ir = cpu_lduw_code(env, dc->pc); diff --git a/target-i386/translate.c b/target-i386/translate.c index 8b35de1a1a..c18f82bfd1 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -4402,7 +4402,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, int rex_w, rex_r; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(pc_start); + tcg_gen_insn_start(pc_start); } s->pc = pc_start; prefixes = 0; diff --git a/target-lm32/translate.c b/target-lm32/translate.c index cf7042e3e0..b1b4cbb750 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -1006,7 +1006,7 @@ static const DecoderInfo decinfo[] = { static inline void decode(DisasContext *dc, uint32_t ir) { if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc->pc); + tcg_gen_insn_start(dc->pc); } dc->ir = ir; diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 3cdf6652aa..e34bf2b8cd 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2956,7 +2956,7 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) uint16_t insn; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(s->pc); + tcg_gen_insn_start(s->pc); } insn = cpu_lduw_code(env, s->pc); diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 3de89440a6..0d340c0e78 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -1589,7 +1589,7 @@ static inline void decode(DisasContext *dc, uint32_t ir) int i; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc->pc); + tcg_gen_insn_start(dc->pc); } dc->ir = ir; diff --git a/target-mips/translate.c b/target-mips/translate.c index 87d495975a..2b3f2b00b1 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -18905,7 +18905,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) } if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(ctx->pc); + tcg_gen_insn_start(ctx->pc); } op = MASK_OP_MAJOR(ctx->opcode); diff --git a/target-moxie/translate.c b/target-moxie/translate.c index cc77366ee7..0bb94a02b8 100644 --- a/target-moxie/translate.c +++ b/target-moxie/translate.c @@ -154,7 +154,7 @@ static int decode_opc(MoxieCPU *cpu, DisasContext *ctx) int length = 2; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(ctx->pc); + tcg_gen_insn_start(ctx->pc); } /* Examine the 16-bit opcode. */ diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 473556e14a..727fbba66f 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -1689,7 +1689,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, } if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc->pc); + tcg_gen_insn_start(dc->pc); } if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { diff --git a/target-ppc/translate.c b/target-ppc/translate.c index c0eed13f98..c46133d9df 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -11516,7 +11516,7 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode), ctx.le_mode ? "little" : "big"); if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(ctx.nip); + tcg_gen_insn_start(ctx.nip); } ctx.nip += 4; table = env->opcodes; diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 2bca33acca..a87d83c79e 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -5375,7 +5375,7 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu, } if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc.pc); + tcg_gen_insn_start(dc.pc); } status = NO_EXIT; diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 724c0e7106..d9d2c02a39 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1791,7 +1791,7 @@ static void decode_opc(DisasContext * ctx) uint32_t old_flags = ctx->flags; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(ctx->pc); + tcg_gen_insn_start(ctx->pc); } _decode_opc(ctx); diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 4690b4699a..ef17e26253 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2483,7 +2483,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) target_long simm; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc->pc); + tcg_gen_insn_start(dc->pc); } opc = GET_FIELD(insn, 0, 1); diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index e70c3e5ab7..3fb7fc6a21 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -2009,7 +2009,7 @@ static void translate_one_bundle(DisasContext *dc, uint64_t bundle) dc->num_wb = 0; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc->pc); + tcg_gen_insn_start(dc->pc); } qemu_log_mask(CPU_LOG_TB_IN_ASM, " %" PRIx64 ": { ", dc->pc); diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 2fc78e6f3e..63a5192b59 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -1795,7 +1795,7 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s) unsigned int insn; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(s->pc); + tcg_gen_insn_start(s->pc); } insn = cpu_ldl_code(env, s->pc); diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index a29b3e61bc..ea777dabdd 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -3078,7 +3078,7 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, } if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(dc.pc); + tcg_gen_insn_start(dc.pc); } ++dc.ccount_delta; diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 6da083a1e9..6409db8893 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -701,14 +701,14 @@ static inline void tcg_gen_concat32_i64(TCGv_i64 ret, TCGv_i64 lo, TCGv_i64 hi) #endif /* debug info: write the PC of the corresponding QEMU CPU instruction */ -static inline void tcg_gen_debug_insn_start(uint64_t pc) +static inline void tcg_gen_insn_start(uint64_t pc) { /* XXX: must really use a 32 bit size for TCGArg in all cases */ #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS - tcg_gen_op2ii(INDEX_op_debug_insn_start, + tcg_gen_op2ii(INDEX_op_insn_start, (uint32_t)(pc), (uint32_t)(pc >> 32)); #else - tcg_gen_op1i(INDEX_op_debug_insn_start, pc); + tcg_gen_op1i(INDEX_op_insn_start, pc); #endif } diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index 02bbf30387..f60d3c2d4e 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -175,9 +175,9 @@ DEF(mulsh_i64, 1, 2, 0, IMPL(TCG_TARGET_HAS_mulsh_i64)) /* QEMU specific */ #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS -DEF(debug_insn_start, 0, 0, 2, TCG_OPF_NOT_PRESENT) +DEF(insn_start, 0, 0, 2, TCG_OPF_NOT_PRESENT) #else -DEF(debug_insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT) +DEF(insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT) #endif DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END) DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END) diff --git a/tcg/tcg.c b/tcg/tcg.c index a2cb027a14..df8788bac5 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -990,7 +990,7 @@ void tcg_dump_ops(TCGContext *s) def = &tcg_op_defs[c]; args = &s->gen_opparam_buf[op->args]; - if (c == INDEX_op_debug_insn_start) { + if (c == INDEX_op_insn_start) { uint64_t pc; #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS pc = ((uint64_t)args[1] << 32) | args[0]; @@ -1400,7 +1400,7 @@ static void tcg_liveness_analysis(TCGContext *s) } } break; - case INDEX_op_debug_insn_start: + case INDEX_op_insn_start: break; case INDEX_op_discard: /* mark the temporary as dead */ @@ -2359,7 +2359,7 @@ static inline int tcg_gen_code_common(TCGContext *s, case INDEX_op_movi_i64: tcg_reg_alloc_movi(s, args, dead_args, sync_args); break; - case INDEX_op_debug_insn_start: + case INDEX_op_insn_start: break; case INDEX_op_discard: temp_dead(s, args[0]); diff --git a/tci.c b/tci.c index 70eaab25eb..b5ed7b1f7a 100644 --- a/tci.c +++ b/tci.c @@ -1081,15 +1081,6 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) /* QEMU specific operations. */ -#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS - case INDEX_op_debug_insn_start: - TODO(); - break; -#else - case INDEX_op_debug_insn_start: - TODO(); - break; -#endif case INDEX_op_exit_tb: next_tb = *(uint64_t *)tb_ptr; goto exit; From 667b8e29c5b1d8c5b4e6ad5f780ca60914eb6e96 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 29 Aug 2015 12:59:29 -0700 Subject: [PATCH 02/26] target-*: Unconditionally emit tcg_gen_insn_start While we're at it, emit the opcode adjacent to where we currently record data for search_pc. This puts gen_io_start et al on the "correct" side of the marker. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-alpha/translate.c | 6 ++---- target-arm/translate-a64.c | 5 +---- target-arm/translate.c | 5 +---- target-cris/translate.c | 5 +---- target-cris/translate_v10.c | 3 --- target-i386/translate.c | 5 ++--- target-lm32/translate.c | 5 +---- target-m68k/translate.c | 10 +++++----- target-microblaze/translate.c | 5 +---- target-mips/translate.c | 9 ++++----- target-moxie/translate.c | 6 ++---- target-openrisc/translate.c | 5 +---- target-ppc/translate.c | 5 ++--- target-s390x/translate.c | 6 ++---- target-sh4/translate.c | 14 +++++--------- target-sparc/translate.c | 10 +++++----- target-tilegx/translate.c | 6 ++---- target-tricore/translate.c | 2 ++ target-unicore32/translate.c | 5 +---- target-xtensa/translate.c | 5 +---- 20 files changed, 41 insertions(+), 81 deletions(-) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 76916f434a..60370d69b6 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -2933,16 +2933,14 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(ctx.pc); + if (num_insns + 1 == 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_insn_start(ctx.pc); - } - TCGV_UNUSED_I64(ctx.zero); TCGV_UNUSED_I64(ctx.sink); TCGV_UNUSED_I64(ctx.lit); diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index a618711b64..6a66ac019a 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -11103,15 +11103,12 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(dc->pc); if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(dc->pc); - } - 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 diff --git a/target-arm/translate.c b/target-arm/translate.c index b521fc86f8..83488486b9 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -11348,14 +11348,11 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(dc->pc); if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(dc->pc); - } - 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 diff --git a/target-cris/translate.c b/target-cris/translate.c index c5a22afa66..0a4b363dec 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -2994,10 +2994,6 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc) int insn_len = 2; int i; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(dc->pc); - } - /* Load a halfword onto the instruction register. */ dc->ir = cris_fetch(env, dc, dc->pc, 2, 0); @@ -3197,6 +3193,7 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(dc->pc); /* Pretty disas. */ LOG_DIS("%8.8x:\t", dc->pc); diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c index 12d7dfc45e..3ab1c398e0 100644 --- a/target-cris/translate_v10.c +++ b/target-cris/translate_v10.c @@ -1199,9 +1199,6 @@ static unsigned int crisv10_decoder(CPUCRISState *env, DisasContext *dc) { unsigned int insn_len = 2; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) - tcg_gen_insn_start(dc->pc); - /* Load a halfword onto the instruction register. */ dc->ir = cpu_lduw_code(env, dc->pc); diff --git a/target-i386/translate.c b/target-i386/translate.c index c18f82bfd1..82d32e12f4 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -4401,9 +4401,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, target_ulong next_eip, tval; int rex_w, rex_r; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(pc_start); - } s->pc = pc_start; prefixes = 0; s->override = -1; @@ -7962,6 +7959,8 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(pc_ptr); + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); diff --git a/target-lm32/translate.c b/target-lm32/translate.c index b1b4cbb750..84eeac3437 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -1005,10 +1005,6 @@ static const DecoderInfo decinfo[] = { static inline void decode(DisasContext *dc, uint32_t ir) { - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(dc->pc); - } - dc->ir = ir; LOG_DIS("%8.8x\t", dc->ir); @@ -1106,6 +1102,7 @@ void gen_intermediate_code_internal(LM32CPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(dc->pc); /* Pretty disas. */ LOG_DIS("%8.8x:\t", dc->pc); diff --git a/target-m68k/translate.c b/target-m68k/translate.c index e34bf2b8cd..bfd9c00edf 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2955,10 +2955,6 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) { uint16_t insn; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(s->pc); - } - insn = cpu_lduw_code(env, s->pc); s->pc += 2; @@ -3025,8 +3021,12 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, 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)) + tcg_gen_insn_start(dc->pc); + + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); + } + dc->insn_pc = dc->pc; disas_m68k_insn(env, dc); num_insns++; diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 0d340c0e78..02ccf45da3 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -1588,10 +1588,6 @@ static inline void decode(DisasContext *dc, uint32_t ir) { int i; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(dc->pc); - } - dc->ir = ir; LOG_DIS("%8.8x\t", dc->ir); @@ -1718,6 +1714,7 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(dc->pc); /* Pretty disas. */ LOG_DIS("%8.8x:\t", dc->pc); diff --git a/target-mips/translate.c b/target-mips/translate.c index 2b3f2b00b1..aa0e0fd55e 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -18904,10 +18904,6 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) gen_set_label(l1); } - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(ctx->pc); - } - op = MASK_OP_MAJOR(ctx->opcode); rs = (ctx->opcode >> 21) & 0x1f; rt = (ctx->opcode >> 16) & 0x1f; @@ -19622,8 +19618,11 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, 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)) + tcg_gen_insn_start(ctx.pc); + + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); + } is_slot = ctx.hflags & MIPS_HFLAG_BMASK; if (!(ctx.hflags & MIPS_HFLAG_M16)) { diff --git a/target-moxie/translate.c b/target-moxie/translate.c index 0bb94a02b8..1becfde1b5 100644 --- a/target-moxie/translate.c +++ b/target-moxie/translate.c @@ -153,10 +153,6 @@ static int decode_opc(MoxieCPU *cpu, DisasContext *ctx) /* Set the default instruction length. */ int length = 2; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(ctx->pc); - } - /* Examine the 16-bit opcode. */ opcode = ctx->opcode; @@ -865,6 +861,8 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(ctx.pc); + ctx.opcode = cpu_lduw_code(env, ctx.pc); ctx.pc += decode_opc(cpu, &ctx); num_insns++; diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 727fbba66f..4f9b76833f 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -1687,10 +1687,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, tcg_ctx.gen_opc_instr_start[k] = 1; tcg_ctx.gen_opc_icount[k] = num_insns; } - - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(dc->pc); - } + tcg_gen_insn_start(dc->pc); if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index c46133d9df..6ca3e9fca5 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -11502,6 +11502,8 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(ctx.nip); + LOG_DISAS("----------------\n"); LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n", ctx.nip, ctx.mem_idx, (int)msr_ir); @@ -11515,9 +11517,6 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n", ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode), ctx.le_mode ? "little" : "big"); - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(ctx.nip); - } ctx.nip += 4; table = env->opcodes; num_insns++; diff --git a/target-s390x/translate.c b/target-s390x/translate.c index a87d83c79e..2767f6a35c 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -5370,14 +5370,12 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(dc.pc); + if (++num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(dc.pc); - } - status = NO_EXIT; if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { diff --git a/target-sh4/translate.c b/target-sh4/translate.c index d9d2c02a39..1e43e6d62d 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1790,10 +1790,6 @@ static void decode_opc(DisasContext * ctx) { uint32_t old_flags = ctx->flags; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(ctx->pc); - } - _decode_opc(ctx); if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { @@ -1876,12 +1872,12 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_instr_start[ii] = 1; tcg_ctx.gen_opc_icount[ii] = num_insns; } - if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + tcg_gen_insn_start(ctx.pc); + + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); -#if 0 - fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc); - fflush(stderr); -#endif + } + ctx.opcode = cpu_lduw_code(env, ctx.pc); decode_opc(&ctx); num_insns++; diff --git a/target-sparc/translate.c b/target-sparc/translate.c index ef17e26253..a47e65f15b 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2482,10 +2482,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64; target_long simm; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(dc->pc); - } - opc = GET_FIELD(insn, 0, 1); rd = GET_FIELD(insn, 2, 6); @@ -5271,8 +5267,12 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, tcg_ctx.gen_opc_icount[lj] = num_insns; } } - if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + tcg_gen_insn_start(dc->pc); + + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); + } + last_pc = dc->pc; insn = cpu_ldl_code(env, dc->pc); diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 3fb7fc6a21..6babc3c733 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -2008,10 +2008,6 @@ static void translate_one_bundle(DisasContext *dc, uint64_t bundle) } dc->num_wb = 0; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(dc->pc); - } - qemu_log_mask(CPU_LOG_TB_IN_ASM, " %" PRIx64 ": { ", dc->pc); if (get_Mode(bundle)) { notice_excp(dc, bundle, "y0", decode_y0(dc, bundle)); @@ -2100,6 +2096,8 @@ static inline void gen_intermediate_code_internal(TileGXCPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(dc->pc); + translate_one_bundle(dc, cpu_ldq_data(env, dc->pc)); if (dc->exit_tb) { diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 440f30a843..27564d330f 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -8292,6 +8292,8 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb, tcg_clear_temp_count(); gen_tb_start(tb); while (ctx.bstate == BS_NONE) { + tcg_gen_insn_start(ctx.pc); + ctx.opcode = cpu_ldl_code(env, ctx.pc); decode_opc(env, &ctx, 0); diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 63a5192b59..28db34a41a 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -1794,10 +1794,6 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s) UniCore32CPU *cpu = uc32_env_get_cpu(env); unsigned int insn; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(s->pc); - } - insn = cpu_ldl_code(env, s->pc); s->pc += 4; @@ -1941,6 +1937,7 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } + tcg_gen_insn_start(dc->pc); if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index ea777dabdd..ab9e8f9c21 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -3076,10 +3076,7 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = insn_count; } - - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_insn_start(dc.pc); - } + tcg_gen_insn_start(dc.pc); ++dc.ccount_delta; From 959082fc4a93a016a6b697e1e0c2b373d8a3a373 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 17 Sep 2015 14:25:46 -0700 Subject: [PATCH 03/26] target-*: Increment num_insns immediately after tcg_gen_insn_start This does tidy the icount test common to all targets. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-alpha/translate.c | 4 ++-- target-arm/translate-a64.c | 6 +++--- target-arm/translate.c | 7 ++++--- target-cris/translate.c | 4 ++-- target-i386/translate.c | 5 +++-- target-lm32/translate.c | 5 ++--- target-m68k/translate.c | 4 ++-- target-microblaze/translate.c | 5 +++-- target-mips/translate.c | 5 ++--- target-moxie/translate.c | 2 +- target-openrisc/translate.c | 4 ++-- target-ppc/translate.c | 4 ++-- target-s390x/translate.c | 3 ++- target-sh4/translate.c | 4 ++-- target-sparc/translate.c | 4 ++-- target-tilegx/translate.c | 3 ++- target-tricore/translate.c | 3 +-- target-unicore32/translate.c | 4 ++-- target-xtensa/translate.c | 4 ++-- 19 files changed, 41 insertions(+), 39 deletions(-) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 60370d69b6..fa0ac2dd6b 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -2934,12 +2934,12 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(ctx.pc); + 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++; TCGV_UNUSED_I64(ctx.zero); TCGV_UNUSED_I64(ctx.sink); diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 6a66ac019a..4670941084 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -11104,8 +11104,9 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(dc->pc); + 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(); } @@ -11120,7 +11121,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, * "did not step an insn" case, and so the syndrome ISV and EX * bits should be zero. */ - assert(num_insns == 0); + 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; @@ -11139,7 +11140,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, * Also stop translation when a page boundary is reached. This * ensures prefetch aborts occur at the right place. */ - num_insns++; } while (!dc->is_jmp && !tcg_op_buf_full() && !cs->singlestep_enabled && !singlestep && diff --git a/target-arm/translate.c b/target-arm/translate.c index 83488486b9..cd889977c6 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -11349,9 +11349,11 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(dc->pc); + 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(); + } if (dc->ss_active && !dc->pstate_ss) { /* Singlestep state is Active-pending. @@ -11364,7 +11366,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, * "did not step an insn" case, and so the syndrome ISV and EX * bits should be zero. */ - assert(num_insns == 0); + assert(num_insns == 1); gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0), default_exception_el(dc)); goto done_generating; @@ -11400,7 +11402,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, * 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. */ - num_insns ++; } while (!dc->is_jmp && !tcg_op_buf_full() && !cs->singlestep_enabled && !singlestep && diff --git a/target-cris/translate.c b/target-cris/translate.c index 0a4b363dec..bba7217dd8 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3194,11 +3194,12 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(dc->pc); + num_insns++; /* Pretty disas. */ LOG_DIS("%8.8x:\t", dc->pc); - if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } dc->clear_x = 1; @@ -3210,7 +3211,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, cris_clear_x_flag(dc); } - num_insns++; /* Check for delayed branches here. If we do it before actually generating any host code, the simulator will just loop doing nothing for on this program location. */ diff --git a/target-i386/translate.c b/target-i386/translate.c index 82d32e12f4..3d0c23df09 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7960,12 +7960,13 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(pc_ptr); + 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(); + } pc_ptr = disas_insn(env, dc, pc_ptr); - num_insns++; /* stop translation if indicated */ if (dc->is_jmp) break; diff --git a/target-lm32/translate.c b/target-lm32/translate.c index 84eeac3437..a34914add3 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -1103,18 +1103,17 @@ void gen_intermediate_code_internal(LM32CPU *cpu, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(dc->pc); + num_insns++; /* Pretty disas. */ LOG_DIS("%8.8x:\t", dc->pc); - if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } decode(dc, cpu_ldl_code(env, dc->pc)); dc->pc += 4; - num_insns++; - } while (!dc->is_jmp && !tcg_op_buf_full() && !cs->singlestep_enabled diff --git a/target-m68k/translate.c b/target-m68k/translate.c index bfd9c00edf..422244ef05 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -3022,14 +3022,14 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(dc->pc); + 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(); } dc->insn_pc = dc->pc; disas_m68k_insn(env, dc); - num_insns++; } while (!dc->is_jmp && !tcg_op_buf_full() && !cs->singlestep_enabled && !singlestep && diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 02ccf45da3..a25b042567 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -1715,19 +1715,20 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(dc->pc); + num_insns++; /* Pretty disas. */ LOG_DIS("%8.8x:\t", dc->pc); - if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); + } dc->clear_imm = 1; decode(dc, cpu_ldl_code(env, dc->pc)); if (dc->clear_imm) dc->tb_flags &= ~IMM_FLAG; dc->pc += 4; - num_insns++; if (dc->delayed_branch) { dc->delayed_branch--; diff --git a/target-mips/translate.c b/target-mips/translate.c index aa0e0fd55e..66147d887f 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -19619,8 +19619,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(ctx.pc); + 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(); } @@ -19659,8 +19660,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, } ctx.pc += insn_bytes; - num_insns++; - /* Execute a branch and its delay slot as a single instruction. This is what GDB expects and is consistent with what the hardware does (e.g. if a delay slot instruction faults, the diff --git a/target-moxie/translate.c b/target-moxie/translate.c index 1becfde1b5..f71ed249a0 100644 --- a/target-moxie/translate.c +++ b/target-moxie/translate.c @@ -862,10 +862,10 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(ctx.pc); + num_insns++; ctx.opcode = cpu_lduw_code(env, ctx.pc); ctx.pc += decode_opc(cpu, &ctx); - num_insns++; if (cs->singlestep_enabled) { break; diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 4f9b76833f..f9b4ed5259 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -1688,8 +1688,9 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, tcg_ctx.gen_opc_icount[k] = num_insns; } tcg_gen_insn_start(dc->pc); + 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(); } dc->ppc = dc->pc - 4; @@ -1698,7 +1699,6 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, tcg_gen_movi_tl(cpu_npc, dc->npc); disas_openrisc_insn(dc, cpu); dc->pc = dc->npc; - num_insns++; /* delay slot */ if (dc->delayed_branch) { dc->delayed_branch--; diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 6ca3e9fca5..7c288aaceb 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -11503,11 +11503,12 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(ctx.nip); + num_insns++; LOG_DISAS("----------------\n"); LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n", ctx.nip, ctx.mem_idx, (int)msr_ir); - if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); if (unlikely(need_byteswap(&ctx))) { ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip)); @@ -11519,7 +11520,6 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, opc3(ctx.opcode), ctx.le_mode ? "little" : "big"); ctx.nip += 4; table = env->opcodes; - num_insns++; handler = table[opc1(ctx.opcode)]; if (is_indirect_opcode(handler)) { table = ind_table(handler); diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 2767f6a35c..58cf365c5f 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -5371,8 +5371,9 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(dc.pc); + num_insns++; - if (++num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 1e43e6d62d..e0294e7d4e 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1873,14 +1873,14 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_icount[ii] = num_insns; } tcg_gen_insn_start(ctx.pc); + 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(); } ctx.opcode = cpu_lduw_code(env, ctx.pc); decode_opc(&ctx); - num_insns++; ctx.pc += 2; if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) break; diff --git a/target-sparc/translate.c b/target-sparc/translate.c index a47e65f15b..762eb9b953 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -5268,8 +5268,9 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, } } tcg_gen_insn_start(dc->pc); + 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(); } @@ -5277,7 +5278,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, insn = cpu_ldl_code(env, dc->pc); disas_sparc_insn(dc, insn); - num_insns++; if (dc->is_br) break; diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 6babc3c733..c23b761979 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -2097,6 +2097,7 @@ static inline void gen_intermediate_code_internal(TileGXCPU *cpu, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(dc->pc); + num_insns++; translate_one_bundle(dc, cpu_ldq_data(env, dc->pc)); @@ -2105,7 +2106,7 @@ static inline void gen_intermediate_code_internal(TileGXCPU *cpu, break; } dc->pc += TILEGX_BUNDLE_SIZE_IN_BYTES; - if (++num_insns >= max_insns + if (num_insns >= max_insns || dc->pc >= next_page_start || tcg_op_buf_full()) { /* Ending the TB due to TB size or page boundary. Set PC. */ diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 27564d330f..fa10d5c23e 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -8293,12 +8293,11 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb, gen_tb_start(tb); while (ctx.bstate == BS_NONE) { tcg_gen_insn_start(ctx.pc); + num_insns++; ctx.opcode = cpu_ldl_code(env, ctx.pc); decode_opc(env, &ctx, 0); - num_insns++; - if (tcg_op_buf_full()) { gen_save_pc(ctx.next_pc); tcg_gen_exit_tb(0); diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 28db34a41a..7aad61f76f 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -1938,8 +1938,9 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu, tcg_ctx.gen_opc_icount[lj] = num_insns; } tcg_gen_insn_start(dc->pc); + 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(); } @@ -1958,7 +1959,6 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu, * 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. */ - num_insns++; } while (!dc->is_jmp && !tcg_op_buf_full() && !cs->singlestep_enabled && !singlestep && diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index ab9e8f9c21..3607e41535 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -3077,10 +3077,11 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, tcg_ctx.gen_opc_icount[lj] = insn_count; } tcg_gen_insn_start(dc.pc); + ++insn_count; ++dc.ccount_delta; - if (insn_count + 1 == max_insns && (tb->cflags & CF_LAST_IO)) { + if (insn_count == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } @@ -3101,7 +3102,6 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, } disas_xtensa_insn(env, &dc); - ++insn_count; if (dc.icount) { tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount); } From b933066ae03d924a92b2616b4a24e7d91cd5b841 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 17 Sep 2015 15:58:10 -0700 Subject: [PATCH 04/26] target-*: Introduce and use cpu_breakpoint_test Reduce the boilerplate required for each target. At the same time, move the test for breakpoint after calling tcg_gen_insn_start. Note that arm and aarch64 do not use cpu_breakpoint_test, but still move the inline test down after tcg_gen_insn_start. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- include/qom/cpu.h | 16 ++++++++++++++++ target-alpha/translate.c | 13 ++++--------- target-arm/translate-a64.c | 26 ++++++++++++------------- target-arm/translate.c | 31 +++++++++++++++--------------- target-cris/translate.c | 27 ++++++++------------------ target-i386/translate.c | 17 +++++++---------- target-lm32/translate.c | 25 +++++++----------------- target-m68k/translate.c | 18 ++++++------------ target-microblaze/translate.c | 36 +++++++++++++---------------------- target-mips/translate.c | 25 ++++++++++-------------- target-moxie/translate.c | 19 +++++++----------- target-openrisc/translate.c | 24 +++++++---------------- target-ppc/translate.c | 14 +++++--------- target-s390x/translate.c | 16 ++++++---------- target-sh4/translate.c | 20 ++++++++----------- target-sparc/translate.c | 23 ++++++++++------------ target-unicore32/translate.c | 24 ++++++++++------------- target-xtensa/translate.c | 25 +++++++----------------- 18 files changed, 160 insertions(+), 239 deletions(-) diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 9405554a2b..b613ff0329 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -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, diff --git a/target-alpha/translate.c b/target-alpha/translate.c index fa0ac2dd6b..c10193ea91 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -2868,7 +2868,6 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu, target_ulong pc_start; target_ulong pc_mask; uint32_t insn; - CPUBreakpoint *bp; int j, lj = -1; ExitStatus ret; int num_insns; @@ -2913,14 +2912,6 @@ 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) { - gen_excp(&ctx, EXCP_DEBUG, 0); - break; - } - } - } if (search_pc) { j = tcg_op_buf_count(); if (lj < j) { @@ -2936,6 +2927,10 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu, 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 (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 4670941084..bc2040e47b 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -11007,7 +11007,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, CPUState *cs = CPU(cpu); CPUARMState *env = &cpu->env; DisasContext dc1, *dc = &dc1; - CPUBreakpoint *bp; int j, lj; target_ulong pc_start; target_ulong next_page_start; @@ -11079,18 +11078,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, tcg_clear_temp_count(); do { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - gen_exception_internal_insn(dc, 0, EXCP_DEBUG); - /* Advance PC so that clearing the breakpoint will - invalidate this TB. */ - dc->pc += 2; - goto done_generating; - } - } - } - if (search_pc) { j = tcg_op_buf_count(); if (lj < j) { @@ -11106,6 +11093,19 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, tcg_gen_insn_start(dc->pc); num_insns++; + if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { + CPUBreakpoint *bp; + QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { + if (bp->pc == dc->pc) { + gen_exception_internal_insn(dc, 0, EXCP_DEBUG); + /* Advance PC so that clearing the breakpoint will + invalidate this TB. */ + dc->pc += 2; + goto done_generating; + } + } + } + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } diff --git a/target-arm/translate.c b/target-arm/translate.c index cd889977c6..44468dca1f 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -11177,7 +11177,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, CPUState *cs = CPU(cpu); CPUARMState *env = &cpu->env; DisasContext dc1, *dc = &dc1; - CPUBreakpoint *bp; int j, lj; target_ulong pc_start; target_ulong next_page_start; @@ -11306,6 +11305,21 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, store_cpu_field(tmp, condexec_bits); } do { + 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] = dc->pc; + gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1); + tcg_ctx.gen_opc_instr_start[lj] = 1; + tcg_ctx.gen_opc_icount[lj] = num_insns; + } + tcg_gen_insn_start(dc->pc); + num_insns++; + #ifdef CONFIG_USER_ONLY /* Intercept jump to the magic kernel page. */ if (dc->pc >= 0xffff0000) { @@ -11326,6 +11340,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, #endif if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { + CPUBreakpoint *bp; QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { if (bp->pc == dc->pc) { gen_exception_internal_insn(dc, 0, EXCP_DEBUG); @@ -11336,20 +11351,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, } } } - 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] = dc->pc; - gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1); - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } - tcg_gen_insn_start(dc->pc); - num_insns++; if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); diff --git a/target-cris/translate.c b/target-cris/translate.c index bba7217dd8..477bddc64b 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3030,23 +3030,6 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc) return insn_len; } -static void check_breakpoint(CPUCRISState *env, DisasContext *dc) -{ - CPUState *cs = CPU(cris_env_get_cpu(env)); - CPUBreakpoint *bp; - - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - cris_evaluate_flags(dc); - tcg_gen_movi_tl(env_pc, dc->pc); - t_gen_raise_exception(EXCP_DEBUG); - dc->is_jmp = DISAS_UPDATE; - } - } - } -} - #include "translate_v10.c" /* @@ -3175,8 +3158,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, gen_tb_start(tb); do { - check_breakpoint(env, dc); - if (search_pc) { j = tcg_op_buf_count(); if (lj < j) { @@ -3196,6 +3177,14 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, tcg_gen_insn_start(dc->pc); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { + cris_evaluate_flags(dc); + tcg_gen_movi_tl(env_pc, dc->pc); + t_gen_raise_exception(EXCP_DEBUG); + dc->is_jmp = DISAS_UPDATE; + break; + } + /* Pretty disas. */ LOG_DIS("%8.8x:\t", dc->pc); diff --git a/target-i386/translate.c b/target-i386/translate.c index 3d0c23df09..9ec9c4c61a 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7849,7 +7849,6 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, CPUX86State *env = &cpu->env; DisasContext dc1, *dc = &dc1; target_ulong pc_ptr; - CPUBreakpoint *bp; int j, lj; uint64_t flags; target_ulong pc_start; @@ -7938,15 +7937,6 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, gen_tb_start(tb); for(;;) { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == pc_ptr && - !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) { - gen_debug(dc, pc_ptr - dc->cs_base); - goto done_generating; - } - } - } if (search_pc) { j = tcg_op_buf_count(); if (lj < j) { @@ -7962,6 +7952,13 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, tcg_gen_insn_start(pc_ptr); num_insns++; + /* If RF is set, suppress an internally generated breakpoint. */ + if (unlikely(cpu_breakpoint_test(cs, pc_ptr, + tb->flags & HF_RF_MASK + ? BP_GDB : BP_ANY))) { + gen_debug(dc, pc_ptr - dc->cs_base); + goto done_generating; + } if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } diff --git a/target-lm32/translate.c b/target-lm32/translate.c index a34914add3..8ea7929ccb 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -1032,22 +1032,6 @@ static inline void decode(DisasContext *dc, uint32_t ir) decinfo[dc->opcode](dc); } -static void check_breakpoint(CPULM32State *env, DisasContext *dc) -{ - CPUState *cs = CPU(lm32_env_get_cpu(env)); - CPUBreakpoint *bp; - - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - tcg_gen_movi_tl(cpu_pc, dc->pc); - t_gen_raise_exception(dc, EXCP_DEBUG); - dc->is_jmp = DISAS_UPDATE; - } - } - } -} - /* generate intermediate code for basic block 'tb'. */ static inline void gen_intermediate_code_internal(LM32CPU *cpu, @@ -1088,8 +1072,6 @@ void gen_intermediate_code_internal(LM32CPU *cpu, gen_tb_start(tb); do { - check_breakpoint(env, dc); - if (search_pc) { j = tcg_op_buf_count(); if (lj < j) { @@ -1105,6 +1087,13 @@ void gen_intermediate_code_internal(LM32CPU *cpu, tcg_gen_insn_start(dc->pc); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { + tcg_gen_movi_tl(cpu_pc, dc->pc); + t_gen_raise_exception(dc, EXCP_DEBUG); + dc->is_jmp = DISAS_UPDATE; + break; + } + /* Pretty disas. */ LOG_DIS("%8.8x:\t", dc->pc); diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 422244ef05..afef37f6f0 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2969,7 +2969,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, CPUState *cs = CPU(cpu); CPUM68KState *env = &cpu->env; DisasContext dc1, *dc = &dc1; - CPUBreakpoint *bp; int j, lj; target_ulong pc_start; int pc_offset; @@ -2999,17 +2998,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, do { pc_offset = dc->pc - pc_start; gen_throws_exception = NULL; - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - gen_exception(dc, dc->pc, EXCP_DEBUG); - dc->is_jmp = DISAS_JUMP; - break; - } - } - if (dc->is_jmp) - break; - } if (search_pc) { j = tcg_op_buf_count(); if (lj < j) { @@ -3024,6 +3012,12 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, tcg_gen_insn_start(dc->pc); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { + gen_exception(dc, dc->pc, EXCP_DEBUG); + dc->is_jmp = DISAS_JUMP; + break; + } + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index a25b042567..1224456662 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -1626,21 +1626,6 @@ static inline void decode(DisasContext *dc, uint32_t ir) } } -static void check_breakpoint(CPUMBState *env, DisasContext *dc) -{ - CPUState *cs = CPU(mb_env_get_cpu(env)); - CPUBreakpoint *bp; - - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - t_gen_raise_exception(dc, EXCP_DEBUG); - dc->is_jmp = DISAS_UPDATE; - } - } - } -} - /* generate intermediate code for basic block 'tb'. */ static inline void gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, @@ -1695,14 +1680,6 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, gen_tb_start(tb); do { -#if SIM_COMPAT - if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { - tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); - gen_helper_debug(); - } -#endif - check_breakpoint(env, dc); - if (search_pc) { j = tcg_op_buf_count(); if (lj < j) { @@ -1717,6 +1694,19 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, tcg_gen_insn_start(dc->pc); num_insns++; +#if SIM_COMPAT + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { + tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc); + gen_helper_debug(); + } +#endif + + if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { + t_gen_raise_exception(dc, EXCP_DEBUG); + dc->is_jmp = DISAS_UPDATE; + break; + } + /* Pretty disas. */ LOG_DIS("%8.8x:\t", dc->pc); diff --git a/target-mips/translate.c b/target-mips/translate.c index 66147d887f..57e826db21 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -19544,7 +19544,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, DisasContext ctx; target_ulong pc_start; target_ulong next_page_start; - CPUBreakpoint *bp; int j, lj = -1; int num_insns; int max_insns; @@ -19591,20 +19590,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags); gen_tb_start(tb); while (ctx.bstate == BS_NONE) { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == ctx.pc) { - save_cpu_state(&ctx, 1); - ctx.bstate = BS_BRANCH; - gen_helper_raise_exception_debug(cpu_env); - /* Include the breakpoint location or the tb won't - * be flushed when it must be. */ - ctx.pc += 4; - goto done_generating; - } - } - } - if (search_pc) { j = tcg_op_buf_count(); if (lj < j) { @@ -19621,6 +19606,16 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, tcg_gen_insn_start(ctx.pc); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) { + save_cpu_state(&ctx, 1); + ctx.bstate = BS_BRANCH; + gen_helper_raise_exception_debug(cpu_env); + /* Include the breakpoint location or the tb won't + * be flushed when it must be. */ + ctx.pc += 4; + goto done_generating; + } + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } diff --git a/target-moxie/translate.c b/target-moxie/translate.c index f71ed249a0..d71f55bf38 100644 --- a/target-moxie/translate.c +++ b/target-moxie/translate.c @@ -822,7 +822,6 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, CPUState *cs = CPU(cpu); DisasContext ctx; target_ulong pc_start; - CPUBreakpoint *bp; int j, lj = -1; CPUMoxieState *env = &cpu->env; int num_insns; @@ -838,17 +837,6 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, gen_tb_start(tb); do { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (ctx.pc == bp->pc) { - tcg_gen_movi_i32(cpu_pc, ctx.pc); - gen_helper_debug(cpu_env); - ctx.bstate = BS_EXCP; - goto done_generating; - } - } - } - if (search_pc) { j = tcg_op_buf_count(); if (lj < j) { @@ -864,6 +852,13 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, tcg_gen_insn_start(ctx.pc); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) { + tcg_gen_movi_i32(cpu_pc, ctx.pc); + gen_helper_debug(cpu_env); + ctx.bstate = BS_EXCP; + goto done_generating; + } + ctx.opcode = cpu_lduw_code(env, ctx.pc); ctx.pc += decode_opc(cpu, &ctx); diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index f9b4ed5259..9755850006 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -1618,22 +1618,6 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) } } -static void check_breakpoint(OpenRISCCPU *cpu, DisasContext *dc) -{ - CPUState *cs = CPU(cpu); - CPUBreakpoint *bp; - - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - tcg_gen_movi_tl(cpu_pc, dc->pc); - gen_exception(dc, EXCP_DEBUG); - dc->is_jmp = DISAS_UPDATE; - } - } - } -} - static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, TranslationBlock *tb, int search_pc) @@ -1674,7 +1658,6 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, gen_tb_start(tb); do { - check_breakpoint(cpu, dc); if (search_pc) { j = tcg_op_buf_count(); if (k < j) { @@ -1690,6 +1673,13 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, tcg_gen_insn_start(dc->pc); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { + tcg_gen_movi_tl(cpu_pc, dc->pc); + gen_exception(dc, EXCP_DEBUG); + dc->is_jmp = DISAS_UPDATE; + break; + } + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 7c288aaceb..fc234a32c8 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -11418,7 +11418,6 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, DisasContext ctx, *ctxp = &ctx; opc_handler_t **table, *handler; target_ulong pc_start; - CPUBreakpoint *bp; int j, lj = -1; int num_insns; int max_insns; @@ -11483,14 +11482,6 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, tcg_clear_temp_count(); /* Set env in case of segfault during code fetch */ while (ctx.exception == POWERPC_EXCP_NONE && !tcg_op_buf_full()) { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == ctx.nip) { - gen_debug_exception(ctxp); - break; - } - } - } if (unlikely(search_pc)) { j = tcg_op_buf_count(); if (lj < j) { @@ -11505,6 +11496,11 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, tcg_gen_insn_start(ctx.nip); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, ctx.nip, BP_ANY))) { + gen_debug_exception(ctxp); + break; + } + LOG_DISAS("----------------\n"); LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n", ctx.nip, ctx.mem_idx, (int)msr_ir); diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 58cf365c5f..4959828111 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -5330,7 +5330,6 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu, uint64_t next_page_start; int j, lj = -1; int num_insns, max_insns; - CPUBreakpoint *bp; ExitStatus status; bool do_debug; @@ -5373,20 +5372,17 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu, tcg_gen_insn_start(dc.pc); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) { + status = EXIT_PC_STALE; + do_debug = true; + break; + } + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } status = NO_EXIT; - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc.pc) { - status = EXIT_PC_STALE; - do_debug = true; - break; - } - } - } if (status == NO_EXIT) { status = translate_one(env, &dc); } diff --git a/target-sh4/translate.c b/target-sh4/translate.c index e0294e7d4e..53bf9e8d2c 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1824,7 +1824,6 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, CPUSH4State *env = &cpu->env; DisasContext ctx; target_ulong pc_start; - CPUBreakpoint *bp; int i, ii; int num_insns; int max_insns; @@ -1849,17 +1848,6 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, max_insns = CF_COUNT_MASK; gen_tb_start(tb); while (ctx.bstate == BS_NONE && !tcg_op_buf_full()) { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (ctx.pc == bp->pc) { - /* We have hit a breakpoint - make sure PC is up-to-date */ - tcg_gen_movi_i32(cpu_pc, ctx.pc); - gen_helper_debug(cpu_env); - ctx.bstate = BS_BRANCH; - break; - } - } - } if (search_pc) { i = tcg_op_buf_count(); if (ii < i) { @@ -1875,6 +1863,14 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, tcg_gen_insn_start(ctx.pc); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) { + /* We have hit a breakpoint - make sure PC is up-to-date */ + tcg_gen_movi_i32(cpu_pc, ctx.pc); + gen_helper_debug(cpu_env); + ctx.bstate = BS_BRANCH; + break; + } + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 762eb9b953..f359ac9187 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -5217,7 +5217,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, CPUSPARCState *env = &cpu->env; target_ulong pc_start, last_pc; DisasContext dc1, *dc = &dc1; - CPUBreakpoint *bp; int j, lj = -1; int num_insns; int max_insns; @@ -5242,18 +5241,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, max_insns = CF_COUNT_MASK; gen_tb_start(tb); do { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - if (dc->pc != pc_start) - save_state(dc); - gen_helper_debug(cpu_env); - tcg_gen_exit_tb(0); - dc->is_br = 1; - goto exit_gen_loop; - } - } - } if (spc) { qemu_log("Search PC...\n"); j = tcg_op_buf_count(); @@ -5270,6 +5257,16 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, tcg_gen_insn_start(dc->pc); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { + if (dc->pc != pc_start) { + save_state(dc); + } + gen_helper_debug(cpu_env); + tcg_gen_exit_tb(0); + dc->is_br = 1; + goto exit_gen_loop; + } + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 7aad61f76f..cd23c4b756 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -1872,7 +1872,6 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu, CPUState *cs = CPU(cpu); CPUUniCore32State *env = &cpu->env; DisasContext dc1, *dc = &dc1; - CPUBreakpoint *bp; int j, lj; target_ulong pc_start; uint32_t next_page_start; @@ -1912,19 +1911,6 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu, gen_tb_start(tb); do { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - gen_set_pc_im(dc->pc); - gen_exception(EXCP_DEBUG); - dc->is_jmp = DISAS_JUMP; - /* Advance PC so that clearing the breakpoint will - invalidate this TB. */ - dc->pc += 2; /* FIXME */ - goto done_generating; - } - } - } if (search_pc) { j = tcg_op_buf_count(); if (lj < j) { @@ -1940,6 +1926,16 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu, tcg_gen_insn_start(dc->pc); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { + gen_set_pc_im(dc->pc); + gen_exception(EXCP_DEBUG); + dc->is_jmp = DISAS_JUMP; + /* Advance PC so that clearing the breakpoint will + invalidate this TB. */ + dc->pc += 2; /* FIXME */ + goto done_generating; + } + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 3607e41535..ea87cb5794 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -2984,22 +2984,6 @@ static inline unsigned xtensa_insn_len(CPUXtensaState *env, DisasContext *dc) return xtensa_op0_insn_len(OP0); } -static void check_breakpoint(CPUXtensaState *env, DisasContext *dc) -{ - CPUState *cs = CPU(xtensa_env_get_cpu(env)); - CPUBreakpoint *bp; - - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - tcg_gen_movi_i32(cpu_pc, dc->pc); - gen_exception(dc, EXCP_DEBUG); - dc->is_jmp = DISAS_UPDATE; - } - } - } -} - static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc) { unsigned i; @@ -3062,8 +3046,6 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, } do { - check_breakpoint(env, &dc); - if (search_pc) { j = tcg_op_buf_count(); if (lj < j) { @@ -3081,6 +3063,13 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, ++dc.ccount_delta; + if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) { + tcg_gen_movi_i32(cpu_pc, dc.pc); + gen_exception(&dc, EXCP_DEBUG); + dc.is_jmp = DISAS_UPDATE; + break; + } + if (insn_count == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); } From 9aef40ed1f6e2bd794bbb3ba8c8b773e506334c9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 30 Aug 2015 09:21:33 -0700 Subject: [PATCH 05/26] tcg: Allow extra data to be attached to insn_start With an eye toward having this data replace the gen_opc_* arrays that each target collects in order to enable restore_state_from_tb. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- tcg/tcg-op.h | 54 ++++++++++++++++++++++++++++++++++++++++++--------- tcg/tcg-opc.h | 4 ++-- tcg/tcg.c | 13 +++++++------ tcg/tcg.h | 6 ++++++ 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 6409db8893..4e20dc1a6b 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -700,17 +700,53 @@ static inline void tcg_gen_concat32_i64(TCGv_i64 ret, TCGv_i64 lo, TCGv_i64 hi) #error must include QEMU headers #endif -/* debug info: write the PC of the corresponding QEMU CPU instruction */ -static inline void tcg_gen_insn_start(uint64_t pc) +#if TARGET_INSN_START_WORDS == 1 +# if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS +static inline void tcg_gen_insn_start(target_ulong pc) { - /* XXX: must really use a 32 bit size for TCGArg in all cases */ -#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS - tcg_gen_op2ii(INDEX_op_insn_start, - (uint32_t)(pc), (uint32_t)(pc >> 32)); -#else - tcg_gen_op1i(INDEX_op_insn_start, pc); -#endif + tcg_gen_op1(&tcg_ctx, INDEX_op_insn_start, pc); } +# else +static inline void tcg_gen_insn_start(target_ulong pc) +{ + tcg_gen_op2(&tcg_ctx, INDEX_op_insn_start, + (uint32_t)pc, (uint32_t)(pc >> 32)); +} +# endif +#elif TARGET_INSN_START_WORDS == 2 +# if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS +static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1) +{ + tcg_gen_op2(&tcg_ctx, INDEX_op_insn_start, pc, a1); +} +# else +static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1) +{ + tcg_gen_op4(&tcg_ctx, INDEX_op_insn_start, + (uint32_t)pc, (uint32_t)(pc >> 32), + (uint32_t)a1, (uint32_t)(a1 >> 32)); +} +# endif +#elif TARGET_INSN_START_WORDS == 3 +# if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS +static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1, + target_ulong a2) +{ + tcg_gen_op3(&tcg_ctx, INDEX_op_insn_start, pc, a1, a2); +} +# else +static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1, + target_ulong a2) +{ + tcg_gen_op6(&tcg_ctx, INDEX_op_insn_start, + (uint32_t)pc, (uint32_t)(pc >> 32), + (uint32_t)a1, (uint32_t)(a1 >> 32), + (uint32_t)a2, (uint32_t)(a2 >> 32)); +} +# endif +#else +# error "Unhandled number of operands to insn_start" +#endif static inline void tcg_gen_exit_tb(uintptr_t val) { diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index f60d3c2d4e..c6f95703eb 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -175,9 +175,9 @@ DEF(mulsh_i64, 1, 2, 0, IMPL(TCG_TARGET_HAS_mulsh_i64)) /* QEMU specific */ #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS -DEF(insn_start, 0, 0, 2, TCG_OPF_NOT_PRESENT) +DEF(insn_start, 0, 0, 2 * TARGET_INSN_START_WORDS, TCG_OPF_NOT_PRESENT) #else -DEF(insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT) +DEF(insn_start, 0, 0, TARGET_INSN_START_WORDS, TCG_OPF_NOT_PRESENT) #endif DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END) DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END) diff --git a/tcg/tcg.c b/tcg/tcg.c index df8788bac5..3308d6822e 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -991,16 +991,17 @@ void tcg_dump_ops(TCGContext *s) args = &s->gen_opparam_buf[op->args]; if (c == INDEX_op_insn_start) { - uint64_t pc; + qemu_log("%s ----", oi != s->gen_first_op_idx ? "\n" : ""); + + for (i = 0; i < TARGET_INSN_START_WORDS; ++i) { + target_ulong a; #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS - pc = ((uint64_t)args[1] << 32) | args[0]; + a = ((target_ulong)args[i * 2 + 1] << 32) | args[i * 2]; #else - pc = args[0]; + a = args[i]; #endif - if (oi != s->gen_first_op_idx) { - qemu_log("\n"); + qemu_log(" " TARGET_FMT_lx, a); } - qemu_log(" ---- 0x%" PRIx64, pc); } else if (c == INDEX_op_call) { /* variable number of arguments */ nb_oargs = op->callo; diff --git a/tcg/tcg.h b/tcg/tcg.h index 879a665012..c975076b84 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -129,6 +129,12 @@ typedef uint64_t TCGRegSet; # error "Missing unsigned widening multiply" #endif +#ifndef TARGET_INSN_START_EXTRA_WORDS +# define TARGET_INSN_START_WORDS 1 +#else +# define TARGET_INSN_START_WORDS (1 + TARGET_INSN_START_EXTRA_WORDS) +#endif + typedef enum TCGOpcode { #define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name, #include "tcg-opc.h" From 52e971d9ff67e340ac2a86bd67e14bd31c7991e0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 30 Aug 2015 09:22:06 -0700 Subject: [PATCH 06/26] target-arm: Add condexec state to insn_start Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-arm/cpu.h | 1 + target-arm/translate-a64.c | 2 +- target-arm/translate.c | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index cc1578c9e8..cebd46360e 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -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. diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index bc2040e47b..654a58645c 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -11090,7 +11090,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } - tcg_gen_insn_start(dc->pc); + tcg_gen_insn_start(dc->pc, 0); num_insns++; if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { diff --git a/target-arm/translate.c b/target-arm/translate.c index 44468dca1f..fb69ecb03d 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -11317,7 +11317,8 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } - tcg_gen_insn_start(dc->pc); + tcg_gen_insn_start(dc->pc, + (dc->condexec_cond << 4) | (dc->condexec_mask >> 1)); num_insns++; #ifdef CONFIG_USER_ONLY From 2066d09516ba34d0d180fdea451436d9babb3308 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 30 Aug 2015 09:24:58 -0700 Subject: [PATCH 07/26] target-i386: Add cc_op state to insn_start Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-i386/cpu.h | 1 + target-i386/translate.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 8926780e85..2b2a29d6a5 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -794,6 +794,7 @@ typedef struct { #define MAX_GP_COUNTERS (MSR_IA32_PERF_STATUS - MSR_P6_EVNTSEL0) #define NB_MMU_MODES 3 +#define TARGET_INSN_START_EXTRA_WORDS 1 #define NB_OPMASK_REGS 8 diff --git a/target-i386/translate.c b/target-i386/translate.c index 9ec9c4c61a..7501b919e3 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7949,7 +7949,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } - tcg_gen_insn_start(pc_ptr); + tcg_gen_insn_start(pc_ptr, dc->cc_op); num_insns++; /* If RF is set, suppress an internally generated breakpoint. */ From c20d594e45bc8c4b21be1a7637cba0f279f72879 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 30 Aug 2015 09:25:36 -0700 Subject: [PATCH 08/26] target-mips: Add delayed branch state to insn_start Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-mips/cpu.h | 1 + target-mips/translate.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index ec5f991dfb..532b39ea1f 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -130,6 +130,7 @@ struct CPUMIPSFPUContext { }; #define NB_MMU_MODES 3 +#define TARGET_INSN_START_EXTRA_WORDS 2 typedef struct CPUMIPSMVPContext CPUMIPSMVPContext; struct CPUMIPSMVPContext { diff --git a/target-mips/translate.c b/target-mips/translate.c index 57e826db21..30d7d46c47 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -19562,6 +19562,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, ctx.CP0_Config1 = env->CP0_Config1; ctx.tb = tb; ctx.bstate = BS_NONE; + ctx.btarget = 0; ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff; ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1; ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3; @@ -19603,7 +19604,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } - tcg_gen_insn_start(ctx.pc); + tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget); num_insns++; if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) { From a3fd522048f6728d8259e14596c9632c7c67305a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 30 Aug 2015 09:26:10 -0700 Subject: [PATCH 09/26] target-s390x: Add cc_op state to insn_start Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-s390x/cpu.h | 1 + target-s390x/translate.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 5acd54c6ca..b927c66404 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -42,6 +42,7 @@ #include "fpu/softfloat.h" #define NB_MMU_MODES 3 +#define TARGET_INSN_START_EXTRA_WORDS 1 #define MMU_MODE0_SUFFIX _primary #define MMU_MODE1_SUFFIX _secondary diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 4959828111..6bbc760596 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -5369,7 +5369,7 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } - tcg_gen_insn_start(dc.pc); + tcg_gen_insn_start(dc.pc, dc.cc_op); num_insns++; if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) { From 07f3c16ced2b869228d58683c1dea06e3e1c9aa5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 30 Aug 2015 09:28:52 -0700 Subject: [PATCH 10/26] target-sh4: Add flags state to insn_start Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-sh4/cpu.h | 1 + target-sh4/translate.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 6fb63215ef..145e5df0d1 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -120,6 +120,7 @@ typedef struct tlb_t { #define ITLB_SIZE 4 #define NB_MMU_MODES 2 +#define TARGET_INSN_START_EXTRA_WORDS 1 enum sh_features { SH_FEATURE_SH4A = 1, diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 53bf9e8d2c..efaa6f6a87 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1860,7 +1860,7 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_instr_start[ii] = 1; tcg_ctx.gen_opc_icount[ii] = num_insns; } - tcg_gen_insn_start(ctx.pc); + tcg_gen_insn_start(ctx.pc, ctx.flags); num_insns++; if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) { From bd03c791a6ed1bb7aec17df15cfeea649362e8fd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 30 Aug 2015 09:35:14 -0700 Subject: [PATCH 11/26] target-cris: Mirror gen_opc_pc into insn_start This perhaps isn't ideal in terms of (ab)using the "pc" field to encode both pc and ppc + delay branch state, as one has to be aware of this when examining opcode dumps. But it preserves existing logic, which will be good for bisection, and it certainly does save storage space. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-cris/translate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target-cris/translate.c b/target-cris/translate.c index 477bddc64b..3d55a6ad68 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3174,7 +3174,8 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } - tcg_gen_insn_start(dc->pc); + tcg_gen_insn_start(dc->delayed_branch == 1 + ? dc->ppc | 1 : dc->pc); num_insns++; if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { From bfa31b765798139804ce9e5e35c7e142d233df31 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 31 Aug 2015 12:44:16 -0700 Subject: [PATCH 12/26] target-sparc: Tidy gen_branch_a interface We always pass pc2 == dc->npc and r_cond == cpu_cond, and always set is_br afterward. Infer all of that. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-sparc/translate.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index f359ac9187..cbc90d8246 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -955,17 +955,19 @@ static inline void gen_branch2(DisasContext *dc, target_ulong pc1, gen_goto_tb(dc, 1, pc2, pc2 + 4); } -static inline void gen_branch_a(DisasContext *dc, target_ulong pc1, - target_ulong pc2, TCGv r_cond) +static void gen_branch_a(DisasContext *dc, target_ulong pc1) { TCGLabel *l1 = gen_new_label(); + target_ulong npc = dc->npc; - tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cond, 0, l1); - gen_goto_tb(dc, 0, pc2, pc1); + gen_goto_tb(dc, 0, npc, pc1); gen_set_label(l1); - gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8); + gen_goto_tb(dc, 1, npc + 4, npc + 8); + + dc->is_br = 1; } static inline void gen_generic_branch(DisasContext *dc) @@ -1398,8 +1400,7 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc) flush_cond(dc); gen_cond(cpu_cond, cc, cond, dc); if (a) { - gen_branch_a(dc, target, dc->npc, cpu_cond); - dc->is_br = 1; + gen_branch_a(dc, target); } else { dc->pc = dc->npc; dc->jump_pc[0] = target; @@ -1447,8 +1448,7 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc) flush_cond(dc); gen_fcond(cpu_cond, cc, cond); if (a) { - gen_branch_a(dc, target, dc->npc, cpu_cond); - dc->is_br = 1; + gen_branch_a(dc, target); } else { dc->pc = dc->npc; dc->jump_pc[0] = target; @@ -1476,8 +1476,7 @@ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn, flush_cond(dc); gen_cond_reg(cpu_cond, cond, r_reg); if (a) { - gen_branch_a(dc, target, dc->npc, cpu_cond); - dc->is_br = 1; + gen_branch_a(dc, target); } else { dc->pc = dc->npc; dc->jump_pc[0] = target; From 2bf2e019ed0a6349220620240c0ba807846793b9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 31 Aug 2015 13:01:47 -0700 Subject: [PATCH 13/26] target-sparc: Split out gen_branch_n Unify three copies of this code from different branch types. Fix the case when npc == DYNAMIC_PC, i.e. a branch within a delay slot. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-sparc/translate.c | 55 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index cbc90d8246..c6a8d86400 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -970,6 +970,31 @@ static void gen_branch_a(DisasContext *dc, target_ulong pc1) dc->is_br = 1; } +static void gen_branch_n(DisasContext *dc, target_ulong pc1) +{ + target_ulong npc = dc->npc; + + if (likely(npc != DYNAMIC_PC)) { + dc->pc = npc; + dc->jump_pc[0] = pc1; + dc->jump_pc[1] = npc + 4; + dc->npc = JUMP_PC; + } else { + TCGv t, z; + + tcg_gen_mov_tl(cpu_pc, cpu_npc); + + tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); + t = tcg_const_tl(pc1); + z = tcg_const_tl(0); + tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, z, t, cpu_npc); + tcg_temp_free(t); + tcg_temp_free(z); + + dc->pc = DYNAMIC_PC; + } +} + static inline void gen_generic_branch(DisasContext *dc) { TCGv npc0 = tcg_const_tl(dc->jump_pc[0]); @@ -1402,15 +1427,7 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc) if (a) { gen_branch_a(dc, target); } else { - dc->pc = dc->npc; - dc->jump_pc[0] = target; - if (unlikely(dc->npc == DYNAMIC_PC)) { - dc->jump_pc[1] = DYNAMIC_PC; - tcg_gen_addi_tl(cpu_pc, cpu_npc, 4); - } else { - dc->jump_pc[1] = dc->npc + 4; - dc->npc = JUMP_PC; - } + gen_branch_n(dc, target); } } } @@ -1450,15 +1467,7 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc) if (a) { gen_branch_a(dc, target); } else { - dc->pc = dc->npc; - dc->jump_pc[0] = target; - if (unlikely(dc->npc == DYNAMIC_PC)) { - dc->jump_pc[1] = DYNAMIC_PC; - tcg_gen_addi_tl(cpu_pc, cpu_npc, 4); - } else { - dc->jump_pc[1] = dc->npc + 4; - dc->npc = JUMP_PC; - } + gen_branch_n(dc, target); } } } @@ -1478,15 +1487,7 @@ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn, if (a) { gen_branch_a(dc, target); } else { - dc->pc = dc->npc; - dc->jump_pc[0] = target; - if (unlikely(dc->npc == DYNAMIC_PC)) { - dc->jump_pc[1] = DYNAMIC_PC; - tcg_gen_addi_tl(cpu_pc, cpu_npc, 4); - } else { - dc->jump_pc[1] = dc->npc + 4; - dc->npc = JUMP_PC; - } + gen_branch_n(dc, target); } } From 6c42444f9a53b6af39d46008cb9f650b11e96cb9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 31 Aug 2015 13:24:44 -0700 Subject: [PATCH 14/26] target-sparc: Remove gen_opc_jump_pc Since jump_pc[1] is always npc + 4, we can infer after incrementing that jump_pc[1] == pc + 4. Because of that, we can encode the branch destination into a single word, and store that in npc. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-sparc/translate.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index c6a8d86400..25b5bc04a9 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -65,7 +65,6 @@ static TCGv cpu_wim; static TCGv_i64 cpu_fpr[TARGET_DPREGS]; static target_ulong gen_opc_npc[OPC_BUF_SIZE]; -static target_ulong gen_opc_jump_pc[2]; #include "exec/gen-icount.h" @@ -5250,6 +5249,10 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_pc[lj] = dc->pc; gen_opc_npc[lj] = dc->npc; + if (dc->npc & JUMP_PC) { + assert(dc->jump_pc[1] == dc->pc + 4); + gen_opc_npc[lj] = dc->jump_pc[0] | JUMP_PC; + } tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_icount[lj] = num_insns; } @@ -5321,8 +5324,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, #if 0 log_page_dump(); #endif - gen_opc_jump_pc[0] = dc->jump_pc[0]; - gen_opc_jump_pc[1] = dc->jump_pc[1]; } else { tb->size = last_pc + 4 - pc_start; tb->icount = num_insns; @@ -5450,17 +5451,17 @@ void gen_intermediate_code_init(CPUSPARCState *env) void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos) { - target_ulong npc; - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + target_ulong pc, npc; + env->pc = pc = tcg_ctx.gen_opc_pc[pc_pos]; npc = gen_opc_npc[pc_pos]; - if (npc == 1) { + if (npc == DYNAMIC_PC) { /* dynamic NPC: already stored */ - } else if (npc == 2) { + } else if (npc & JUMP_PC) { /* jump PC: use 'cond' and the jump targets of the translation */ if (env->cond) { - env->npc = gen_opc_jump_pc[0]; + env->npc = npc & ~3; } else { - env->npc = gen_opc_jump_pc[1]; + env->npc = pc + 4; } } else { env->npc = npc; From a3d5ad761cafc669e25f4185e63d8d758a989135 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 31 Aug 2015 13:30:52 -0700 Subject: [PATCH 15/26] target-sparc: Add npc state to insn_start Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-sparc/cpu.h | 1 + target-sparc/translate.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 053edd5ed1..c68e4806bc 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -230,6 +230,7 @@ typedef struct trap_state { uint32_t tt; } trap_state; #endif +#define TARGET_INSN_START_EXTRA_WORDS 1 typedef struct sparc_def_t { const char *name; diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 25b5bc04a9..6e5b82d192 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -5257,7 +5257,12 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, tcg_ctx.gen_opc_icount[lj] = num_insns; } } - tcg_gen_insn_start(dc->pc); + if (dc->npc & JUMP_PC) { + assert(dc->jump_pc[1] == dc->pc + 4); + tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC); + } else { + tcg_gen_insn_start(dc->pc, dc->npc); + } num_insns++; if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { From fec88f64bda27846add83e924c8f4def9d94e068 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 27 Aug 2015 18:17:40 -0700 Subject: [PATCH 16/26] tcg: Merge cpu_gen_code into tb_gen_code As it's only caller, this tidies things a bit. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- include/exec/exec-all.h | 2 - translate-all.c | 131 ++++++++++++++++++---------------------- 2 files changed, 59 insertions(+), 74 deletions(-) diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index a3719b7f0d..5340745b0a 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -78,8 +78,6 @@ void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb, int pc_pos); 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); diff --git a/translate-all.c b/translate-all.c index 4a9ee33dac..19c2988e84 100644 --- a/translate-all.c +++ b/translate-all.c @@ -168,73 +168,7 @@ void cpu_gen_init(void) tcg_context_init(&tcg_ctx); } -/* return non zero if the very first instruction is invalid so that - * the virtual CPU can trigger an exception. - * - * '*gen_code_size_ptr' contains the size of the generated code (host - * code). - * - * Called with mmap_lock held for user-mode emulation. - */ -int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr) -{ - TCGContext *s = &tcg_ctx; - tcg_insn_unit *gen_code_buf; - int gen_code_size; -#ifdef CONFIG_PROFILER - int64_t ti; -#endif - -#ifdef CONFIG_PROFILER - s->tb_count1++; /* includes aborted translations because of - exceptions */ - ti = profile_getclock(); -#endif - tcg_func_start(s); - - gen_intermediate_code(env, tb); - - trace_translate_block(tb, tb->pc, tb->tc_ptr); - - /* generate machine code */ - gen_code_buf = tb->tc_ptr; - tb->tb_next_offset[0] = 0xffff; - tb->tb_next_offset[1] = 0xffff; - s->tb_next_offset = tb->tb_next_offset; -#ifdef USE_DIRECT_JUMP - s->tb_jmp_offset = tb->tb_jmp_offset; - s->tb_next = NULL; -#else - s->tb_jmp_offset = NULL; - s->tb_next = tb->tb_next; -#endif - -#ifdef CONFIG_PROFILER - s->tb_count++; - s->interm_time += profile_getclock() - ti; - s->code_time -= profile_getclock(); -#endif - gen_code_size = tcg_gen_code(s, gen_code_buf); - *gen_code_size_ptr = gen_code_size; -#ifdef CONFIG_PROFILER - s->code_time += profile_getclock(); - s->code_in_len += tb->size; - s->code_out_len += gen_code_size; -#endif - -#ifdef DEBUG_DISAS - if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) { - qemu_log("OUT: [size=%d]\n", gen_code_size); - log_disas(tb->tc_ptr, gen_code_size); - qemu_log("\n"); - qemu_log_flush(); - } -#endif - return 0; -} - -/* The cpu state corresponding to 'searched_pc' is restored. - */ +/* The cpu state corresponding to 'searched_pc' is restored. */ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, uintptr_t searched_pc) { @@ -1034,7 +968,11 @@ TranslationBlock *tb_gen_code(CPUState *cpu, TranslationBlock *tb; tb_page_addr_t phys_pc, phys_page2; target_ulong virt_page2; - int code_gen_size; + tcg_insn_unit *gen_code_buf; + int gen_code_size; +#ifdef CONFIG_PROFILER + int64_t ti; +#endif phys_pc = get_page_addr_code(env, pc); if (use_icount) { @@ -1049,13 +987,62 @@ TranslationBlock *tb_gen_code(CPUState *cpu, /* Don't forget to invalidate previous TB info. */ tcg_ctx.tb_ctx.tb_invalidated_flag = 1; } - tb->tc_ptr = tcg_ctx.code_gen_ptr; + + gen_code_buf = tcg_ctx.code_gen_ptr; + tb->tc_ptr = gen_code_buf; tb->cs_base = cs_base; tb->flags = flags; tb->cflags = cflags; - cpu_gen_code(env, tb, &code_gen_size); - tcg_ctx.code_gen_ptr = (void *)(((uintptr_t)tcg_ctx.code_gen_ptr + - code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); + +#ifdef CONFIG_PROFILER + tcg_ctx.tb_count1++; /* includes aborted translations because of + exceptions */ + ti = profile_getclock(); +#endif + + tcg_func_start(&tcg_ctx); + + gen_intermediate_code(env, tb); + + trace_translate_block(tb, tb->pc, tb->tc_ptr); + + /* generate machine code */ + tb->tb_next_offset[0] = 0xffff; + tb->tb_next_offset[1] = 0xffff; + tcg_ctx.tb_next_offset = tb->tb_next_offset; +#ifdef USE_DIRECT_JUMP + tcg_ctx.tb_jmp_offset = tb->tb_jmp_offset; + tcg_ctx.tb_next = NULL; +#else + tcg_ctx.tb_jmp_offset = NULL; + tcg_ctx.tb_next = tb->tb_next; +#endif + +#ifdef CONFIG_PROFILER + tcg_ctx.tb_count++; + tcg_ctx.interm_time += profile_getclock() - ti; + tcg_ctx.code_time -= profile_getclock(); +#endif + + gen_code_size = tcg_gen_code(&tcg_ctx, gen_code_buf); + +#ifdef CONFIG_PROFILER + tcg_ctx.code_time += profile_getclock(); + tcg_ctx.code_in_len += tb->size; + tcg_ctx.code_out_len += gen_code_size; +#endif + +#ifdef DEBUG_DISAS + if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) { + qemu_log("OUT: [size=%d]\n", gen_code_size); + log_disas(tb->tc_ptr, gen_code_size); + qemu_log("\n"); + qemu_log_flush(); + } +#endif + + tcg_ctx.code_gen_ptr = (void *)(((uintptr_t)gen_code_buf + + gen_code_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); /* check next page if needed */ virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; From dc03246cc377268db63abc8c5663ef571aec2eea Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 27 Aug 2015 18:18:09 -0700 Subject: [PATCH 17/26] target-*: Drop cpu_gen_code define This symbol no longer exists. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-alpha/cpu.h | 1 - target-arm/cpu.h | 1 - target-cris/cpu.h | 1 - target-i386/cpu.h | 1 - target-lm32/cpu.h | 1 - target-m68k/cpu.h | 1 - target-microblaze/cpu.h | 1 - target-mips/cpu.h | 1 - target-moxie/cpu.h | 1 - target-openrisc/cpu.h | 1 - target-ppc/cpu.h | 1 - target-s390x/cpu.h | 1 - target-sh4/cpu.h | 1 - target-sparc/cpu.h | 1 - target-tilegx/cpu.h | 1 - target-xtensa/cpu.h | 1 - 16 files changed, 16 deletions(-) diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 097637eb4e..bcd8076abb 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -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" diff --git a/target-arm/cpu.h b/target-arm/cpu.h index cebd46360e..493f9d02a9 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -1601,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 diff --git a/target-cris/cpu.h b/target-cris/cpu.h index d47fad466b..32204607ca 100644 --- a/target-cris/cpu.h +++ b/target-cris/cpu.h @@ -223,7 +223,6 @@ enum { #define cpu_init(cpu_model) CPU(cpu_cris_init(cpu_model)) #define cpu_exec cpu_cris_exec -#define cpu_gen_code cpu_cris_gen_code #define cpu_signal_handler cpu_cris_signal_handler /* MMU modes definitions */ diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 2b2a29d6a5..54d9d50140 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1189,7 +1189,6 @@ uint64_t cpu_get_tsc(CPUX86State *env); #define cpu_init(cpu_model) CPU(cpu_x86_init(cpu_model)) #define cpu_exec cpu_x86_exec -#define cpu_gen_code cpu_x86_gen_code #define cpu_signal_handler cpu_x86_signal_handler #define cpu_list x86_cpu_list #define cpudef_setup x86_cpudef_setup diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h index 3f874d5111..2b7620c7da 100644 --- a/target-lm32/cpu.h +++ b/target-lm32/cpu.h @@ -219,7 +219,6 @@ bool lm32_cpu_do_semihosting(CPUState *cs); #define cpu_list lm32_cpu_list #define cpu_exec cpu_lm32_exec -#define cpu_gen_code cpu_lm32_gen_code #define cpu_signal_handler cpu_lm32_signal_handler int lm32_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index d1957063b4..224c16967c 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -213,7 +213,6 @@ void register_m68k_insns (CPUM68KState *env); #define cpu_init(cpu_model) CPU(cpu_m68k_init(cpu_model)) #define cpu_exec cpu_m68k_exec -#define cpu_gen_code cpu_m68k_gen_code #define cpu_signal_handler cpu_m68k_signal_handler #define cpu_list m68k_cpu_list diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index b707c71367..6b212ab7f0 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -295,7 +295,6 @@ int cpu_mb_signal_handler(int host_signum, void *pinfo, #define cpu_init(cpu_model) CPU(cpu_mb_init(cpu_model)) #define cpu_exec cpu_mb_exec -#define cpu_gen_code cpu_mb_gen_code #define cpu_signal_handler cpu_mb_signal_handler /* MMU modes definitions */ diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 532b39ea1f..f32a0fd737 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -620,7 +620,6 @@ void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr, void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf); #define cpu_exec cpu_mips_exec -#define cpu_gen_code cpu_mips_gen_code #define cpu_signal_handler cpu_mips_signal_handler #define cpu_list mips_cpu_list diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h index 2bac15bf60..a612744011 100644 --- a/target-moxie/cpu.h +++ b/target-moxie/cpu.h @@ -122,7 +122,6 @@ int cpu_moxie_signal_handler(int host_signum, void *pinfo, #define cpu_init(cpu_model) CPU(cpu_moxie_init(cpu_model)) #define cpu_exec cpu_moxie_exec -#define cpu_gen_code cpu_moxie_gen_code #define cpu_signal_handler cpu_moxie_signal_handler static inline int cpu_mmu_index(CPUMoxieState *env, bool ifetch) diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index 1ff1c9ec2a..eb71607395 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -360,7 +360,6 @@ int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc); #define cpu_list cpu_openrisc_list #define cpu_exec cpu_openrisc_exec -#define cpu_gen_code cpu_openrisc_gen_code #define cpu_signal_handler cpu_openrisc_signal_handler #ifndef CONFIG_USER_ONLY diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index c6dbb38fea..98ce5a7ab0 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1241,7 +1241,6 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val); #define cpu_init(cpu_model) CPU(cpu_ppc_init(cpu_model)) #define cpu_exec cpu_ppc_exec -#define cpu_gen_code cpu_ppc_gen_code #define cpu_signal_handler cpu_ppc_signal_handler #define cpu_list ppc_cpu_list diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index b927c66404..da0adf649a 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -598,7 +598,6 @@ bool css_present(uint8_t cssid); #define cpu_init(model) CPU(cpu_s390x_init(model)) #define cpu_exec cpu_s390x_exec -#define cpu_gen_code cpu_s390x_gen_code #define cpu_signal_handler cpu_s390x_signal_handler void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf); diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 145e5df0d1..5b022c5973 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -226,7 +226,6 @@ void cpu_load_tlb(CPUSH4State * env); #define cpu_init(cpu_model) CPU(cpu_sh4_init(cpu_model)) #define cpu_exec cpu_sh4_exec -#define cpu_gen_code cpu_sh4_gen_code #define cpu_signal_handler cpu_sh4_signal_handler #define cpu_list sh4_cpu_list diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index c68e4806bc..9fa770b144 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -593,7 +593,6 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc); #endif #define cpu_exec cpu_sparc_exec -#define cpu_gen_code cpu_sparc_gen_code #define cpu_signal_handler cpu_sparc_signal_handler #define cpu_list sparc_cpu_list diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h index b9f5082b95..bcc1fdb962 100644 --- a/target-tilegx/cpu.h +++ b/target-tilegx/cpu.h @@ -163,7 +163,6 @@ TileGXCPU *cpu_tilegx_init(const char *cpu_model); #define cpu_init(cpu_model) CPU(cpu_tilegx_init(cpu_model)) #define cpu_exec cpu_tilegx_exec -#define cpu_gen_code cpu_tilegx_gen_code #define cpu_signal_handler cpu_tilegx_signal_handler static inline void cpu_get_tb_cpu_state(CPUTLGState *env, target_ulong *pc, diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h index 148a0f8d92..006bcb78b8 100644 --- a/target-xtensa/cpu.h +++ b/target-xtensa/cpu.h @@ -382,7 +382,6 @@ typedef struct CPUXtensaState { #include "cpu-qom.h" #define cpu_exec cpu_xtensa_exec -#define cpu_gen_code cpu_xtensa_gen_code #define cpu_signal_handler cpu_xtensa_signal_handler #define cpu_list xtensa_cpu_list From 190ce7fbc79fd0883a6170d7f30da59d366e6830 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 31 Aug 2015 14:34:41 -0700 Subject: [PATCH 18/26] tcg: Add TCG_MAX_INSNS Adjust all translators to respect it. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- target-alpha/translate.c | 3 +++ target-arm/translate-a64.c | 3 +++ target-arm/translate.c | 6 +++++- target-cris/translate.c | 3 +++ target-i386/translate.c | 6 +++++- target-lm32/translate.c | 3 +++ target-m68k/translate.c | 6 +++++- target-microblaze/translate.c | 6 +++++- target-mips/translate.c | 7 ++++++- target-moxie/translate.c | 13 +++++++++++-- target-openrisc/translate.c | 3 +++ target-ppc/translate.c | 6 +++++- target-s390x/translate.c | 3 +++ target-sh4/translate.c | 7 ++++++- target-sparc/translate.c | 7 ++++++- target-tilegx/translate.c | 3 +++ target-tricore/translate.c | 20 +++++++++++++------- target-unicore32/translate.c | 3 +++ target-xtensa/translate.c | 3 +++ tcg/tcg.h | 1 + 20 files changed, 95 insertions(+), 17 deletions(-) diff --git a/target-alpha/translate.c b/target-alpha/translate.c index c10193ea91..538e20293a 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -2903,6 +2903,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; diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 654a58645c..5022fc35c6 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -11072,6 +11072,9 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, if (max_insns == 0) { max_insns = CF_COUNT_MASK; } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); diff --git a/target-arm/translate.c b/target-arm/translate.c index fb69ecb03d..fedb7814bd 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -11258,8 +11258,12 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) + if (max_insns == 0) { max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); diff --git a/target-cris/translate.c b/target-cris/translate.c index 3d55a6ad68..d038bdbd19 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3155,6 +3155,9 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, if (max_insns == 0) { max_insns = CF_COUNT_MASK; } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); do { diff --git a/target-i386/translate.c b/target-i386/translate.c index 7501b919e3..d3282e89a6 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7932,8 +7932,12 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) + if (max_insns == 0) { max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); for(;;) { diff --git a/target-lm32/translate.c b/target-lm32/translate.c index 8ea7929ccb..e16c31a29c 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -1069,6 +1069,9 @@ void gen_intermediate_code_internal(LM32CPU *cpu, if (max_insns == 0) { max_insns = CF_COUNT_MASK; } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); do { diff --git a/target-m68k/translate.c b/target-m68k/translate.c index afef37f6f0..185c5650d9 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2991,8 +2991,12 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) + if (max_insns == 0) { max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); do { diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 1224456662..58b27ca652 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -1674,8 +1674,12 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) + if (max_insns == 0) { max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); do diff --git a/target-mips/translate.c b/target-mips/translate.c index 30d7d46c47..c0a06741de 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -19586,8 +19586,13 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, MO_UNALN : MO_ALIGN; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) + if (max_insns == 0) { max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } + LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags); gen_tb_start(tb); while (ctx.bstate == BS_NONE) { diff --git a/target-moxie/translate.c b/target-moxie/translate.c index d71f55bf38..68588da236 100644 --- a/target-moxie/translate.c +++ b/target-moxie/translate.c @@ -824,7 +824,7 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, target_ulong pc_start; int j, lj = -1; CPUMoxieState *env = &cpu->env; - int num_insns; + int num_insns, max_insns; pc_start = tb->pc; ctx.pc = pc_start; @@ -834,6 +834,13 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, ctx.singlestep_enabled = 0; ctx.bstate = BS_NONE; num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) { + max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); do { @@ -862,10 +869,12 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, ctx.opcode = cpu_lduw_code(env, ctx.pc); ctx.pc += decode_opc(cpu, &ctx); + if (num_insns >= max_insns) { + break; + } if (cs->singlestep_enabled) { break; } - if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) { break; } diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 9755850006..7573d346d4 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -1654,6 +1654,9 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, if (max_insns == 0) { max_insns = CF_COUNT_MASK; } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index fc234a32c8..2dc6fb463a 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -11475,8 +11475,12 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, #endif num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) + if (max_insns == 0) { max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); tcg_clear_temp_count(); diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 6bbc760596..b1aa139f88 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -5352,6 +5352,9 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu, if (max_insns == 0) { max_insns = CF_COUNT_MASK; } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); diff --git a/target-sh4/translate.c b/target-sh4/translate.c index efaa6f6a87..b48b9bbb5e 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1844,8 +1844,13 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, ii = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) + if (max_insns == 0) { max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } + gen_tb_start(tb); while (ctx.bstate == BS_NONE && !tcg_op_buf_full()) { if (search_pc) { diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 6e5b82d192..e6ecd2182f 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -5236,8 +5236,13 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) + if (max_insns == 0) { max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } + gen_tb_start(tb); do { if (spc) { diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index c23b761979..a6b9cd87ac 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -2081,6 +2081,9 @@ static inline void gen_intermediate_code_internal(TileGXCPU *cpu, if (cs->singlestep_enabled || singlestep) { max_insns = 1; } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } gen_tb_start(tb); while (1) { diff --git a/target-tricore/translate.c b/target-tricore/translate.c index fa10d5c23e..5345486dd9 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -8274,13 +8274,24 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb, CPUTriCoreState *env = &cpu->env; DisasContext ctx; target_ulong pc_start; - int num_insns; + int num_insns, max_insns; if (search_pc) { qemu_log("search pc %d\n", search_pc); } num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) { + max_insns = CF_COUNT_MASK; + } + if (singlestep) { + max_insns = 1; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } + pc_start = tb->pc; ctx.pc = pc_start; ctx.saved_pc = -1; @@ -8298,12 +8309,7 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb, ctx.opcode = cpu_ldl_code(env, ctx.pc); decode_opc(env, &ctx, 0); - if (tcg_op_buf_full()) { - gen_save_pc(ctx.next_pc); - tcg_gen_exit_tb(0); - break; - } - if (singlestep) { + if (num_insns >= max_insns || tcg_op_buf_full()) { gen_save_pc(ctx.next_pc); tcg_gen_exit_tb(0); break; diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index cd23c4b756..5e61e384fa 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -1900,6 +1900,9 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu, if (max_insns == 0) { max_insns = CF_COUNT_MASK; } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } #ifndef CONFIG_USER_ONLY if ((env->uncached_asr & ASR_M) == ASR_MODE_USER) { diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index ea87cb5794..4d4dc06af2 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -3014,6 +3014,9 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, if (max_insns == 0) { max_insns = CF_COUNT_MASK; } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } dc.config = env->config; dc.singlestep_enabled = cs->singlestep_enabled; diff --git a/tcg/tcg.h b/tcg/tcg.h index c975076b84..151e17d4ad 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -194,6 +194,7 @@ typedef struct TCGPool { #define TCG_POOL_CHUNK_SIZE 32768 #define TCG_MAX_TEMPS 512 +#define TCG_MAX_INSNS 512 /* when the size of the arguments of a called function is smaller than this value, they are statically allocated in the TB stack frame */ From bad729e272387de7dbfa3ec4319036552fc6c107 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 1 Sep 2015 15:51:12 -0700 Subject: [PATCH 19/26] tcg: Pass data argument to restore_state_to_opc The gen_opc_* arrays are already redundant with the data stored in the insn_start arguments. Transition restore_state_to_opc to use data from the latter. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- include/exec/exec-all.h | 2 +- target-alpha/translate.c | 5 +++-- target-arm/translate.c | 9 +++++---- target-cris/translate.c | 5 +++-- target-i386/translate.c | 26 ++++++-------------------- target-lm32/translate.c | 5 +++-- target-m68k/translate.c | 5 +++-- target-microblaze/translate.c | 5 +++-- target-mips/translate.c | 9 +++++---- target-moxie/translate.c | 5 +++-- target-openrisc/translate.c | 4 ++-- target-ppc/translate.c | 5 +++-- target-s390x/translate.c | 8 ++++---- target-sh4/translate.c | 7 ++++--- target-sparc/translate.c | 10 ++++++---- target-tilegx/translate.c | 5 +++-- target-tricore/translate.c | 5 +++-- target-unicore32/translate.c | 5 +++-- target-xtensa/translate.c | 5 +++-- tcg/tcg.c | 11 ++++++++++- tcg/tcg.h | 2 ++ translate-all.c | 2 +- 22 files changed, 79 insertions(+), 66 deletions(-) diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 5340745b0a..6a698026b5 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -75,7 +75,7 @@ typedef struct TranslationBlock TranslationBlock; 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); bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc); diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 538e20293a..8395a30a15 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -3023,7 +3023,8 @@ 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]; } diff --git a/target-arm/translate.c b/target-arm/translate.c index fedb7814bd..22969539fd 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -11612,13 +11612,14 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, } } -void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, + target_ulong *data) { if (is_a64(env)) { - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + env->pc = data[0]; env->condexec_bits = 0; } else { - env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos]; - env->condexec_bits = gen_opc_condexec_bits[pc_pos]; + env->regs[15] = data[0]; + env->condexec_bits = data[1]; } } diff --git a/target-cris/translate.c b/target-cris/translate.c index d038bdbd19..77e2794c03 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3433,7 +3433,8 @@ void cris_initialize_tcg(void) } } -void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, + target_ulong *data) { - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + env->pc = data[0]; } diff --git a/target-i386/translate.c b/target-i386/translate.c index d3282e89a6..2f7b77fd7c 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -8055,26 +8055,12 @@ void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb) gen_intermediate_code_internal(x86_env_get_cpu(env), tb, true); } -void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, + target_ulong *data) { - int cc_op; -#ifdef DEBUG_DISAS - if (qemu_loglevel_mask(CPU_LOG_TB_OP)) { - int i; - qemu_log("RESTORE:\n"); - for(i = 0;i <= pc_pos; i++) { - if (tcg_ctx.gen_opc_instr_start[i]) { - qemu_log("0x%04x: " TARGET_FMT_lx "\n", i, - tcg_ctx.gen_opc_pc[i]); - } - } - qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n", - pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base, - (uint32_t)tb->cs_base); - } -#endif - env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base; - cc_op = gen_opc_cc_op[pc_pos]; - if (cc_op != CC_OP_DYNAMIC) + int cc_op = data[1]; + env->eip = data[0] - tb->cs_base; + if (cc_op != CC_OP_DYNAMIC) { env->cc_op = cc_op; + } } diff --git a/target-lm32/translate.c b/target-lm32/translate.c index e16c31a29c..3379d2c5fb 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -1207,9 +1207,10 @@ void lm32_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf(f, "\n\n"); } -void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb, + target_ulong *data) { - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + env->pc = data[0]; } void lm32_translate_init(void) diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 185c5650d9..ce8150e8e7 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -3118,7 +3118,8 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result); } -void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb, + target_ulong *data) { - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + env->pc = data[0]; } diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 58b27ca652..973c74461f 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -1928,7 +1928,8 @@ void mb_tcg_init(void) } } -void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, + target_ulong *data) { - env->sregs[SR_PC] = tcg_ctx.gen_opc_pc[pc_pos]; + env->sregs[SR_PC] = data[0]; } diff --git a/target-mips/translate.c b/target-mips/translate.c index c0a06741de..56f00e6e88 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -20061,18 +20061,19 @@ void cpu_state_reset(CPUMIPSState *env) } } -void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, + target_ulong *data) { - env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos]; + env->active_tc.PC = data[0]; env->hflags &= ~MIPS_HFLAG_BMASK; - env->hflags |= gen_opc_hflags[pc_pos]; + env->hflags |= data[1]; switch (env->hflags & MIPS_HFLAG_BMASK_BASE) { case MIPS_HFLAG_BR: break; case MIPS_HFLAG_BC: case MIPS_HFLAG_BL: case MIPS_HFLAG_B: - env->btarget = gen_opc_btarget[pc_pos]; + env->btarget = data[2]; break; } } diff --git a/target-moxie/translate.c b/target-moxie/translate.c index 68588da236..c007764f3e 100644 --- a/target-moxie/translate.c +++ b/target-moxie/translate.c @@ -922,7 +922,8 @@ void gen_intermediate_code_pc(CPUMoxieState *env, struct TranslationBlock *tb) gen_intermediate_code_internal(moxie_env_get_cpu(env), tb, true); } -void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb, + target_ulong *data) { - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + env->pc = data[0]; } diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 7573d346d4..26bf87f5fd 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -1794,7 +1794,7 @@ void openrisc_cpu_dump_state(CPUState *cs, FILE *f, } void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb, - int pc_pos) + target_ulong *data) { - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + env->pc = data[0]; } diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 2dc6fb463a..5c2dc38d35 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -11629,7 +11629,8 @@ void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb) gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, true); } -void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, + target_ulong *data) { - env->nip = tcg_ctx.gen_opc_pc[pc_pos]; + env->nip = data[0]; } diff --git a/target-s390x/translate.c b/target-s390x/translate.c index b1aa139f88..104265db5f 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -5460,11 +5460,11 @@ void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb) gen_intermediate_code_internal(s390_env_get_cpu(env), tb, true); } -void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, + target_ulong *data) { - int cc_op; - env->psw.addr = tcg_ctx.gen_opc_pc[pc_pos]; - cc_op = gen_opc_cc_op[pc_pos]; + int cc_op = data[1]; + env->psw.addr = data[0]; if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) { env->cc_op = cc_op; } diff --git a/target-sh4/translate.c b/target-sh4/translate.c index b48b9bbb5e..d3fe1de94a 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1950,8 +1950,9 @@ void gen_intermediate_code_pc(CPUSH4State * env, struct TranslationBlock *tb) gen_intermediate_code_internal(sh_env_get_cpu(env), tb, true); } -void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, + target_ulong *data) { - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; - env->flags = gen_opc_hflags[pc_pos]; + env->pc = data[0]; + env->flags = data[1]; } diff --git a/target-sparc/translate.c b/target-sparc/translate.c index e6ecd2182f..18344c82ed 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -5459,11 +5459,13 @@ void gen_intermediate_code_init(CPUSPARCState *env) } } -void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, + target_ulong *data) { - target_ulong pc, npc; - env->pc = pc = tcg_ctx.gen_opc_pc[pc_pos]; - npc = gen_opc_npc[pc_pos]; + target_ulong pc = data[0]; + target_ulong npc = data[1]; + + env->pc = pc; if (npc == DYNAMIC_PC) { /* dynamic NPC: already stored */ } else if (npc & JUMP_PC) { diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index a6b9cd87ac..eae5622a9a 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -2144,9 +2144,10 @@ void gen_intermediate_code_pc(CPUTLGState *env, struct TranslationBlock *tb) gen_intermediate_code_internal(tilegx_env_get_cpu(env), tb, true); } -void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb, + target_ulong *data) { - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + env->pc = data[0]; } void tilegx_tcg_init(void) diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 5345486dd9..6f5438fe1e 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -8350,9 +8350,10 @@ gen_intermediate_code_pc(CPUTriCoreState *env, struct TranslationBlock *tb) } void -restore_state_to_opc(CPUTriCoreState *env, TranslationBlock *tb, int pc_pos) +restore_state_to_opc(CPUTriCoreState *env, TranslationBlock *tb, + target_ulong *data) { - env->PC = tcg_ctx.gen_opc_pc[pc_pos]; + env->PC = data[0]; } /* * diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 5e61e384fa..9d8167a35c 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -2129,7 +2129,8 @@ void uc32_cpu_dump_state(CPUState *cs, FILE *f, cpu_dump_state_ucf64(env, f, cpu_fprintf, flags); } -void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb, + target_ulong *data) { - env->regs[31] = tcg_ctx.gen_opc_pc[pc_pos]; + env->regs[31] = data[0]; } diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 4d4dc06af2..ac967e136c 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -3202,7 +3202,8 @@ void xtensa_cpu_dump_state(CPUState *cs, FILE *f, } } -void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos) +void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, + target_ulong *data) { - env->pc = tcg_ctx.gen_opc_pc[pc_pos]; + env->pc = data[0]; } diff --git a/tcg/tcg.c b/tcg/tcg.c index 3308d6822e..bdb83d91d3 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2294,7 +2294,7 @@ static inline int tcg_gen_code_common(TCGContext *s, tcg_insn_unit *gen_code_buf, long search_pc) { - int oi, oi_next; + int i, oi, oi_next; #ifdef DEBUG_DISAS if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { @@ -2361,6 +2361,15 @@ static inline int tcg_gen_code_common(TCGContext *s, tcg_reg_alloc_movi(s, args, dead_args, sync_args); break; case INDEX_op_insn_start: + for (i = 0; i < TARGET_INSN_START_WORDS; ++i) { + target_ulong a; +#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS + a = ((target_ulong)args[i * 2 + 1] << 32) | args[i * 2]; +#else + a = args[i]; +#endif + s->gen_opc_data[i] = a; + } break; case INDEX_op_discard: temp_dead(s, args[0]); diff --git a/tcg/tcg.h b/tcg/tcg.h index 151e17d4ad..8fd12528cb 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -580,6 +580,8 @@ struct TCGContext { target_ulong gen_opc_pc[OPC_BUF_SIZE]; uint16_t gen_opc_icount[OPC_BUF_SIZE]; uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; + + target_ulong gen_opc_data[TARGET_INSN_START_WORDS]; }; extern TCGContext tcg_ctx; diff --git a/translate-all.c b/translate-all.c index 19c2988e84..9f801ae758 100644 --- a/translate-all.c +++ b/translate-all.c @@ -218,7 +218,7 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, } cpu->icount_decr.u16.low -= s->gen_opc_icount[j]; - restore_state_to_opc(env, tb, j); + restore_state_to_opc(env, tb, s->gen_opc_data); #ifdef CONFIG_PROFILER s->restore_time += profile_getclock() - ti; From fca8a500d519a56abeaedf8073167a61d3c6b9c4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 1 Sep 2015 19:11:45 -0700 Subject: [PATCH 20/26] tcg: Save insn data and use it in cpu_restore_state_from_tb We can now restore state without retranslation. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- include/exec/exec-all.h | 1 + tcg/tcg.c | 40 +++++++---- tcg/tcg.h | 4 +- translate-all.c | 150 +++++++++++++++++++++++++++++----------- 4 files changed, 140 insertions(+), 55 deletions(-) diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 6a698026b5..402dd87543 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -199,6 +199,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 */ diff --git a/tcg/tcg.c b/tcg/tcg.c index bdb83d91d3..40f24de1ad 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2294,7 +2294,7 @@ static inline int tcg_gen_code_common(TCGContext *s, tcg_insn_unit *gen_code_buf, long search_pc) { - int i, oi, oi_next; + int i, oi, oi_next, num_insns; #ifdef DEBUG_DISAS if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { @@ -2338,6 +2338,7 @@ static inline int tcg_gen_code_common(TCGContext *s, tcg_out_tb_init(s); + num_insns = -1; for (oi = s->gen_first_op_idx; oi >= 0; oi = oi_next) { TCGOp * const op = &s->gen_op_buf[oi]; TCGArg * const args = &s->gen_opparam_buf[op->args]; @@ -2361,6 +2362,10 @@ static inline int tcg_gen_code_common(TCGContext *s, tcg_reg_alloc_movi(s, args, dead_args, sync_args); break; case INDEX_op_insn_start: + if (num_insns >= 0) { + s->gen_insn_end_off[num_insns] = tcg_current_code_size(s); + } + num_insns++; for (i = 0; i < TARGET_INSN_START_WORDS; ++i) { target_ulong a; #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS @@ -2368,7 +2373,7 @@ static inline int tcg_gen_code_common(TCGContext *s, #else a = args[i]; #endif - s->gen_opc_data[i] = a; + s->gen_insn_data[num_insns][i] = a; } break; case INDEX_op_discard: @@ -2400,6 +2405,8 @@ static inline int tcg_gen_code_common(TCGContext *s, check_regs(s); #endif } + tcg_debug_assert(num_insns >= 0); + s->gen_insn_end_off[num_insns] = tcg_current_code_size(s); /* Generate TB finalization at the end of block */ tcg_out_tb_finalize(s); @@ -2448,24 +2455,26 @@ int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf, void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf) { TCGContext *s = &tcg_ctx; - int64_t tot; + int64_t tb_count = s->tb_count; + int64_t tb_div_count = tb_count ? tb_count : 1; + int64_t tot = s->interm_time + s->code_time; - tot = s->interm_time + s->code_time; cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n", tot, tot / 2.4e9); cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n", - s->tb_count, - s->tb_count1 - s->tb_count, - s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0); + tb_count, s->tb_count1 - tb_count, + (double)(s->tb_count1 - s->tb_count) + / (s->tb_count1 ? s->tb_count1 : 1) * 100.0); cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n", - s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max); + (double)s->op_count / tb_div_count, s->op_count_max); cpu_fprintf(f, "deleted ops/TB %0.2f\n", - s->tb_count ? - (double)s->del_op_count / s->tb_count : 0); + (double)s->del_op_count / tb_div_count); cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n", - s->tb_count ? - (double)s->temp_count / s->tb_count : 0, - s->temp_count_max); + (double)s->temp_count / tb_div_count, s->temp_count_max); + cpu_fprintf(f, "avg host code/TB %0.1f\n", + (double)s->code_out_len / tb_div_count); + cpu_fprintf(f, "avg search data/TB %0.1f\n", + (double)s->search_out_len / tb_div_count); cpu_fprintf(f, "cycles/op %0.1f\n", s->op_count ? (double)tot / s->op_count : 0); @@ -2473,8 +2482,11 @@ void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf) s->code_in_len ? (double)tot / s->code_in_len : 0); cpu_fprintf(f, "cycles/out byte %0.1f\n", s->code_out_len ? (double)tot / s->code_out_len : 0); - if (tot == 0) + cpu_fprintf(f, "cycles/search byte %0.1f\n", + s->search_out_len ? (double)tot / s->search_out_len : 0); + if (tot == 0) { tot = 1; + } cpu_fprintf(f, " gen_interm time %0.1f%%\n", (double)s->interm_time / tot * 100.0); cpu_fprintf(f, " gen_code time %0.1f%%\n", diff --git a/tcg/tcg.h b/tcg/tcg.h index 8fd12528cb..df499c6fa9 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -532,6 +532,7 @@ struct TCGContext { int64_t del_op_count; int64_t code_in_len; int64_t code_out_len; + int64_t search_out_len; int64_t interm_time; int64_t code_time; int64_t la_time; @@ -581,7 +582,8 @@ struct TCGContext { uint16_t gen_opc_icount[OPC_BUF_SIZE]; uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; - target_ulong gen_opc_data[TARGET_INSN_START_WORDS]; + uint16_t gen_insn_end_off[TCG_MAX_INSNS]; + target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS]; }; extern TCGContext tcg_ctx; diff --git a/translate-all.c b/translate-all.c index 9f801ae758..3454f4ed45 100644 --- a/translate-all.c +++ b/translate-all.c @@ -168,61 +168,128 @@ void cpu_gen_init(void) tcg_context_init(&tcg_ctx); } +/* Encode VAL as a signed leb128 sequence at P. + Return P incremented past the encoded value. */ +static uint8_t *encode_sleb128(uint8_t *p, target_long val) +{ + int more, byte; + + do { + byte = val & 0x7f; + val >>= 7; + more = !((val == 0 && (byte & 0x40) == 0) + || (val == -1 && (byte & 0x40) != 0)); + if (more) { + byte |= 0x80; + } + *p++ = byte; + } while (more); + + return p; +} + +/* Decode a signed leb128 sequence at *PP; increment *PP past the + decoded value. Return the decoded value. */ +static target_long decode_sleb128(uint8_t **pp) +{ + uint8_t *p = *pp; + target_long val = 0; + int byte, shift = 0; + + do { + byte = *p++; + val |= (target_ulong)(byte & 0x7f) << shift; + shift += 7; + } while (byte & 0x80); + if (shift < TARGET_LONG_BITS && (byte & 0x40)) { + val |= -(target_ulong)1 << shift; + } + + *pp = p; + return val; +} + +/* Encode the data collected about the instructions while compiling TB. + Place the data at BLOCK, and return the number of bytes consumed. + + The logical table consisits of TARGET_INSN_START_WORDS target_ulong's, + which come from the target's insn_start data, followed by a uintptr_t + which comes from the host pc of the end of the code implementing the insn. + + Each line of the table is encoded as sleb128 deltas from the previous + line. The seed for the first line is { tb->pc, 0..., tb->tc_ptr }. + That is, the first column is seeded with the guest pc, the last column + with the host pc, and the middle columns with zeros. */ + +static int encode_search(TranslationBlock *tb, uint8_t *block) +{ + uint8_t *p = block; + int i, j, n; + + tb->tc_search = block; + + for (i = 0, n = tb->icount; i < n; ++i) { + target_ulong prev; + + for (j = 0; j < TARGET_INSN_START_WORDS; ++j) { + if (i == 0) { + prev = (j == 0 ? tb->pc : 0); + } else { + prev = tcg_ctx.gen_insn_data[i - 1][j]; + } + p = encode_sleb128(p, tcg_ctx.gen_insn_data[i][j] - prev); + } + prev = (i == 0 ? 0 : tcg_ctx.gen_insn_end_off[i - 1]); + p = encode_sleb128(p, tcg_ctx.gen_insn_end_off[i] - prev); + } + + return p - block; +} + /* The cpu state corresponding to 'searched_pc' is restored. */ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, uintptr_t searched_pc) { + target_ulong data[TARGET_INSN_START_WORDS] = { tb->pc }; + uintptr_t host_pc = (uintptr_t)tb->tc_ptr; CPUArchState *env = cpu->env_ptr; - TCGContext *s = &tcg_ctx; - int j; - uintptr_t tc_ptr; + uint8_t *p = tb->tc_search; + int i, j, num_insns = tb->icount; #ifdef CONFIG_PROFILER - int64_t ti; + int64_t ti = profile_getclock(); #endif -#ifdef CONFIG_PROFILER - ti = profile_getclock(); -#endif - tcg_func_start(s); + if (searched_pc < host_pc) { + return -1; + } - gen_intermediate_code_pc(env, tb); + /* Reconstruct the stored insn data while looking for the point at + which the end of the insn exceeds the searched_pc. */ + for (i = 0; i < num_insns; ++i) { + for (j = 0; j < TARGET_INSN_START_WORDS; ++j) { + data[j] += decode_sleb128(&p); + } + host_pc += decode_sleb128(&p); + if (host_pc > searched_pc) { + goto found; + } + } + return -1; + found: if (tb->cflags & CF_USE_ICOUNT) { assert(use_icount); /* Reset the cycle counter to the start of the block. */ - cpu->icount_decr.u16.low += tb->icount; + cpu->icount_decr.u16.low += num_insns; /* Clear the IO flag. */ cpu->can_do_io = 0; } - - /* find opc index corresponding to search_pc */ - tc_ptr = (uintptr_t)tb->tc_ptr; - if (searched_pc < tc_ptr) - return -1; - - s->tb_next_offset = tb->tb_next_offset; -#ifdef USE_DIRECT_JUMP - s->tb_jmp_offset = tb->tb_jmp_offset; - s->tb_next = NULL; -#else - s->tb_jmp_offset = NULL; - s->tb_next = tb->tb_next; -#endif - j = tcg_gen_code_search_pc(s, (tcg_insn_unit *)tc_ptr, - searched_pc - tc_ptr); - if (j < 0) - return -1; - /* now find start of instruction before */ - while (s->gen_opc_instr_start[j] == 0) { - j--; - } - cpu->icount_decr.u16.low -= s->gen_opc_icount[j]; - - restore_state_to_opc(env, tb, s->gen_opc_data); + cpu->icount_decr.u16.low -= i; + restore_state_to_opc(env, tb, data); #ifdef CONFIG_PROFILER - s->restore_time += profile_getclock() - ti; - s->restore_count++; + tcg_ctx.restore_time += profile_getclock() - ti; + tcg_ctx.restore_count++; #endif return 0; } @@ -969,7 +1036,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb_page_addr_t phys_pc, phys_page2; target_ulong virt_page2; tcg_insn_unit *gen_code_buf; - int gen_code_size; + int gen_code_size, search_size; #ifdef CONFIG_PROFILER int64_t ti; #endif @@ -1025,11 +1092,13 @@ TranslationBlock *tb_gen_code(CPUState *cpu, #endif gen_code_size = tcg_gen_code(&tcg_ctx, gen_code_buf); + search_size = encode_search(tb, (void *)gen_code_buf + gen_code_size); #ifdef CONFIG_PROFILER tcg_ctx.code_time += profile_getclock(); tcg_ctx.code_in_len += tb->size; tcg_ctx.code_out_len += gen_code_size; + tcg_ctx.search_out_len += search_size; #endif #ifdef DEBUG_DISAS @@ -1041,8 +1110,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu, } #endif - tcg_ctx.code_gen_ptr = (void *)(((uintptr_t)gen_code_buf + - gen_code_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1)); + tcg_ctx.code_gen_ptr = (void *) + ROUND_UP((uintptr_t)gen_code_buf + gen_code_size + search_size, + CODE_GEN_ALIGN); /* check next page if needed */ virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; From 4e5e1215156662b2b153255c49d4640d82c5568b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 1 Sep 2015 20:01:40 -0700 Subject: [PATCH 21/26] tcg: Remove gen_intermediate_code_pc It is no longer used, so tidy up everything reached by it. This includes the gen_opc_* arrays, the search_pc parameter and the inline gen_intermediate_code_internal functions. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- include/exec/exec-all.h | 1 - target-alpha/translate.c | 41 +++----------------------- target-arm/translate-a64.c | 30 ++----------------- target-arm/translate.c | 54 ++++++----------------------------- target-arm/translate.h | 8 ++---- target-cris/translate.c | 50 ++++---------------------------- target-i386/translate.c | 49 ++++--------------------------- target-lm32/translate.c | 42 +++------------------------ target-m68k/translate.c | 43 +++------------------------- target-microblaze/translate.c | 40 +++----------------------- target-mips/translate.c | 48 ++++--------------------------- target-moxie/translate.c | 41 +++----------------------- target-openrisc/translate.c | 42 +++------------------------ target-ppc/translate.c | 40 ++++---------------------- target-s390x/translate.c | 44 +++------------------------- target-sh4/translate.c | 43 +++------------------------- target-sparc/translate.c | 51 ++++----------------------------- target-tilegx/translate.c | 41 +++----------------------- target-tricore/translate.c | 31 ++++---------------- target-unicore32/translate.c | 44 ++++------------------------ target-xtensa/translate.c | 39 +++---------------------- tcg/tcg.h | 4 --- 22 files changed, 90 insertions(+), 736 deletions(-) diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 402dd87543..6871e782b3 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -73,7 +73,6 @@ typedef struct TranslationBlock TranslationBlock; #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, target_ulong *data); diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 8395a30a15..f936d1b5b9 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -2858,17 +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; - int j, lj = -1; ExitStatus ret; int num_insns; int max_insns; @@ -2915,18 +2912,6 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu, gen_tb_start(tb); do { - 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; - } tcg_gen_insn_start(ctx.pc); num_insns++; @@ -2993,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; - } + tb->size = ctx.pc - pc_start; + tb->icount = num_insns; #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { @@ -3013,16 +2990,6 @@ 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, target_ulong *data) { diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 5022fc35c6..e65e309535 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -11000,14 +11000,11 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s) free_tmp_a64(s); } -void gen_intermediate_code_internal_a64(ARMCPU *cpu, - TranslationBlock *tb, - bool search_pc) +void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb) { CPUState *cs = CPU(cpu); CPUARMState *env = &cpu->env; DisasContext dc1, *dc = &dc1; - int j, lj; target_ulong pc_start; target_ulong next_page_start; int num_insns; @@ -11066,7 +11063,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, init_tmp_a64_array(dc); next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { @@ -11081,18 +11077,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, tcg_clear_temp_count(); do { - 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] = dc->pc; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(dc->pc, 0); num_insns++; @@ -11221,14 +11205,6 @@ done_generating: qemu_log("\n"); } #endif - if (search_pc) { - j = tcg_op_buf_count(); - lj++; - while (lj <= j) { - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } - } else { - tb->size = dc->pc - pc_start; - tb->icount = num_insns; - } + tb->size = dc->pc - pc_start; + tb->icount = num_insns; } diff --git a/target-arm/translate.c b/target-arm/translate.c index 22969539fd..22c35877e5 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -52,7 +52,6 @@ #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0) #include "translate.h" -static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE]; #if defined(CONFIG_USER_ONLY) #define IS_USER(s) 1 @@ -11168,16 +11167,12 @@ undef: } /* generate intermediate code in gen_opc_buf and gen_opparam_buf for - basic block 'tb'. If search_pc is TRUE, also generate PC - information for each intermediate instruction. */ -static inline void gen_intermediate_code_internal(ARMCPU *cpu, - TranslationBlock *tb, - bool search_pc) + basic block 'tb'. */ +void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) { + ARMCPU *cpu = arm_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUARMState *env = &cpu->env; DisasContext dc1, *dc = &dc1; - int j, lj; target_ulong pc_start; target_ulong next_page_start; int num_insns; @@ -11189,7 +11184,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, * the A32/T32 complexity to do with conditional execution/IT blocks/etc. */ if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) { - gen_intermediate_code_internal_a64(cpu, tb, search_pc); + gen_intermediate_code_a64(cpu, tb); return; } @@ -11255,7 +11250,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, /* 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; - lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { @@ -11289,10 +11283,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, * (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 will be called again with search_pc=1 - * and generate a mapping of the condexec bits for each PC in - * gen_opc_condexec_bits[]. restore_state_to_opc() then uses - * this to restore the condexec bits. + * 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 @@ -11309,18 +11302,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, store_cpu_field(tmp, condexec_bits); } do { - 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] = dc->pc; - gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1); - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(dc->pc, (dc->condexec_cond << 4) | (dc->condexec_mask >> 1)); num_insns++; @@ -11537,25 +11518,8 @@ done_generating: qemu_log("\n"); } #endif - if (search_pc) { - j = tcg_op_buf_count(); - lj++; - while (lj <= j) - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } else { - tb->size = dc->pc - pc_start; - tb->icount = num_insns; - } -} - -void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true); + tb->size = dc->pc - pc_start; + tb->icount = num_insns; } static const char *cpu_mode_names[16] = { diff --git a/target-arm/translate.h b/target-arm/translate.h index b8fe37a0a7..53ef971058 100644 --- a/target-arm/translate.h +++ b/target-arm/translate.h @@ -122,9 +122,7 @@ static inline int default_exception_el(DisasContext *s) #ifdef TARGET_AARCH64 void a64_translate_init(void); -void gen_intermediate_code_internal_a64(ARMCPU *cpu, - TranslationBlock *tb, - bool search_pc); +void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb); void gen_a64_set_pc_im(uint64_t val); void aarch64_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags); @@ -133,9 +131,7 @@ static inline void a64_translate_init(void) { } -static inline void gen_intermediate_code_internal_a64(ARMCPU *cpu, - TranslationBlock *tb, - bool search_pc) +static inline void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb) { } diff --git a/target-cris/translate.c b/target-cris/translate.c index 77e2794c03..964845c461 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3067,15 +3067,12 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc) */ /* generate intermediate code for basic block 'tb'. */ -static inline void -gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, - bool search_pc) +void gen_intermediate_code(CPUCRISState *env, struct TranslationBlock *tb) { + CRISCPU *cpu = cris_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUCRISState *env = &cpu->env; uint32_t pc_start; unsigned int insn_len; - int j, lj; struct DisasContext ctx; struct DisasContext *dc = &ctx; uint32_t next_page_start; @@ -3127,13 +3124,13 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { qemu_log( - "srch=%d pc=%x %x flg=%" PRIx64 " bt=%x ds=%u ccs=%x\n" + "pc=%x %x flg=%" PRIx64 " bt=%x ds=%u ccs=%x\n" "pid=%x usp=%x\n" "%x.%x.%x.%x\n" "%x.%x.%x.%x\n" "%x.%x.%x.%x\n" "%x.%x.%x.%x\n", - search_pc, dc->pc, dc->ppc, + dc->pc, dc->ppc, (uint64_t)tb->flags, env->btarget, (unsigned)tb->flags & 7, env->pregs[PR_CCS], @@ -3149,7 +3146,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, } next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { @@ -3161,22 +3157,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, gen_tb_start(tb); do { - if (search_pc) { - j = tcg_op_buf_count(); - if (lj < j) { - lj++; - while (lj < j) { - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } - } - if (dc->delayed_branch == 1) { - tcg_ctx.gen_opc_pc[lj] = dc->ppc | 1; - } else { - tcg_ctx.gen_opc_pc[lj] = dc->pc; - } - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(dc->delayed_branch == 1 ? dc->ppc | 1 : dc->pc); num_insns++; @@ -3308,16 +3288,8 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, } 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 = dc->pc - pc_start; - tb->icount = num_insns; - } + tb->size = dc->pc - pc_start; + tb->icount = num_insns; #ifdef DEBUG_DISAS #if !DISAS_CRIS @@ -3331,16 +3303,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, #endif } -void gen_intermediate_code (CPUCRISState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(cris_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc (CPUCRISState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(cris_env_get_cpu(env), tb, true); -} - void cris_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags) { diff --git a/target-i386/translate.c b/target-i386/translate.c index 2f7b77fd7c..ef10e685cc 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -75,8 +75,6 @@ static TCGv_ptr cpu_ptr0, cpu_ptr1; static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32; static TCGv_i64 cpu_tmp1_i64; -static uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; - #include "exec/gen-icount.h" #ifdef TARGET_X86_64 @@ -7839,17 +7837,13 @@ void optimize_flags_init(void) } /* generate intermediate code in gen_opc_buf and gen_opparam_buf for - basic block 'tb'. If search_pc is TRUE, also generate PC - information for each intermediate instruction. */ -static inline void gen_intermediate_code_internal(X86CPU *cpu, - TranslationBlock *tb, - bool search_pc) + basic block 'tb'. */ +void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) { + X86CPU *cpu = x86_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUX86State *env = &cpu->env; DisasContext dc1, *dc = &dc1; target_ulong pc_ptr; - int j, lj; uint64_t flags; target_ulong pc_start; target_ulong cs_base; @@ -7929,7 +7923,6 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, dc->is_jmp = DISAS_NEXT; pc_ptr = pc_start; - lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { @@ -7941,18 +7934,6 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, gen_tb_start(tb); for(;;) { - 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] = pc_ptr; - gen_opc_cc_op[lj] = dc->cc_op; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(pc_ptr, dc->cc_op); num_insns++; @@ -8015,14 +7996,6 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, done_generating: gen_tb_end(tb, num_insns); - /* we don't forget to fill the last values */ - if (search_pc) { - j = tcg_op_buf_count(); - lj++; - while (lj <= j) - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } - #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { int disas_flags; @@ -8039,20 +8012,8 @@ done_generating: } #endif - if (!search_pc) { - tb->size = pc_ptr - pc_start; - tb->icount = num_insns; - } -} - -void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(x86_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(x86_env_get_cpu(env), tb, true); + tb->size = pc_ptr - pc_start; + tb->icount = num_insns; } void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, diff --git a/target-lm32/translate.c b/target-lm32/translate.c index 3379d2c5fb..c61ad0f9ab 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -1033,15 +1033,12 @@ static inline void decode(DisasContext *dc, uint32_t ir) } /* generate intermediate code for basic block 'tb'. */ -static inline -void gen_intermediate_code_internal(LM32CPU *cpu, - TranslationBlock *tb, bool search_pc) +void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb) { + LM32CPU *cpu = lm32_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPULM32State *env = &cpu->env; struct DisasContext ctx, *dc = &ctx; uint32_t pc_start; - int j, lj; uint32_t next_page_start; int num_insns; int max_insns; @@ -1063,7 +1060,6 @@ void gen_intermediate_code_internal(LM32CPU *cpu, } next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { @@ -1075,18 +1071,6 @@ void gen_intermediate_code_internal(LM32CPU *cpu, gen_tb_start(tb); do { - 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] = dc->pc; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(dc->pc); num_insns++; @@ -1142,16 +1126,8 @@ void gen_intermediate_code_internal(LM32CPU *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 = dc->pc - pc_start; - tb->icount = num_insns; - } + tb->size = dc->pc - pc_start; + tb->icount = num_insns; #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { @@ -1163,16 +1139,6 @@ void gen_intermediate_code_internal(LM32CPU *cpu, #endif } -void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(lm32_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPULM32State *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(lm32_env_get_cpu(env), tb, true); -} - void lm32_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags) { diff --git a/target-m68k/translate.c b/target-m68k/translate.c index ce8150e8e7..5995ccea92 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2962,14 +2962,11 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) } /* generate intermediate code for basic block 'tb'. */ -static inline void -gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, - bool search_pc) +void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb) { + M68kCPU *cpu = m68k_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUM68KState *env = &cpu->env; DisasContext dc1, *dc = &dc1; - int j, lj; target_ulong pc_start; int pc_offset; int num_insns; @@ -2988,7 +2985,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, dc->fpcr = env->fpcr; dc->user = (env->sr & SR_S) == 0; dc->done_mac = 0; - lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { @@ -3002,17 +2998,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, do { pc_offset = dc->pc - pc_start; gen_throws_exception = NULL; - 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] = dc->pc; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(dc->pc); num_insns++; @@ -3071,28 +3056,8 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, qemu_log("\n"); } #endif - if (search_pc) { - j = tcg_op_buf_count(); - lj++; - while (lj <= j) - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } else { - tb->size = dc->pc - pc_start; - tb->icount = num_insns; - } - - //optimize_flags(); - //expand_target_qops(); -} - -void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(m68k_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUM68KState *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(m68k_env_get_cpu(env), tb, true); + tb->size = dc->pc - pc_start; + tb->icount = num_insns; } void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 973c74461f..a9c501099c 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -1627,14 +1627,11 @@ static inline void decode(DisasContext *dc, uint32_t ir) } /* generate intermediate code for basic block 'tb'. */ -static inline void -gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, - bool search_pc) +void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb) { + MicroBlazeCPU *cpu = mb_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUMBState *env = &cpu->env; uint32_t pc_start; - int j, lj; struct DisasContext ctx; struct DisasContext *dc = &ctx; uint32_t next_page_start, org_flags; @@ -1671,7 +1668,6 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, } next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { @@ -1684,17 +1680,6 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, gen_tb_start(tb); do { - 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] = dc->pc; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(dc->pc); num_insns++; @@ -1813,15 +1798,8 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, } 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 = dc->pc - pc_start; - tb->icount = num_insns; - } + tb->size = dc->pc - pc_start; + tb->icount = num_insns; #ifdef DEBUG_DISAS #if !SIM_COMPAT @@ -1838,16 +1816,6 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, assert(!dc->abort_at_next_insn); } -void gen_intermediate_code (CPUMBState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(mb_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc (CPUMBState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(mb_env_get_cpu(env), tb, true); -} - void mb_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags) { diff --git a/target-mips/translate.c b/target-mips/translate.c index 56f00e6e88..897839ced9 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1359,9 +1359,6 @@ static TCGv_i32 fpu_fcr0, fpu_fcr31; static TCGv_i64 fpu_f64[32]; static TCGv_i64 msa_wr_d[64]; -static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; -static target_ulong gen_opc_btarget[OPC_BUF_SIZE]; - #include "exec/gen-icount.h" #define gen_helper_0e0i(name, arg) do { \ @@ -19535,24 +19532,18 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) } } -static inline void -gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, - bool search_pc) +void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb) { + MIPSCPU *cpu = mips_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUMIPSState *env = &cpu->env; DisasContext ctx; target_ulong pc_start; target_ulong next_page_start; - int j, lj = -1; int num_insns; int max_insns; int insn_bytes; int is_slot; - if (search_pc) - qemu_log("search pc %d\n", search_pc); - pc_start = tb->pc; next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; ctx.pc = pc_start; @@ -19596,19 +19587,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags); gen_tb_start(tb); while (ctx.bstate == BS_NONE) { - 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; - gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK; - gen_opc_btarget[lj] = ctx.btarget; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget); num_insns++; @@ -19709,15 +19687,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, done_generating: 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; - } + tb->size = ctx.pc - pc_start; + tb->icount = num_insns; + #ifdef DEBUG_DISAS LOG_DISAS("\n"); if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { @@ -19728,16 +19700,6 @@ done_generating: #endif } -void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true); -} - static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf, int flags) { diff --git a/target-moxie/translate.c b/target-moxie/translate.c index c007764f3e..f84841efe2 100644 --- a/target-moxie/translate.c +++ b/target-moxie/translate.c @@ -815,15 +815,12 @@ static int decode_opc(MoxieCPU *cpu, DisasContext *ctx) } /* generate intermediate code for basic block 'tb'. */ -static inline void -gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, - bool search_pc) +void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb) { + MoxieCPU *cpu = moxie_env_get_cpu(env); CPUState *cs = CPU(cpu); DisasContext ctx; target_ulong pc_start; - int j, lj = -1; - CPUMoxieState *env = &cpu->env; int num_insns, max_insns; pc_start = tb->pc; @@ -844,18 +841,6 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, gen_tb_start(tb); do { - 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; - } tcg_gen_insn_start(ctx.pc); num_insns++; @@ -900,26 +885,8 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, done_generating: 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; - } -} - -void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(moxie_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUMoxieState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(moxie_env_get_cpu(env), tb, true); + tb->size = ctx.pc - pc_start; + tb->icount = num_insns; } void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb, diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index 26bf87f5fd..b66fde18fe 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -1618,14 +1618,12 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu) } } -static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, - TranslationBlock *tb, - int search_pc) +void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) { + OpenRISCCPU *cpu = openrisc_env_get_cpu(env); CPUState *cs = CPU(cpu); struct DisasContext ctx, *dc = &ctx; uint32_t pc_start; - int j, k; uint32_t next_page_start; int num_insns; int max_insns; @@ -1647,7 +1645,6 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, } next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - k = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; @@ -1661,18 +1658,6 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, gen_tb_start(tb); do { - if (search_pc) { - j = tcg_op_buf_count(); - if (k < j) { - k++; - while (k < j) { - tcg_ctx.gen_opc_instr_start[k++] = 0; - } - } - tcg_ctx.gen_opc_pc[k] = dc->pc; - tcg_ctx.gen_opc_instr_start[k] = 1; - tcg_ctx.gen_opc_icount[k] = num_insns; - } tcg_gen_insn_start(dc->pc); num_insns++; @@ -1746,16 +1731,8 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, gen_tb_end(tb, num_insns); - if (search_pc) { - j = tcg_op_buf_count(); - k++; - while (k <= j) { - tcg_ctx.gen_opc_instr_start[k++] = 0; - } - } else { - tb->size = dc->pc - pc_start; - tb->icount = num_insns; - } + tb->size = dc->pc - pc_start; + tb->icount = num_insns; #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { @@ -1767,17 +1744,6 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, #endif } -void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(openrisc_env_get_cpu(env), tb, 0); -} - -void gen_intermediate_code_pc(CPUOpenRISCState *env, - struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(openrisc_env_get_cpu(env), tb, 1); -} - void openrisc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 5c2dc38d35..c2bc1a7ec6 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -11409,16 +11409,13 @@ void ppc_cpu_dump_statistics(CPUState *cs, FILE*f, } /*****************************************************************************/ -static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, - TranslationBlock *tb, - bool search_pc) +void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb) { + PowerPCCPU *cpu = ppc_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUPPCState *env = &cpu->env; DisasContext ctx, *ctxp = &ctx; opc_handler_t **table, *handler; target_ulong pc_start; - int j, lj = -1; int num_insns; int max_insns; @@ -11486,17 +11483,6 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, tcg_clear_temp_count(); /* Set env in case of segfault during code fetch */ while (ctx.exception == POWERPC_EXCP_NONE && !tcg_op_buf_full()) { - if (unlikely(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.nip; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(ctx.nip); num_insns++; @@ -11598,15 +11584,9 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, } gen_tb_end(tb, num_insns); - if (unlikely(search_pc)) { - j = tcg_op_buf_count(); - lj++; - while (lj <= j) - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } else { - tb->size = ctx.nip - pc_start; - tb->icount = num_insns; - } + tb->size = ctx.nip - pc_start; + tb->icount = num_insns; + #if defined(DEBUG_DISAS) if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { int flags; @@ -11619,16 +11599,6 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, #endif } -void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, true); -} - void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, target_ulong *data) { diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 104265db5f..d4d7c735c0 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -161,8 +161,6 @@ static char cpu_reg_names[32][4]; static TCGv_i64 regs[16]; static TCGv_i64 fregs[16]; -static uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; - void s390x_translate_init(void) { int i; @@ -5319,16 +5317,13 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s) return ret; } -static inline void gen_intermediate_code_internal(S390CPU *cpu, - TranslationBlock *tb, - bool search_pc) +void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb) { + S390CPU *cpu = s390_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUS390XState *env = &cpu->env; DisasContext dc; target_ulong pc_start; uint64_t next_page_start; - int j, lj = -1; int num_insns, max_insns; ExitStatus status; bool do_debug; @@ -5359,19 +5354,6 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu, gen_tb_start(tb); do { - 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] = dc.pc; - gen_opc_cc_op[lj] = dc.cc_op; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(dc.pc, dc.cc_op); num_insns++; @@ -5430,16 +5412,8 @@ static inline void gen_intermediate_code_internal(S390CPU *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 = dc.pc - pc_start; - tb->icount = num_insns; - } + tb->size = dc.pc - pc_start; + tb->icount = num_insns; #if defined(S390X_DEBUG_DISAS) if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { @@ -5450,16 +5424,6 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu, #endif } -void gen_intermediate_code (CPUS390XState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(s390_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(s390_env_get_cpu(env), tb, true); -} - void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, target_ulong *data) { diff --git a/target-sh4/translate.c b/target-sh4/translate.c index d3fe1de94a..f764bc2539 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -70,8 +70,6 @@ static TCGv cpu_fregs[32]; /* internal register indexes */ static TCGv cpu_flags, cpu_delayed_pc; -static uint32_t gen_opc_hflags[OPC_BUF_SIZE]; - #include "exec/gen-icount.h" void sh4_translate_init(void) @@ -1816,15 +1814,12 @@ static void decode_opc(DisasContext * ctx) gen_store_flags(ctx->flags); } -static inline void -gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, - bool search_pc) +void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb) { + SuperHCPU *cpu = sh_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUSH4State *env = &cpu->env; DisasContext ctx; target_ulong pc_start; - int i, ii; int num_insns; int max_insns; @@ -1841,7 +1836,6 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, ctx.features = env->features; ctx.has_movcal = (ctx.flags & TB_FLAG_PENDING_MOVCA); - ii = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { @@ -1853,18 +1847,6 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, gen_tb_start(tb); while (ctx.bstate == BS_NONE && !tcg_op_buf_full()) { - if (search_pc) { - i = tcg_op_buf_count(); - if (ii < i) { - ii++; - while (ii < i) - tcg_ctx.gen_opc_instr_start[ii++] = 0; - } - tcg_ctx.gen_opc_pc[ii] = ctx.pc; - gen_opc_hflags[ii] = ctx.flags; - tcg_ctx.gen_opc_instr_start[ii] = 1; - tcg_ctx.gen_opc_icount[ii] = num_insns; - } tcg_gen_insn_start(ctx.pc, ctx.flags); num_insns++; @@ -1921,15 +1903,8 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, gen_tb_end(tb, num_insns); - if (search_pc) { - i = tcg_op_buf_count(); - ii++; - while (ii <= i) - tcg_ctx.gen_opc_instr_start[ii++] = 0; - } else { - tb->size = ctx.pc - pc_start; - tb->icount = num_insns; - } + tb->size = ctx.pc - pc_start; + tb->icount = num_insns; #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { @@ -1940,16 +1915,6 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, #endif } -void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(sh_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUSH4State * env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(sh_env_get_cpu(env), tb, true); -} - void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, target_ulong *data) { diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 18344c82ed..b59742ad2e 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -64,8 +64,6 @@ static TCGv cpu_wim; /* Floating point registers */ static TCGv_i64 cpu_fpr[TARGET_DPREGS]; -static target_ulong gen_opc_npc[OPC_BUF_SIZE]; - #include "exec/gen-icount.h" typedef struct DisasContext { @@ -5208,15 +5206,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } } -static inline void gen_intermediate_code_internal(SPARCCPU *cpu, - TranslationBlock *tb, - bool spc) +void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb) { + SPARCCPU *cpu = sparc_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUSPARCState *env = &cpu->env; target_ulong pc_start, last_pc; DisasContext dc1, *dc = &dc1; - int j, lj = -1; int num_insns; int max_insns; unsigned int insn; @@ -5245,23 +5240,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, gen_tb_start(tb); do { - if (spc) { - qemu_log("Search PC...\n"); - 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] = dc->pc; - gen_opc_npc[lj] = dc->npc; - if (dc->npc & JUMP_PC) { - assert(dc->jump_pc[1] == dc->pc + 4); - gen_opc_npc[lj] = dc->jump_pc[0] | JUMP_PC; - } - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } - } if (dc->npc & JUMP_PC) { assert(dc->jump_pc[1] == dc->pc + 4); tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC); @@ -5326,18 +5304,9 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, } gen_tb_end(tb, num_insns); - if (spc) { - j = tcg_op_buf_count(); - lj++; - while (lj <= j) - tcg_ctx.gen_opc_instr_start[lj++] = 0; -#if 0 - log_page_dump(); -#endif - } else { - tb->size = last_pc + 4 - pc_start; - tb->icount = num_insns; - } + tb->size = last_pc + 4 - pc_start; + tb->icount = num_insns; + #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { qemu_log("--------------\n"); @@ -5348,16 +5317,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, #endif } -void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb) -{ - gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb) -{ - gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, true); -} - void gen_intermediate_code_init(CPUSPARCState *env) { unsigned int i; diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index eae5622a9a..ff96165c94 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -2049,17 +2049,14 @@ static void translate_one_bundle(DisasContext *dc, uint64_t bundle) } } -static inline void gen_intermediate_code_internal(TileGXCPU *cpu, - TranslationBlock *tb, - bool search_pc) +void gen_intermediate_code(CPUTLGState *env, struct TranslationBlock *tb) { + TileGXCPU *cpu = tilegx_env_get_cpu(env); DisasContext ctx; DisasContext *dc = &ctx; CPUState *cs = CPU(cpu); - CPUTLGState *env = &cpu->env; uint64_t pc_start = tb->pc; uint64_t next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - int j, lj = -1; int num_insns = 0; int max_insns = tb->cflags & CF_COUNT_MASK; @@ -2087,18 +2084,6 @@ static inline void gen_intermediate_code_internal(TileGXCPU *cpu, gen_tb_start(tb); while (1) { - 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] = dc->pc; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(dc->pc); num_insns++; @@ -2120,30 +2105,12 @@ static inline void gen_intermediate_code_internal(TileGXCPU *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 = dc->pc - pc_start; - tb->icount = num_insns; - } + tb->size = dc->pc - pc_start; + tb->icount = num_insns; qemu_log_mask(CPU_LOG_TB_IN_ASM, "\n"); } -void gen_intermediate_code(CPUTLGState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(tilegx_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUTLGState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(tilegx_env_get_cpu(env), tb, true); -} - void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb, target_ulong *data) { diff --git a/target-tricore/translate.c b/target-tricore/translate.c index 6f5438fe1e..135c58347a 100644 --- a/target-tricore/translate.c +++ b/target-tricore/translate.c @@ -8266,20 +8266,14 @@ static void decode_opc(CPUTriCoreState *env, DisasContext *ctx, int *is_branch) } } -static inline void -gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb, - int search_pc) +void gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb) { + TriCoreCPU *cpu = tricore_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUTriCoreState *env = &cpu->env; DisasContext ctx; target_ulong pc_start; int num_insns, max_insns; - if (search_pc) { - qemu_log("search pc %d\n", search_pc); - } - num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { @@ -8318,12 +8312,9 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb, } gen_tb_end(tb, num_insns); - if (search_pc) { - printf("done_generating search pc\n"); - } else { - tb->size = ctx.pc - pc_start; - tb->icount = num_insns; - } + tb->size = ctx.pc - pc_start; + tb->icount = num_insns; + if (tcg_check_temp_count()) { printf("LEAK at %08x\n", env->PC); } @@ -8337,18 +8328,6 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb, #endif } -void -gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(tricore_env_get_cpu(env), tb, false); -} - -void -gen_intermediate_code_pc(CPUTriCoreState *env, struct TranslationBlock *tb) -{ - gen_intermediate_code_internal(tricore_env_get_cpu(env), tb, true); -} - void restore_state_to_opc(CPUTriCoreState *env, TranslationBlock *tb, target_ulong *data) diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 9d8167a35c..48f89fb1c5 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -1864,15 +1864,12 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s) } /* generate intermediate code in gen_opc_buf and gen_opparam_buf for - basic block 'tb'. If search_pc is TRUE, also generate PC - information for each intermediate instruction. */ -static inline void gen_intermediate_code_internal(UniCore32CPU *cpu, - TranslationBlock *tb, bool search_pc) + basic block 'tb'. */ +void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb) { + UniCore32CPU *cpu = uc32_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUUniCore32State *env = &cpu->env; DisasContext dc1, *dc = &dc1; - int j, lj; target_ulong pc_start; uint32_t next_page_start; int num_insns; @@ -1894,7 +1891,6 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu, cpu_F0d = tcg_temp_new_i64(); cpu_F1d = tcg_temp_new_i64(); next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { @@ -1914,18 +1910,6 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu, gen_tb_start(tb); do { - 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] = dc->pc; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; - } tcg_gen_insn_start(dc->pc); num_insns++; @@ -2039,26 +2023,8 @@ done_generating: qemu_log("\n"); } #endif - if (search_pc) { - j = tcg_op_buf_count(); - lj++; - while (lj <= j) { - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } - } else { - tb->size = dc->pc - pc_start; - tb->icount = num_insns; - } -} - -void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUUniCore32State *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, true); + tb->size = dc->pc - pc_start; + tb->icount = num_insns; } static const char *cpu_mode_names[16] = { diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index ac967e136c..fda91b7e5d 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -2997,15 +2997,12 @@ static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc) } } -static inline -void gen_intermediate_code_internal(XtensaCPU *cpu, - TranslationBlock *tb, bool search_pc) +void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb) { + XtensaCPU *cpu = xtensa_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUXtensaState *env = &cpu->env; DisasContext dc; int insn_count = 0; - int j, lj = -1; int max_insns = tb->cflags & CF_COUNT_MASK; uint32_t pc_start = tb->pc; uint32_t next_page_start = @@ -3049,18 +3046,6 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, } do { - 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] = dc.pc; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = insn_count; - } tcg_gen_insn_start(dc.pc); ++insn_count; @@ -3131,24 +3116,8 @@ void gen_intermediate_code_internal(XtensaCPU *cpu, qemu_log("\n"); } #endif - if (search_pc) { - j = tcg_op_buf_count(); - memset(tcg_ctx.gen_opc_instr_start + lj + 1, 0, - (j - lj) * sizeof(tcg_ctx.gen_opc_instr_start[0])); - } else { - tb->size = dc.pc - pc_start; - tb->icount = insn_count; - } -} - -void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUXtensaState *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, true); + tb->size = dc.pc - pc_start; + tb->icount = insn_count; } void xtensa_cpu_dump_state(CPUState *cs, FILE *f, diff --git a/tcg/tcg.h b/tcg/tcg.h index df499c6fa9..d079a91ef5 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -578,10 +578,6 @@ struct TCGContext { TCGOp gen_op_buf[OPC_BUF_SIZE]; TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE]; - target_ulong gen_opc_pc[OPC_BUF_SIZE]; - uint16_t gen_opc_icount[OPC_BUF_SIZE]; - uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; - uint16_t gen_insn_end_off[TCG_MAX_INSNS]; target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS]; }; From 04fe64000162c45d8974da9ca4d266f8d0e67eb7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 1 Sep 2015 20:07:48 -0700 Subject: [PATCH 22/26] tcg: Remove tcg_gen_code_search_pc It's no longer used, so tidy up everything reached by it. Reviewed-by: Aurelien Jarno Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- tcg/tcg.c | 59 ++++++++++++++++++------------------------------------- tcg/tcg.h | 2 -- 2 files changed, 19 insertions(+), 42 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index 40f24de1ad..d3693b17f2 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -2290,12 +2290,28 @@ void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf) #endif -static inline int tcg_gen_code_common(TCGContext *s, - tcg_insn_unit *gen_code_buf, - long search_pc) +int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf) { int i, oi, oi_next, num_insns; +#ifdef CONFIG_PROFILER + { + int n; + + n = s->gen_last_op_idx + 1; + s->op_count += n; + if (n > s->op_count_max) { + s->op_count_max = n; + } + + n = s->nb_temps; + s->temp_count += n; + if (n > s->temp_count_max) { + s->temp_count_max = n; + } + } +#endif + #ifdef DEBUG_DISAS if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { qemu_log("OP:\n"); @@ -2398,9 +2414,6 @@ static inline int tcg_gen_code_common(TCGContext *s, tcg_reg_alloc_op(s, def, opc, args, dead_args, sync_args); break; } - if (search_pc >= 0 && search_pc < tcg_current_code_size(s)) { - return oi; - } #ifndef NDEBUG check_regs(s); #endif @@ -2410,30 +2423,6 @@ static inline int tcg_gen_code_common(TCGContext *s, /* Generate TB finalization at the end of block */ tcg_out_tb_finalize(s); - return -1; -} - -int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf) -{ -#ifdef CONFIG_PROFILER - { - int n; - - n = s->gen_last_op_idx + 1; - s->op_count += n; - if (n > s->op_count_max) { - s->op_count_max = n; - } - - n = s->nb_temps; - s->temp_count += n; - if (n > s->temp_count_max) { - s->temp_count_max = n; - } - } -#endif - - tcg_gen_code_common(s, gen_code_buf, -1); /* flush instruction cache */ flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr); @@ -2441,16 +2430,6 @@ int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf) return tcg_current_code_size(s); } -/* Return the index of the micro operation such as the pc after is < - offset bytes from the start of the TB. The contents of gen_code_buf must - not be changed, though writing the same values is ok. - Return -1 if not found. */ -int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf, - long offset) -{ - return tcg_gen_code_common(s, gen_code_buf, offset); -} - #ifdef CONFIG_PROFILER void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf) { diff --git a/tcg/tcg.h b/tcg/tcg.h index d079a91ef5..5fbbd15660 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -626,8 +626,6 @@ void tcg_prologue_init(TCGContext *s); void tcg_func_start(TCGContext *s); int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf); -int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf, - long offset); void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size); From 8163b74938d8b7d12e70597c4553dd0dc49443d5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 18 Sep 2015 23:43:05 -0700 Subject: [PATCH 23/26] tcg: Emit prologue to the beginning of code_gen_buffer By putting the prologue at the end, we risk overwriting the prologue should our estimate of maximum TB size. Given the two different placements of the call to tcg_prologue_init, move the high water mark computation into tcg_prologue_init. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- tcg/tcg.c | 35 ++++++++++++++++++++++++++++------- translate-all.c | 24 +++++++----------------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/tcg/tcg.c b/tcg/tcg.c index d3693b17f2..56091087a4 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -363,17 +363,38 @@ void tcg_context_init(TCGContext *s) void tcg_prologue_init(TCGContext *s) { - /* init global prologue and epilogue */ - s->code_buf = s->code_gen_prologue; - s->code_ptr = s->code_buf; + size_t prologue_size, total_size; + void *buf0, *buf1; + + /* Put the prologue at the beginning of code_gen_buffer. */ + buf0 = s->code_gen_buffer; + s->code_ptr = buf0; + s->code_buf = buf0; + s->code_gen_prologue = buf0; + + /* Generate the prologue. */ tcg_target_qemu_prologue(s); - flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr); + buf1 = s->code_ptr; + flush_icache_range((uintptr_t)buf0, (uintptr_t)buf1); + + /* Deduct the prologue from the buffer. */ + prologue_size = tcg_current_code_size(s); + s->code_gen_ptr = buf1; + s->code_gen_buffer = buf1; + s->code_buf = buf1; + total_size = s->code_gen_buffer_size - prologue_size; + s->code_gen_buffer_size = total_size; + + /* Compute a high-water mark, at which we voluntarily flush the + buffer and start over. */ + s->code_gen_buffer_max_size = total_size - TCG_MAX_OP_SIZE * OPC_BUF_SIZE; + + tcg_register_jit(s->code_gen_buffer, total_size); #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) { - size_t size = tcg_current_code_size(s); - qemu_log("PROLOGUE: [size=%zu]\n", size); - log_disas(s->code_buf, size); + qemu_log("PROLOGUE: [size=%zu]\n", prologue_size); + log_disas(buf0, prologue_size); qemu_log("\n"); qemu_log_flush(); } diff --git a/translate-all.c b/translate-all.c index 3454f4ed45..0e8d176de0 100644 --- a/translate-all.c +++ b/translate-all.c @@ -690,23 +690,15 @@ static inline void code_gen_alloc(size_t tb_size) } qemu_madvise(tcg_ctx.code_gen_buffer, tcg_ctx.code_gen_buffer_size, - QEMU_MADV_HUGEPAGE); + QEMU_MADV_HUGEPAGE); - /* Steal room for the prologue at the end of the buffer. This ensures - (via the MAX_CODE_GEN_BUFFER_SIZE limits above) that direct branches - from TB's to the prologue are going to be in range. It also means - that we don't need to mark (additional) portions of the data segment - as executable. */ - tcg_ctx.code_gen_prologue = tcg_ctx.code_gen_buffer + - tcg_ctx.code_gen_buffer_size - 1024; - tcg_ctx.code_gen_buffer_size -= 1024; + /* Estimate a good size for the number of TBs we can support. We + still haven't deducted the prologue from the buffer size here, + but that's minimal and won't affect the estimate much. */ + tcg_ctx.code_gen_max_blocks + = tcg_ctx.code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE; + tcg_ctx.tb_ctx.tbs = g_new(TranslationBlock, tcg_ctx.code_gen_max_blocks); - tcg_ctx.code_gen_buffer_max_size = tcg_ctx.code_gen_buffer_size - - (TCG_MAX_OP_SIZE * OPC_BUF_SIZE); - tcg_ctx.code_gen_max_blocks = tcg_ctx.code_gen_buffer_size / - CODE_GEN_AVG_BLOCK_SIZE; - tcg_ctx.tb_ctx.tbs = - g_malloc(tcg_ctx.code_gen_max_blocks * sizeof(TranslationBlock)); qemu_mutex_init(&tcg_ctx.tb_ctx.tb_lock); } @@ -717,8 +709,6 @@ void tcg_exec_init(unsigned long tb_size) { cpu_gen_init(); code_gen_alloc(tb_size); - tcg_ctx.code_gen_ptr = tcg_ctx.code_gen_buffer; - tcg_register_jit(tcg_ctx.code_gen_buffer, tcg_ctx.code_gen_buffer_size); page_init(); #if defined(CONFIG_SOFTMMU) /* There's no guest base to take into account, so go ahead and From f293709c6af7a65a9bcec09cdba7a60183657a3e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 19 Sep 2015 12:03:15 -0700 Subject: [PATCH 24/26] tcg: Allocate a guard page after code_gen_buffer This will catch any overflow of the buffer. Add a native win32 alternative for alloc_code_gen_buffer; remove the malloc alternative. Signed-off-by: Richard Henderson --- translate-all.c | 214 +++++++++++++++++++++++++++--------------------- 1 file changed, 121 insertions(+), 93 deletions(-) diff --git a/translate-all.c b/translate-all.c index 0e8d176de0..b43bd03654 100644 --- a/translate-all.c +++ b/translate-all.c @@ -312,31 +312,6 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t retaddr) return false; } -#ifdef _WIN32 -static __attribute__((unused)) void map_exec(void *addr, long size) -{ - DWORD old_protect; - VirtualProtect(addr, size, - PAGE_EXECUTE_READWRITE, &old_protect); -} -#else -static __attribute__((unused)) void map_exec(void *addr, long size) -{ - unsigned long start, end, page_size; - - page_size = getpagesize(); - start = (unsigned long)addr; - start &= ~(page_size - 1); - - end = (unsigned long)addr + size; - end += page_size - 1; - end &= ~(page_size - 1); - - mprotect((void *)start, end - start, - PROT_READ | PROT_WRITE | PROT_EXEC); -} -#endif - void page_size_init(void) { /* NOTE: we can always suppose that qemu_host_page_size >= @@ -473,14 +448,6 @@ static inline PageDesc *page_find(tb_page_addr_t index) #define USE_STATIC_CODE_GEN_BUFFER #endif -/* ??? Should configure for this, not list operating systems here. */ -#if (defined(__linux__) \ - || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \ - || defined(__DragonFly__) || defined(__OpenBSD__) \ - || defined(__NetBSD__)) -# define USE_MMAP -#endif - /* Minimum size of the code gen buffer. This number is randomly chosen, but not so small that we can't have a fair number of TB's live. */ #define MIN_CODE_GEN_BUFFER_SIZE (1024u * 1024) @@ -568,22 +535,102 @@ static inline void *split_cross_256mb(void *buf1, size_t size1) static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE] __attribute__((aligned(CODE_GEN_ALIGN))); +# ifdef _WIN32 +static inline void do_protect(void *addr, long size, int prot) +{ + DWORD old_protect; + VirtualProtect(addr, size, prot, &old_protect); +} + +static inline void map_exec(void *addr, long size) +{ + do_protect(addr, size, PAGE_EXECUTE_READWRITE); +} + +static inline void map_none(void *addr, long size) +{ + do_protect(addr, size, PAGE_NOACCESS); +} +# else +static inline void do_protect(void *addr, long size, int prot) +{ + uintptr_t start, end; + + start = (uintptr_t)addr; + start &= qemu_real_host_page_mask; + + end = (uintptr_t)addr + size; + end = ROUND_UP(end, qemu_real_host_page_size); + + mprotect((void *)start, end - start, prot); +} + +static inline void map_exec(void *addr, long size) +{ + do_protect(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC); +} + +static inline void map_none(void *addr, long size) +{ + do_protect(addr, size, PROT_NONE); +} +# endif /* WIN32 */ + static inline void *alloc_code_gen_buffer(void) { void *buf = static_code_gen_buffer; + size_t full_size, size; + + /* The size of the buffer, rounded down to end on a page boundary. */ + full_size = (((uintptr_t)buf + sizeof(static_code_gen_buffer)) + & qemu_real_host_page_mask) - (uintptr_t)buf; + + /* Reserve a guard page. */ + size = full_size - qemu_real_host_page_size; + + /* Honor a command-line option limiting the size of the buffer. */ + if (size > tcg_ctx.code_gen_buffer_size) { + size = (((uintptr_t)buf + tcg_ctx.code_gen_buffer_size) + & qemu_real_host_page_mask) - (uintptr_t)buf; + } + tcg_ctx.code_gen_buffer_size = size; + #ifdef __mips__ - if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) { - buf = split_cross_256mb(buf, tcg_ctx.code_gen_buffer_size); + if (cross_256mb(buf, size)) { + buf = split_cross_256mb(buf, size); + size = tcg_ctx.code_gen_buffer_size; } #endif - map_exec(buf, tcg_ctx.code_gen_buffer_size); + + map_exec(buf, size); + map_none(buf + size, qemu_real_host_page_size); + qemu_madvise(buf, size, QEMU_MADV_HUGEPAGE); + return buf; } -#elif defined(USE_MMAP) +#elif defined(_WIN32) +static inline void *alloc_code_gen_buffer(void) +{ + size_t size = tcg_ctx.code_gen_buffer_size; + void *buf1, *buf2; + + /* Perform the allocation in two steps, so that the guard page + is reserved but uncommitted. */ + buf1 = VirtualAlloc(NULL, size + qemu_real_host_page_size, + MEM_RESERVE, PAGE_NOACCESS); + if (buf1 != NULL) { + buf2 = VirtualAlloc(buf1, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + assert(buf1 == buf2); + } + + return buf1; +} +#else static inline void *alloc_code_gen_buffer(void) { int flags = MAP_PRIVATE | MAP_ANONYMOUS; uintptr_t start = 0; + size_t size = tcg_ctx.code_gen_buffer_size; void *buf; /* Constrain the position of the buffer based on the host cpu. @@ -599,86 +646,70 @@ static inline void *alloc_code_gen_buffer(void) Leave the choice of exact location with the kernel. */ flags |= MAP_32BIT; /* Cannot expect to map more than 800MB in low memory. */ - if (tcg_ctx.code_gen_buffer_size > 800u * 1024 * 1024) { - tcg_ctx.code_gen_buffer_size = 800u * 1024 * 1024; + if (size > 800u * 1024 * 1024) { + tcg_ctx.code_gen_buffer_size = size = 800u * 1024 * 1024; } # elif defined(__sparc__) start = 0x40000000ul; # elif defined(__s390x__) start = 0x90000000ul; # elif defined(__mips__) - /* ??? We ought to more explicitly manage layout for softmmu too. */ -# ifdef CONFIG_USER_ONLY - start = 0x68000000ul; -# elif _MIPS_SIM == _ABI64 +# if _MIPS_SIM == _ABI64 start = 0x128000000ul; # else start = 0x08000000ul; # endif # endif - buf = mmap((void *)start, tcg_ctx.code_gen_buffer_size, - PROT_WRITE | PROT_READ | PROT_EXEC, flags, -1, 0); + buf = mmap((void *)start, size + qemu_real_host_page_size, + PROT_NONE, flags, -1, 0); if (buf == MAP_FAILED) { return NULL; } #ifdef __mips__ - if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) { + if (cross_256mb(buf, size)) { /* Try again, with the original still mapped, to avoid re-acquiring that 256mb crossing. This time don't specify an address. */ - size_t size2, size1 = tcg_ctx.code_gen_buffer_size; - void *buf2 = mmap(NULL, size1, PROT_WRITE | PROT_READ | PROT_EXEC, - flags, -1, 0); - if (buf2 != MAP_FAILED) { - if (!cross_256mb(buf2, size1)) { + size_t size2; + void *buf2 = mmap(NULL, size + qemu_real_host_page_size, + PROT_NONE, flags, -1, 0); + switch (buf2 != MAP_FAILED) { + case 1: + if (!cross_256mb(buf2, size)) { /* Success! Use the new buffer. */ - munmap(buf, size1); - return buf2; + munmap(buf, size); + break; } /* Failure. Work with what we had. */ - munmap(buf2, size1); + munmap(buf2, size); + /* fallthru */ + default: + /* Split the original buffer. Free the smaller half. */ + buf2 = split_cross_256mb(buf, size); + size2 = tcg_ctx.code_gen_buffer_size; + if (buf == buf2) { + munmap(buf + size2 + qemu_real_host_page_size, size - size2); + } else { + munmap(buf, size - size2); + } + size = size2; + break; } - - /* Split the original buffer. Free the smaller half. */ - buf2 = split_cross_256mb(buf, size1); - size2 = tcg_ctx.code_gen_buffer_size; - munmap(buf + (buf == buf2 ? size2 : 0), size1 - size2); - return buf2; + buf = buf2; } #endif + /* Make the final buffer accessible. The guard page at the end + will remain inaccessible with PROT_NONE. */ + mprotect(buf, size, PROT_WRITE | PROT_READ | PROT_EXEC); + + /* Request large pages for the buffer. */ + qemu_madvise(buf, size, QEMU_MADV_HUGEPAGE); + return buf; } -#else -static inline void *alloc_code_gen_buffer(void) -{ - void *buf = g_try_malloc(tcg_ctx.code_gen_buffer_size); - - if (buf == NULL) { - return NULL; - } - -#ifdef __mips__ - if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) { - void *buf2 = g_malloc(tcg_ctx.code_gen_buffer_size); - if (buf2 != NULL && !cross_256mb(buf2, size1)) { - /* Success! Use the new buffer. */ - free(buf); - buf = buf2; - } else { - /* Failure. Work with what we had. Since this is malloc - and not mmap, we can't free the other half. */ - free(buf2); - buf = split_cross_256mb(buf, tcg_ctx.code_gen_buffer_size); - } - } -#endif - - map_exec(buf, tcg_ctx.code_gen_buffer_size); - return buf; -} -#endif /* USE_STATIC_CODE_GEN_BUFFER, USE_MMAP */ +#endif /* USE_STATIC_CODE_GEN_BUFFER, WIN32, POSIX */ static inline void code_gen_alloc(size_t tb_size) { @@ -689,9 +720,6 @@ static inline void code_gen_alloc(size_t tb_size) exit(1); } - qemu_madvise(tcg_ctx.code_gen_buffer, tcg_ctx.code_gen_buffer_size, - QEMU_MADV_HUGEPAGE); - /* Estimate a good size for the number of TBs we can support. We still haven't deducted the prologue from the buffer size here, but that's minimal and won't affect the estimate much. */ @@ -708,8 +736,8 @@ static inline void code_gen_alloc(size_t tb_size) void tcg_exec_init(unsigned long tb_size) { cpu_gen_init(); - code_gen_alloc(tb_size); page_init(); + code_gen_alloc(tb_size); #if defined(CONFIG_SOFTMMU) /* There's no guest base to take into account, so go ahead and initialize the prologue now. */ From b125f9dc7bd68cd4c57189db4da83b0620b28a72 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 22 Sep 2015 13:01:15 -0700 Subject: [PATCH 25/26] tcg: Check for overflow via highwater mark We currently pre-compute an worst case code size for any TB, which works out to be 122kB. Since the average TB size is near 1kB, this wastes quite a lot of storage. Instead, check for overflow in between generating code for each opcode. The overhead of the check isn't measurable and wastage is minimized. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- include/exec/exec-all.h | 6 ------ tcg/tcg.c | 14 +++++++++++--- tcg/tcg.h | 5 +++-- translate-all.c | 31 ++++++++++++++++++++++++++----- 4 files changed, 40 insertions(+), 16 deletions(-) diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 6871e782b3..71c9d85278 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -62,12 +62,6 @@ 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" diff --git a/tcg/tcg.c b/tcg/tcg.c index 56091087a4..682af8a7c6 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -385,9 +385,10 @@ void tcg_prologue_init(TCGContext *s) total_size = s->code_gen_buffer_size - prologue_size; s->code_gen_buffer_size = total_size; - /* Compute a high-water mark, at which we voluntarily flush the - buffer and start over. */ - s->code_gen_buffer_max_size = total_size - TCG_MAX_OP_SIZE * OPC_BUF_SIZE; + /* Compute a high-water mark, at which we voluntarily flush the buffer + and start over. The size here is arbitrary, significantly larger + than we expect the code generation for any one opcode to require. */ + s->code_gen_highwater = s->code_gen_buffer + (total_size - 1024); tcg_register_jit(s->code_gen_buffer, total_size); @@ -2438,6 +2439,13 @@ int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf) #ifndef NDEBUG check_regs(s); #endif + /* Test for (pending) buffer overflow. The assumption is that any + one operation beginning below the high water mark cannot overrun + the buffer completely. Thus we can test for overflow after + generating code without having to check during generation. */ + if (unlikely(s->code_gen_ptr > s->code_gen_highwater)) { + return -1; + } } tcg_debug_assert(num_insns >= 0); s->gen_insn_end_off[num_insns] = tcg_current_code_size(s); diff --git a/tcg/tcg.h b/tcg/tcg.h index 5fbbd15660..a696922420 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -559,10 +559,11 @@ struct TCGContext { void *code_gen_prologue; void *code_gen_buffer; size_t code_gen_buffer_size; - /* threshold to flush the translated code buffer */ - size_t code_gen_buffer_max_size; void *code_gen_ptr; + /* Threshold to flush the translated code buffer. */ + void *code_gen_highwater; + TBContext tb_ctx; /* The TCGBackendData structure is private to tcg-target.c. */ diff --git a/translate-all.c b/translate-all.c index b43bd03654..333eba4f5d 100644 --- a/translate-all.c +++ b/translate-all.c @@ -223,6 +223,7 @@ static target_long decode_sleb128(uint8_t **pp) static int encode_search(TranslationBlock *tb, uint8_t *block) { + uint8_t *highwater = tcg_ctx.code_gen_highwater; uint8_t *p = block; int i, j, n; @@ -241,6 +242,14 @@ static int encode_search(TranslationBlock *tb, uint8_t *block) } prev = (i == 0 ? 0 : tcg_ctx.gen_insn_end_off[i - 1]); p = encode_sleb128(p, tcg_ctx.gen_insn_end_off[i] - prev); + + /* Test for (pending) buffer overflow. The assumption is that any + one row beginning below the high water mark cannot overrun + the buffer completely. Thus we can test for overflow after + encoding a row without having to check during encoding. */ + if (unlikely(p > highwater)) { + return -1; + } } return p - block; @@ -756,9 +765,7 @@ static TranslationBlock *tb_alloc(target_ulong pc) { TranslationBlock *tb; - if (tcg_ctx.tb_ctx.nb_tbs >= tcg_ctx.code_gen_max_blocks || - (tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) >= - tcg_ctx.code_gen_buffer_max_size) { + if (tcg_ctx.tb_ctx.nb_tbs >= tcg_ctx.code_gen_max_blocks) { return NULL; } tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++]; @@ -1063,12 +1070,15 @@ TranslationBlock *tb_gen_code(CPUState *cpu, if (use_icount) { cflags |= CF_USE_ICOUNT; } + tb = tb_alloc(pc); - if (!tb) { + if (unlikely(!tb)) { + buffer_overflow: /* flush must be done */ tb_flush(cpu); /* cannot fail at this point */ tb = tb_alloc(pc); + assert(tb != NULL); /* Don't forget to invalidate previous TB info. */ tcg_ctx.tb_ctx.tb_invalidated_flag = 1; } @@ -1109,8 +1119,19 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tcg_ctx.code_time -= profile_getclock(); #endif + /* ??? Overflow could be handled better here. In particular, we + don't need to re-do gen_intermediate_code, nor should we re-do + the tcg optimization currently hidden inside tcg_gen_code. All + that should be required is to flush the TBs, allocate a new TB, + re-initialize it per above, and re-do the actual code generation. */ gen_code_size = tcg_gen_code(&tcg_ctx, gen_code_buf); + if (unlikely(gen_code_size < 0)) { + goto buffer_overflow; + } search_size = encode_search(tb, (void *)gen_code_buf + gen_code_size); + if (unlikely(search_size < 0)) { + goto buffer_overflow; + } #ifdef CONFIG_PROFILER tcg_ctx.code_time += profile_getclock(); @@ -1681,7 +1702,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf) cpu_fprintf(f, "Translation buffer state:\n"); cpu_fprintf(f, "gen code size %td/%zd\n", tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer, - tcg_ctx.code_gen_buffer_max_size); + tcg_ctx.code_gen_highwater - tcg_ctx.code_gen_buffer); cpu_fprintf(f, "TB count %d/%d\n", tcg_ctx.tb_ctx.nb_tbs, tcg_ctx.code_gen_max_blocks); cpu_fprintf(f, "TB avg target size %d max=%d bytes\n", From 126d89e8cdfa3be15d51f76906eaccbcd0023f98 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 26 Sep 2015 09:23:42 -0700 Subject: [PATCH 26/26] tcg: Adjust CODE_GEN_AVG_BLOCK_SIZE At present, the "average" guestimate of TB size is way too small, leading to many unused entries in the pre-allocated TB array. For a guest with 1GB ram, we're currently allocating 256MB for the array. Survey arm, alpha, aarch64, ppc, sparc, i686, x86_64 guests running on x86_64 and ppc64 hosts and select a new average. The size of the array drops to 81MB with no more flushing than before. Reviewed-by: Aurelien Jarno Signed-off-by: Richard Henderson --- include/exec/exec-all.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 71c9d85278..a63fd6015e 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -161,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) \