Remove most uses of phys_ram_base (initial patch by Ian Jackson)
[qemu] / hw / mips_timer.c
1 #include "hw.h"
2 #include "mips.h"
3 #include "qemu-timer.h"
4
5 #define TIMER_FREQ      100 * 1000 * 1000
6
7 void cpu_mips_irqctrl_init (void)
8 {
9 }
10
11 /* XXX: do not use a global */
12 uint32_t cpu_mips_get_random (CPUState *env)
13 {
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;
19 }
20
21 /* MIPS R4K timer */
22 uint32_t cpu_mips_get_count (CPUState *env)
23 {
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);
30 }
31
32 static void cpu_mips_timer_update(CPUState *env)
33 {
34     uint64_t now, next;
35     uint32_t wait;
36
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);
42 }
43
44 void cpu_mips_store_count (CPUState *env, uint32_t count)
45 {
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);
55     }
56 }
57
58 void cpu_mips_store_compare (CPUState *env, uint32_t value)
59 {
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]);
66 }
67
68 void cpu_mips_start_count(CPUState *env)
69 {
70     cpu_mips_store_count(env, env->CP0_Count);
71 }
72
73 void cpu_mips_stop_count(CPUState *env)
74 {
75     /* Store the current value */
76     env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock),
77                                          TIMER_FREQ, ticks_per_sec);
78 }
79
80 static void mips_timer_cb (void *opaque)
81 {
82     CPUState *env;
83
84     env = opaque;
85 #if 0
86     if (logfile) {
87         fprintf(logfile, "%s\n", __func__);
88     }
89 #endif
90
91     if (env->CP0_Cause & (1 << CP0Ca_DC))
92         return;
93
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]);
98 }
99
100 void cpu_mips_clock_init (CPUState *env)
101 {
102     env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
103     env->CP0_Compare = 0;
104     cpu_mips_store_count(env, 1);
105 }