Statistics
| Branch: | Revision:

root / hw / mips_timer.c @ 731ba0ce

History | View | Annotate | Download (2.6 kB)

1 87ecb68b pbrook
#include "hw.h"
2 87ecb68b pbrook
#include "mips.h"
3 87ecb68b pbrook
#include "qemu-timer.h"
4 e16fe40c ths
5 ea86e4e6 aurel32
#define TIMER_FREQ        100 * 1000 * 1000
6 ea86e4e6 aurel32
7 e16fe40c ths
void cpu_mips_irqctrl_init (void)
8 e16fe40c ths
{
9 e16fe40c ths
}
10 e16fe40c ths
11 e16fe40c ths
/* XXX: do not use a global */
12 e16fe40c ths
uint32_t cpu_mips_get_random (CPUState *env)
13 e16fe40c ths
{
14 e16fe40c ths
    static uint32_t seed = 0;
15 e16fe40c ths
    uint32_t idx;
16 e16fe40c ths
    seed = seed * 314159 + 1;
17 ead9360e ths
    idx = (seed >> 16) % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
18 e16fe40c ths
    return idx;
19 e16fe40c ths
}
20 e16fe40c ths
21 e16fe40c ths
/* MIPS R4K timer */
22 e16fe40c ths
uint32_t cpu_mips_get_count (CPUState *env)
23 e16fe40c ths
{
24 42532189 ths
    if (env->CP0_Cause & (1 << CP0Ca_DC))
25 42532189 ths
        return env->CP0_Count;
26 42532189 ths
    else
27 42532189 ths
        return env->CP0_Count +
28 42532189 ths
            (uint32_t)muldiv64(qemu_get_clock(vm_clock),
29 ea86e4e6 aurel32
                               TIMER_FREQ, ticks_per_sec);
30 e16fe40c ths
}
31 e16fe40c ths
32 ea86e4e6 aurel32
static void cpu_mips_timer_update(CPUState *env)
33 e16fe40c ths
{
34 e16fe40c ths
    uint64_t now, next;
35 ea86e4e6 aurel32
    uint32_t wait;
36 39d51eb8 ths
37 e16fe40c ths
    now = qemu_get_clock(vm_clock);
38 ea86e4e6 aurel32
    wait = env->CP0_Compare - env->CP0_Count -
39 ea86e4e6 aurel32
            (uint32_t)muldiv64(now, TIMER_FREQ, ticks_per_sec);
40 ea86e4e6 aurel32
    next = now + muldiv64(wait, ticks_per_sec, TIMER_FREQ);
41 e16fe40c ths
    qemu_mod_timer(env->timer, next);
42 e16fe40c ths
}
43 e16fe40c ths
44 ea86e4e6 aurel32
void cpu_mips_store_count (CPUState *env, uint32_t count)
45 e16fe40c ths
{
46 3529b538 ths
    if (env->CP0_Cause & (1 << CP0Ca_DC))
47 ea86e4e6 aurel32
        env->CP0_Count = count;
48 ea86e4e6 aurel32
    else {
49 ea86e4e6 aurel32
        /* Store new count register */
50 ea86e4e6 aurel32
        env->CP0_Count =
51 ea86e4e6 aurel32
            count - (uint32_t)muldiv64(qemu_get_clock(vm_clock),
52 ea86e4e6 aurel32
                                       TIMER_FREQ, ticks_per_sec);
53 ea86e4e6 aurel32
        /* Update timer timer */
54 ea86e4e6 aurel32
        cpu_mips_timer_update(env);
55 ea86e4e6 aurel32
    }
56 e16fe40c ths
}
57 e16fe40c ths
58 e16fe40c ths
void cpu_mips_store_compare (CPUState *env, uint32_t value)
59 e16fe40c ths
{
60 3529b538 ths
    env->CP0_Compare = value;
61 ea86e4e6 aurel32
    if (!(env->CP0_Cause & (1 << CP0Ca_DC)))
62 ea86e4e6 aurel32
        cpu_mips_timer_update(env);
63 ea86e4e6 aurel32
    if (env->insn_flags & ISA_MIPS32R2)
64 39d51eb8 ths
        env->CP0_Cause &= ~(1 << CP0Ca_TI);
65 42532189 ths
    qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
66 42532189 ths
}
67 42532189 ths
68 42532189 ths
void cpu_mips_start_count(CPUState *env)
69 42532189 ths
{
70 42532189 ths
    cpu_mips_store_count(env, env->CP0_Count);
71 42532189 ths
}
72 42532189 ths
73 42532189 ths
void cpu_mips_stop_count(CPUState *env)
74 42532189 ths
{
75 42532189 ths
    /* Store the current value */
76 42532189 ths
    env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock),
77 ea86e4e6 aurel32
                                         TIMER_FREQ, ticks_per_sec);
78 e16fe40c ths
}
79 e16fe40c ths
80 e16fe40c ths
static void mips_timer_cb (void *opaque)
81 e16fe40c ths
{
82 e16fe40c ths
    CPUState *env;
83 e16fe40c ths
84 e16fe40c ths
    env = opaque;
85 e16fe40c ths
#if 0
86 e16fe40c ths
    if (logfile) {
87 e16fe40c ths
        fprintf(logfile, "%s\n", __func__);
88 e16fe40c ths
    }
89 e16fe40c ths
#endif
90 42532189 ths
91 42532189 ths
    if (env->CP0_Cause & (1 << CP0Ca_DC))
92 42532189 ths
        return;
93 42532189 ths
94 ea86e4e6 aurel32
    cpu_mips_timer_update(env);
95 ea86e4e6 aurel32
    if (env->insn_flags & ISA_MIPS32R2)
96 39d51eb8 ths
        env->CP0_Cause |= 1 << CP0Ca_TI;
97 42532189 ths
    qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
98 e16fe40c ths
}
99 e16fe40c ths
100 e16fe40c ths
void cpu_mips_clock_init (CPUState *env)
101 e16fe40c ths
{
102 e16fe40c ths
    env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
103 e16fe40c ths
    env->CP0_Compare = 0;
104 ea86e4e6 aurel32
    cpu_mips_store_count(env, 1);
105 e16fe40c ths
}