Skip to content

Commit

Permalink
More accurately emulate MIPS Count register.
Browse files Browse the repository at this point in the history
The MIPS Count register is incremented every 2 cycles, not every
cycle (according to sys/mips/include/clock.h).

Also, instead of using muldiv64() to convert from ticks to nanoseconds:
	y = muldiv64(x, get_ticks_per_sec(), TIMER_FREQ)
where y = number of system ticks and x = device ticks we can just do:
	y = x * 10ns (for 100Mhz clock)
  • Loading branch information
staceyson committed May 15, 2017
1 parent 12871eb commit b79c3d9
Showing 1 changed file with 10 additions and 11 deletions.
21 changes: 10 additions & 11 deletions hw/mips/cputimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
#include "qemu/timer.h"
#include "sysemu/kvm.h"

#define TIMER_FREQ 100 * 1000 * 1000
#define CLOCK_PERIOD 10 /* 10 ns period for 100 Mhz frequency */
#define CYCLES_PER_CNT 2
#define TIMER_PERIOD (CYCLES_PER_CNT * CLOCK_PERIOD)

/* XXX: do not use a global */
uint32_t cpu_mips_get_random (CPUMIPSState *env)
Expand All @@ -49,9 +51,8 @@ static void cpu_mips_timer_update(CPUMIPSState *env)
uint32_t wait;

now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
wait = env->CP0_Compare - env->CP0_Count -
(uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
wait = env->CP0_Compare - env->CP0_Count - (uint32_t)(now / TIMER_PERIOD);
next = now + (uint64_t)wait * CLOCK_PERIOD;
timer_mod(env->timer, next);
}

Expand Down Expand Up @@ -79,8 +80,7 @@ uint32_t cpu_mips_get_count (CPUMIPSState *env)
cpu_mips_timer_expire(env);
}

return env->CP0_Count +
(uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
return env->CP0_Count + (uint32_t)(now / TIMER_PERIOD);
}
}

Expand All @@ -95,9 +95,8 @@ void cpu_mips_store_count (CPUMIPSState *env, uint32_t count)
env->CP0_Count = count;
else {
/* Store new count register */
env->CP0_Count =
count - (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
TIMER_FREQ, get_ticks_per_sec());
env->CP0_Count = count -
(uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD);
/* Update timer timer */
cpu_mips_timer_update(env);
}
Expand All @@ -121,8 +120,8 @@ void cpu_mips_start_count(CPUMIPSState *env)
void cpu_mips_stop_count(CPUMIPSState *env)
{
/* Store the current value */
env->CP0_Count += (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
TIMER_FREQ, get_ticks_per_sec());
env->CP0_Count += (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
TIMER_PERIOD);
}

static void mips_timer_cb (void *opaque)
Expand Down

1 comment on commit b79c3d9

@trasz
Copy link
Contributor

@trasz trasz commented on b79c3d9 Oct 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks the time in two different ways: #55 and #54.

Please sign in to comment.