aboutsummaryrefslogtreecommitdiff
path: root/target-mips
diff options
context:
space:
mode:
Diffstat (limited to 'target-mips')
-rw-r--r--target-mips/cpu.h6
-rw-r--r--target-mips/translate.c51
2 files changed, 57 insertions, 0 deletions
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 78851ed932..8e21f6b4a8 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -572,4 +572,10 @@ CPUMIPSState *cpu_mips_init(const char *cpu_model);
uint32_t cpu_mips_get_clock (void);
int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
+#define CPU_PC_FROM_TB(env, tb) do { \
+ env->active_tc.PC = tb->pc; \
+ env->hflags &= ~MIPS_HFLAG_BMASK; \
+ env->hflags |= tb->flags & MIPS_HFLAG_BMASK; \
+ } while (0)
+
#endif /* !defined (__MIPS_CPU_H__) */
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 9c97b9c486..67fbbedf7e 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -428,6 +428,8 @@ static TCGv cpu_env, current_fpu;
/* FPU TNs, global for now. */
static TCGv fpu32_T[3], fpu64_T[3], fpu32h_T[3];
+#include "gen-icount.h"
+
static inline void tcg_gen_helper_0_i(void *func, TCGv arg)
{
TCGv tmp = tcg_const_i32(arg);
@@ -3061,7 +3063,14 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int se
case 9:
switch (sel) {
case 0:
+ /* Mark as an IO operation because we read the time. */
+ if (use_icount)
+ gen_io_start();
tcg_gen_helper_1_0(do_mfc0_count, t0);
+ if (use_icount) {
+ gen_io_end();
+ ctx->bstate = BS_STOP;
+ }
rn = "Count";
break;
/* 6,7 are implementation dependent */
@@ -3422,6 +3431,9 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int se
if (sel != 0)
check_insn(env, ctx, ISA_MIPS32);
+ if (use_icount)
+ gen_io_start();
+
switch (reg) {
case 0:
switch (sel) {
@@ -4004,6 +4016,11 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int se
rn, reg, sel);
}
#endif
+ /* For simplicitly assume that all writes can cause interrupts. */
+ if (use_icount) {
+ gen_io_end();
+ ctx->bstate = BS_STOP;
+ }
return;
die:
@@ -4238,7 +4255,14 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int s
case 9:
switch (sel) {
case 0:
+ /* Mark as an IO operation because we read the time. */
+ if (use_icount)
+ gen_io_start();
tcg_gen_helper_1_0(do_mfc0_count, t0);
+ if (use_icount) {
+ gen_io_end();
+ ctx->bstate = BS_STOP;
+ }
rn = "Count";
break;
/* 6,7 are implementation dependent */
@@ -4591,6 +4615,9 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int s
if (sel != 0)
check_insn(env, ctx, ISA_MIPS64);
+ if (use_icount)
+ gen_io_start();
+
switch (reg) {
case 0:
switch (sel) {
@@ -5161,6 +5188,11 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv t0, int reg, int s
}
#endif
tcg_temp_free(t0);
+ /* For simplicitly assume that all writes can cause interrupts. */
+ if (use_icount) {
+ gen_io_end();
+ ctx->bstate = BS_STOP;
+ }
return;
die:
@@ -7760,6 +7792,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
ctx->hflags &= ~MIPS_HFLAG_BMASK;
ctx->bstate = BS_BRANCH;
save_cpu_state(ctx, 0);
+ /* FIXME: Need to clear can_do_io. */
switch (hflags) {
case MIPS_HFLAG_B:
/* unconditional branch */
@@ -7807,6 +7840,8 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
target_ulong pc_start;
uint16_t *gen_opc_end;
int j, lj = -1;
+ int num_insns;
+ int max_insns;
if (search_pc && loglevel)
fprintf (logfile, "search pc %d\n", search_pc);
@@ -7826,6 +7861,11 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
#else
ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
#endif
+ num_insns = 0;
+ num_insns = 0;
+ max_insns = tb->cflags & CF_COUNT_MASK;
+ if (max_insns == 0)
+ max_insns = CF_COUNT_MASK;
#ifdef DEBUG_DISAS
if (loglevel & CPU_LOG_TB_CPU) {
fprintf(logfile, "------------------------------------------------\n");
@@ -7838,6 +7878,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
tb, ctx.mem_idx, ctx.hflags);
#endif
+ gen_icount_start();
while (ctx.bstate == BS_NONE) {
if (env->nb_breakpoints > 0) {
for(j = 0; j < env->nb_breakpoints; j++) {
@@ -7863,10 +7904,14 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
gen_opc_pc[lj] = ctx.pc;
gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
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();
ctx.opcode = ldl_code(ctx.pc);
decode_opc(env, &ctx);
ctx.pc += 4;
+ num_insns++;
if (env->singlestep_enabled)
break;
@@ -7880,10 +7925,14 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
if (gen_opc_ptr >= gen_opc_end)
break;
+ if (num_insns >= max_insns)
+ break;
#if defined (MIPS_SINGLE_STEP)
break;
#endif
}
+ if (tb->cflags & CF_LAST_IO)
+ gen_io_end();
if (env->singlestep_enabled) {
save_cpu_state(&ctx, ctx.bstate == BS_NONE);
tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
@@ -7907,6 +7956,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
}
}
done_generating:
+ gen_icount_end(tb, num_insns);
*gen_opc_ptr = INDEX_op_end;
if (search_pc) {
j = gen_opc_ptr - gen_opc_buf;
@@ -7915,6 +7965,7 @@ done_generating:
gen_opc_instr_start[lj++] = 0;
} else {
tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
}
#ifdef DEBUG_DISAS
#if defined MIPS_DEBUG_DISAS