Index: hw/mips_timer.c =================================================================== RCS file: /sources/qemu/qemu/hw/mips_timer.c,v retrieving revision 1.8 diff -u -d -p -r1.8 mips_timer.c --- hw/mips_timer.c 25 Sep 2007 16:53:15 -0000 1.8 +++ hw/mips_timer.c 2 Oct 2007 10:20:37 -0000 @@ -1,5 +1,7 @@ #include "vl.h" +#define TIMER_FREQ 100 * 1000 * 1000 + void cpu_mips_irqctrl_init (void) { } @@ -22,49 +24,41 @@ uint32_t cpu_mips_get_count (CPUState *e else return env->CP0_Count + (uint32_t)muldiv64(qemu_get_clock(vm_clock), - 100 * 1000 * 1000, ticks_per_sec); + TIMER_FREQ, ticks_per_sec); } -void cpu_mips_store_count (CPUState *env, uint32_t count) +static void cpu_mips_timer_update(CPUState *env) { uint64_t now, next; - uint32_t tmp; - uint32_t compare = env->CP0_Compare; + uint32_t wait; - tmp = count; - if (count == compare) - tmp++; now = qemu_get_clock(vm_clock); - next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000); - if (next == now) - next++; -#if 0 - if (logfile) { - fprintf(logfile, "%s: 0x%08" PRIx64 " %08x %08x => 0x%08" PRIx64 "\n", - __func__, now, count, compare, next - now); - } -#endif - /* Store new count and compare registers */ - env->CP0_Compare = compare; - env->CP0_Count = - count - (uint32_t)muldiv64(now, 100 * 1000 * 1000, ticks_per_sec); - /* Adjust timer */ + wait = env->CP0_Compare - env->CP0_Count - + (uint32_t)muldiv64(now, TIMER_FREQ, ticks_per_sec); + next = now + muldiv64(wait, ticks_per_sec, TIMER_FREQ); qemu_mod_timer(env->timer, next); } -static void cpu_mips_update_count (CPUState *env, uint32_t count) +void cpu_mips_store_count (CPUState *env, uint32_t count) { if (env->CP0_Cause & (1 << CP0Ca_DC)) - return; - - cpu_mips_store_count(env, count); + env->CP0_Count = count; + else { + /* Store new count register */ + env->CP0_Count = + count - (uint32_t)muldiv64(qemu_get_clock(vm_clock), + TIMER_FREQ, ticks_per_sec); + /* Update timer timer */ + cpu_mips_timer_update(env); + } } void cpu_mips_store_compare (CPUState *env, uint32_t value) { env->CP0_Compare = value; - cpu_mips_update_count(env, cpu_mips_get_count(env)); - if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) + if (!(env->CP0_Cause & (1 << CP0Ca_DC))) + cpu_mips_timer_update(env); + if (env->insn_flags & ISA_MIPS32R2) env->CP0_Cause &= ~(1 << CP0Ca_TI); qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); } @@ -78,7 +72,7 @@ void cpu_mips_stop_count(CPUState *env) { /* Store the current value */ env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock), - 100 * 1000 * 1000, ticks_per_sec); + TIMER_FREQ, ticks_per_sec); } static void mips_timer_cb (void *opaque) @@ -95,8 +89,8 @@ static void mips_timer_cb (void *opaque) if (env->CP0_Cause & (1 << CP0Ca_DC)) return; - cpu_mips_update_count(env, cpu_mips_get_count(env)); - if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) + cpu_mips_timer_update(env); + if (env->insn_flags & ISA_MIPS32R2) env->CP0_Cause |= 1 << CP0Ca_TI; qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); } @@ -105,5 +99,5 @@ void cpu_mips_clock_init (CPUState *env) { env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env); env->CP0_Compare = 0; - cpu_mips_update_count(env, 1); + cpu_mips_store_count(env, 1); } Index: target-mips/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/translate.c,v retrieving revision 1.104 diff -u -d -p -r1.104 translate.c --- target-mips/translate.c 30 Sep 2007 01:58:33 -0000 1.104 +++ target-mips/translate.c 2 Oct 2007 10:20:38 -0000 @@ -2763,8 +2763,6 @@ static void gen_mtc0 (CPUState *env, Dis default: goto die; } - /* Stop translation as we may have switched the execution mode */ - ctx->bstate = BS_STOP; break; case 12: switch (sel) {