summaryrefslogtreecommitdiff
path: root/target-alpha
diff options
context:
space:
mode:
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2008-06-29 01:03:05 +0000
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2008-06-29 01:03:05 +0000
commit2e70f6efa8b960d3b5401373ad6fa98747bb9578 (patch)
tree4864a691a4d52324fe4626261e202525dd3a8659 /target-alpha
parentf6e5889e7f581d286cd2153a71c386795a7070ac (diff)
downloadqemu-2e70f6efa8b960d3b5401373ad6fa98747bb9578.zip
Add instruction counter.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4799 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-alpha')
-rw-r--r--target-alpha/cpu.h2
-rw-r--r--target-alpha/translate.c33
2 files changed, 34 insertions, 1 deletions
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index e9b2b07571..bdd0ae6124 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -415,4 +415,6 @@ void cpu_loop_exit (void);
void pal_init (CPUState *env);
void call_pal (CPUState *env, int palcode);
+#define CPU_PC_FROM_TB(env, tb) env->pc = tb->pc
+
#endif /* !defined (__CPU_ALPHA_H__) */
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index a3991022e3..4a741573d7 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -43,6 +43,19 @@ struct DisasContext {
uint32_t amask;
};
+TCGv cpu_env;
+
+#include "gen-icount.h"
+
+void alpha_translate_init()
+{
+ static int done_init = 0;
+ if (done_init)
+ return;
+ cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
+ done_init = 1;
+}
+
static always_inline void gen_op_nop (void)
{
#if defined(GENERATE_NOP)
@@ -1970,6 +1983,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
uint16_t *gen_opc_end;
int j, lj = -1;
int ret;
+ int num_insns;
+ int max_insns;
pc_start = tb->pc;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
@@ -1981,6 +1996,12 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
ctx.mem_idx = ((env->ps >> 3) & 3);
ctx.pal_mode = env->ipr[IPR_EXC_ADDR] & 1;
#endif
+ num_insns = 0;
+ max_insns = tb->cflags & CF_COUNT_MASK;
+ if (max_insns == 0)
+ max_insns = CF_COUNT_MASK;
+
+ gen_icount_start();
for (ret = 0; ret == 0;) {
if (env->nb_breakpoints > 0) {
for(j = 0; j < env->nb_breakpoints; j++) {
@@ -1998,8 +2019,11 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
gen_opc_instr_start[lj++] = 0;
gen_opc_pc[lj] = ctx.pc;
gen_opc_instr_start[lj] = 1;
+ gen_opc_icount[lj] = num_insns;
}
}
+ if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+ gen_io_start();
#if defined ALPHA_DEBUG_DISAS
insn_count++;
if (logfile != NULL) {
@@ -2014,6 +2038,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
fprintf(logfile, "opcode %08x %d\n", insn, insn_count);
}
#endif
+ num_insns++;
ctx.pc += 4;
ret = translate_one(ctxp, insn);
if (ret != 0)
@@ -2022,7 +2047,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
* generation
*/
if (((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) ||
- (env->singlestep_enabled)) {
+ (env->singlestep_enabled) ||
+ num_insns >= max_insns) {
break;
}
#if defined (DO_SINGLE_STEP)
@@ -2035,8 +2061,11 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
#if defined (DO_TB_FLUSH)
gen_op_tb_flush();
#endif
+ if (tb->cflags & CF_LAST_IO)
+ gen_io_end();
/* Generate the return instruction */
tcg_gen_exit_tb(0);
+ gen_icount_end(tb, num_insns);
*gen_opc_ptr = INDEX_op_end;
if (search_pc) {
j = gen_opc_ptr - gen_opc_buf;
@@ -2045,6 +2074,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
gen_opc_instr_start[lj++] = 0;
} else {
tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
}
#if defined ALPHA_DEBUG_DISAS
if (loglevel & CPU_LOG_TB_CPU) {
@@ -2079,6 +2109,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
if (!env)
return NULL;
cpu_exec_init(env);
+ alpha_translate_init();
tlb_flush(env, 1);
/* XXX: should not be hardcoded */
env->implver = IMPLVER_2106x;