summaryrefslogtreecommitdiffstats
path: root/target/mips/cp0_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/mips/cp0_timer.c')
-rw-r--r--target/mips/cp0_timer.c51
1 files changed, 13 insertions, 38 deletions
diff --git a/target/mips/cp0_timer.c b/target/mips/cp0_timer.c
index bd7efb152d..5ec0d6249e 100644
--- a/target/mips/cp0_timer.c
+++ b/target/mips/cp0_timer.c
@@ -27,43 +27,17 @@
#include "sysemu/kvm.h"
#include "internal.h"
-#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */
-
-/* XXX: do not use a global */
-uint32_t cpu_mips_get_random(CPUMIPSState *env)
-{
- static uint32_t seed = 1;
- static uint32_t prev_idx = 0;
- uint32_t idx;
- uint32_t nb_rand_tlb = env->tlb->nb_tlb - env->CP0_Wired;
-
- if (nb_rand_tlb == 1) {
- return env->tlb->nb_tlb - 1;
- }
-
- /* Don't return same value twice, so get another value */
- do {
- /*
- * Use a simple algorithm of Linear Congruential Generator
- * from ISO/IEC 9899 standard.
- */
- seed = 1103515245 * seed + 12345;
- idx = (seed >> 16) % nb_rand_tlb + env->CP0_Wired;
- } while (idx == prev_idx);
- prev_idx = idx;
- return idx;
-}
-
/* MIPS R4K timer */
static void cpu_mips_timer_update(CPUMIPSState *env)
{
- uint64_t now, next;
+ uint64_t now_ns, next_ns;
uint32_t wait;
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- wait = env->CP0_Compare - env->CP0_Count - (uint32_t)(now / TIMER_PERIOD);
- next = now + (uint64_t)wait * TIMER_PERIOD;
- timer_mod(env->timer, next);
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ wait = env->CP0_Compare - env->CP0_Count -
+ (uint32_t)(now_ns / env->cp0_count_ns);
+ next_ns = now_ns + (uint64_t)wait * env->cp0_count_ns;
+ timer_mod(env->timer, next_ns);
}
/* Expire the timer. */
@@ -81,16 +55,16 @@ uint32_t cpu_mips_get_count(CPUMIPSState *env)
if (env->CP0_Cause & (1 << CP0Ca_DC)) {
return env->CP0_Count;
} else {
- uint64_t now;
+ uint64_t now_ns;
- now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ now_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (timer_pending(env->timer)
- && timer_expired(env->timer, now)) {
+ && timer_expired(env->timer, now_ns)) {
/* The timer has already expired. */
cpu_mips_timer_expire(env);
}
- return env->CP0_Count + (uint32_t)(now / TIMER_PERIOD);
+ return env->CP0_Count + (uint32_t)(now_ns / env->cp0_count_ns);
}
}
@@ -106,7 +80,8 @@ void cpu_mips_store_count(CPUMIPSState *env, uint32_t count)
} else {
/* Store new count register */
env->CP0_Count = count -
- (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD);
+ (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
+ env->cp0_count_ns);
/* Update timer timer */
cpu_mips_timer_update(env);
}
@@ -133,7 +108,7 @@ void cpu_mips_stop_count(CPUMIPSState *env)
{
/* Store the current value */
env->CP0_Count += (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
- TIMER_PERIOD);
+ env->cp0_count_ns);
}
static void mips_timer_cb(void *opaque)