diff options
author | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-06-29 01:03:05 +0000 |
---|---|---|
committer | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-06-29 01:03:05 +0000 |
commit | 2e70f6efa8b960d3b5401373ad6fa98747bb9578 (patch) | |
tree | 4864a691a4d52324fe4626261e202525dd3a8659 /target-ppc | |
parent | f6e5889e7f581d286cd2153a71c386795a7070ac (diff) |
Add instruction counter.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4799 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/cpu.h | 3 | ||||
-rw-r--r-- | target-ppc/helper.c | 1 | ||||
-rw-r--r-- | target-ppc/translate.c | 32 |
3 files changed, 35 insertions, 1 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index d08bbba995..d9dcf58ef3 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -697,6 +697,7 @@ struct mmu_ctx_t { /*****************************************************************************/ CPUPPCState *cpu_ppc_init (const char *cpu_model); +void ppc_translate_init(void); int cpu_ppc_exec (CPUPPCState *s); void cpu_ppc_close (CPUPPCState *s); /* you can call this signal handler from your SIGBUS and SIGSEGV @@ -833,6 +834,8 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp) } #endif +#define CPU_PC_FROM_TB(env, tb) env->nip = tb->pc + #include "cpu-all.h" /*****************************************************************************/ diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 2a52dc69a2..c6ac6cb0e0 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -2977,6 +2977,7 @@ CPUPPCState *cpu_ppc_init (const char *cpu_model) if (!env) return NULL; cpu_exec_init(env); + ppc_translate_init(); env->cpu_model_str = cpu_model; cpu_ppc_register_internal(env, def); cpu_ppc_reset(env); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 28cb6abdda..b98ba35bd3 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -43,6 +43,19 @@ /*****************************************************************************/ /* Code translation helpers */ +static TCGv cpu_env; + +#include "gen-icount.h" + +void ppc_translate_init(void) +{ + int done_init = 0; + if (done_init) + return; + cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env"); + done_init = 1; +} + #if defined(OPTIMIZE_FPRF_UPDATE) static uint16_t *gen_fprf_buf[OPC_BUF_SIZE]; static uint16_t **gen_fprf_ptr; @@ -6168,6 +6181,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, uint16_t *gen_opc_end; int supervisor, little_endian; int j, lj = -1; + int num_insns; + int max_insns; pc_start = tb->pc; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; @@ -6211,6 +6226,12 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, /* Single step trace mode */ msr_se = 1; #endif + num_insns = 0; + max_insns = tb->cflags & CF_COUNT_MASK; + if (max_insns == 0) + max_insns = CF_COUNT_MASK; + + gen_icount_start(); /* Set env in case of segfault during code fetch */ while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) { if (unlikely(env->nb_breakpoints > 0)) { @@ -6230,6 +6251,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, gen_opc_instr_start[lj++] = 0; gen_opc_pc[lj] = ctx.nip; gen_opc_instr_start[lj] = 1; + gen_opc_icount[lj] = num_insns; } } #if defined PPC_DEBUG_DISAS @@ -6239,6 +6261,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, ctx.nip, supervisor, (int)msr_ir); } #endif + if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + gen_io_start(); if (unlikely(little_endian)) { ctx.opcode = bswap32(ldl_code(ctx.nip)); } else { @@ -6253,6 +6277,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, #endif ctx.nip += 4; table = env->opcodes; + num_insns++; handler = table[opc1(ctx.opcode)]; if (is_indirect_opcode(handler)) { table = ind_table(handler); @@ -6306,7 +6331,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, ctx.exception != POWERPC_EXCP_BRANCH)) { GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0); } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) || - (env->singlestep_enabled))) { + (env->singlestep_enabled) || + num_insns >= max_insns)) { /* if we reach a page boundary or are single stepping, stop * generation */ @@ -6316,6 +6342,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, break; #endif } + if (tb->cflags & CF_LAST_IO) + gen_io_end(); if (ctx.exception == POWERPC_EXCP_NONE) { gen_goto_tb(&ctx, 0, ctx.nip); } else if (ctx.exception != POWERPC_EXCP_BRANCH) { @@ -6326,6 +6354,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, /* Generate the return instruction */ tcg_gen_exit_tb(0); } + gen_icount_end(tb, num_insns); *gen_opc_ptr = INDEX_op_end; if (unlikely(search_pc)) { j = gen_opc_ptr - gen_opc_buf; @@ -6334,6 +6363,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, gen_opc_instr_start[lj++] = 0; } else { tb->size = ctx.nip - pc_start; + tb->icount = num_insns; } #if defined(DEBUG_DISAS) if (loglevel & CPU_LOG_TB_CPU) { |