More TCG updates for CRIS
[qemu/qemu-JZ.git] / hw / mips_timer.c
blob5b172ea424271e4de15e1a69db6e3f4f823d6549
1 #include "hw.h"
2 #include "mips.h"
3 #include "qemu-timer.h"
5 #define TIMER_FREQ 100 * 1000 * 1000
7 void cpu_mips_irqctrl_init (void)
11 /* XXX: do not use a global */
12 uint32_t cpu_mips_get_random (CPUState *env)
14 static uint32_t seed = 0;
15 uint32_t idx;
16 seed = seed * 314159 + 1;
17 idx = (seed >> 16) % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
18 return idx;
21 /* MIPS R4K timer */
22 uint32_t cpu_mips_get_count (CPUState *env)
24 if (env->CP0_Cause & (1 << CP0Ca_DC))
25 return env->CP0_Count;
26 else
27 return env->CP0_Count +
28 (uint32_t)muldiv64(qemu_get_clock(vm_clock),
29 TIMER_FREQ, ticks_per_sec);
32 static void cpu_mips_timer_update(CPUState *env)
34 uint64_t now, next;
35 uint32_t wait;
37 now = qemu_get_clock(vm_clock);
38 wait = env->CP0_Compare - env->CP0_Count -
39 (uint32_t)muldiv64(now, TIMER_FREQ, ticks_per_sec);
40 next = now + muldiv64(wait, ticks_per_sec, TIMER_FREQ);
41 qemu_mod_timer(env->timer, next);
44 void cpu_mips_store_count (CPUState *env, uint32_t count)
46 if (env->CP0_Cause & (1 << CP0Ca_DC))
47 env->CP0_Count = count;
48 else {
49 /* Store new count register */
50 env->CP0_Count =
51 count - (uint32_t)muldiv64(qemu_get_clock(vm_clock),
52 TIMER_FREQ, ticks_per_sec);
53 /* Update timer timer */
54 cpu_mips_timer_update(env);
58 void cpu_mips_store_compare (CPUState *env, uint32_t value)
60 env->CP0_Compare = value;
61 if (!(env->CP0_Cause & (1 << CP0Ca_DC)))
62 cpu_mips_timer_update(env);
63 if (env->insn_flags & ISA_MIPS32R2)
64 env->CP0_Cause &= ~(1 << CP0Ca_TI);
65 qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
68 void cpu_mips_start_count(CPUState *env)
70 cpu_mips_store_count(env, env->CP0_Count);
73 void cpu_mips_stop_count(CPUState *env)
75 /* Store the current value */
76 env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock),
77 TIMER_FREQ, ticks_per_sec);
80 static void mips_timer_cb (void *opaque)
82 CPUState *env;
84 env = opaque;
85 #if 0
86 if (logfile) {
87 fprintf(logfile, "%s\n", __func__);
89 #endif
91 if (env->CP0_Cause & (1 << CP0Ca_DC))
92 return;
94 cpu_mips_timer_update(env);
95 if (env->insn_flags & ISA_MIPS32R2)
96 env->CP0_Cause |= 1 << CP0Ca_TI;
97 qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
100 void cpu_mips_clock_init (CPUState *env)
102 env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
103 env->CP0_Compare = 0;
104 cpu_mips_store_count(env, 1);