Statistics
| Branch: | Revision:

root / hw / mips_timer.c @ 04088adb

History | View | Annotate | Download (3 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
/* XXX: do not use a global */
8 e16fe40c ths
uint32_t cpu_mips_get_random (CPUState *env)
9 e16fe40c ths
{
10 59d94130 aurel32
    static uint32_t lfsr = 1;
11 59d94130 aurel32
    static uint32_t prev_idx = 0;
12 e16fe40c ths
    uint32_t idx;
13 59d94130 aurel32
    /* Don't return same value twice, so get another value */
14 59d94130 aurel32
    do {
15 59d94130 aurel32
        lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u);
16 59d94130 aurel32
        idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
17 59d94130 aurel32
    } while (idx == prev_idx);
18 59d94130 aurel32
    prev_idx = idx;
19 e16fe40c ths
    return idx;
20 e16fe40c ths
}
21 e16fe40c ths
22 e16fe40c ths
/* MIPS R4K timer */
23 e16fe40c ths
uint32_t cpu_mips_get_count (CPUState *env)
24 e16fe40c ths
{
25 42532189 ths
    if (env->CP0_Cause & (1 << CP0Ca_DC))
26 42532189 ths
        return env->CP0_Count;
27 42532189 ths
    else
28 42532189 ths
        return env->CP0_Count +
29 42532189 ths
            (uint32_t)muldiv64(qemu_get_clock(vm_clock),
30 6ee093c9 Juan Quintela
                               TIMER_FREQ, get_ticks_per_sec());
31 e16fe40c ths
}
32 e16fe40c ths
33 ea86e4e6 aurel32
static void cpu_mips_timer_update(CPUState *env)
34 e16fe40c ths
{
35 e16fe40c ths
    uint64_t now, next;
36 ea86e4e6 aurel32
    uint32_t wait;
37 39d51eb8 ths
38 e16fe40c ths
    now = qemu_get_clock(vm_clock);
39 ea86e4e6 aurel32
    wait = env->CP0_Compare - env->CP0_Count -
40 6ee093c9 Juan Quintela
            (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
41 6ee093c9 Juan Quintela
    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
42 e16fe40c ths
    qemu_mod_timer(env->timer, next);
43 e16fe40c ths
}
44 e16fe40c ths
45 ea86e4e6 aurel32
void cpu_mips_store_count (CPUState *env, uint32_t count)
46 e16fe40c ths
{
47 3529b538 ths
    if (env->CP0_Cause & (1 << CP0Ca_DC))
48 ea86e4e6 aurel32
        env->CP0_Count = count;
49 ea86e4e6 aurel32
    else {
50 ea86e4e6 aurel32
        /* Store new count register */
51 ea86e4e6 aurel32
        env->CP0_Count =
52 ea86e4e6 aurel32
            count - (uint32_t)muldiv64(qemu_get_clock(vm_clock),
53 6ee093c9 Juan Quintela
                                       TIMER_FREQ, get_ticks_per_sec());
54 ea86e4e6 aurel32
        /* Update timer timer */
55 ea86e4e6 aurel32
        cpu_mips_timer_update(env);
56 ea86e4e6 aurel32
    }
57 e16fe40c ths
}
58 e16fe40c ths
59 e16fe40c ths
void cpu_mips_store_compare (CPUState *env, uint32_t value)
60 e16fe40c ths
{
61 3529b538 ths
    env->CP0_Compare = value;
62 ea86e4e6 aurel32
    if (!(env->CP0_Cause & (1 << CP0Ca_DC)))
63 ea86e4e6 aurel32
        cpu_mips_timer_update(env);
64 ea86e4e6 aurel32
    if (env->insn_flags & ISA_MIPS32R2)
65 39d51eb8 ths
        env->CP0_Cause &= ~(1 << CP0Ca_TI);
66 42532189 ths
    qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
67 42532189 ths
}
68 42532189 ths
69 42532189 ths
void cpu_mips_start_count(CPUState *env)
70 42532189 ths
{
71 42532189 ths
    cpu_mips_store_count(env, env->CP0_Count);
72 42532189 ths
}
73 42532189 ths
74 42532189 ths
void cpu_mips_stop_count(CPUState *env)
75 42532189 ths
{
76 42532189 ths
    /* Store the current value */
77 42532189 ths
    env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock),
78 6ee093c9 Juan Quintela
                                         TIMER_FREQ, get_ticks_per_sec());
79 e16fe40c ths
}
80 e16fe40c ths
81 e16fe40c ths
static void mips_timer_cb (void *opaque)
82 e16fe40c ths
{
83 e16fe40c ths
    CPUState *env;
84 e16fe40c ths
85 e16fe40c ths
    env = opaque;
86 e16fe40c ths
#if 0
87 93fcfe39 aliguori
    qemu_log("%s\n", __func__);
88 e16fe40c ths
#endif
89 42532189 ths
90 42532189 ths
    if (env->CP0_Cause & (1 << CP0Ca_DC))
91 42532189 ths
        return;
92 42532189 ths
93 2e70f6ef pbrook
    /* ??? This callback should occur when the counter is exactly equal to
94 2e70f6ef pbrook
       the comparator value.  Offset the count by one to avoid immediately
95 2e70f6ef pbrook
       retriggering the callback before any virtual time has passed.  */
96 2e70f6ef pbrook
    env->CP0_Count++;
97 ea86e4e6 aurel32
    cpu_mips_timer_update(env);
98 2e70f6ef pbrook
    env->CP0_Count--;
99 ea86e4e6 aurel32
    if (env->insn_flags & ISA_MIPS32R2)
100 39d51eb8 ths
        env->CP0_Cause |= 1 << CP0Ca_TI;
101 42532189 ths
    qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
102 e16fe40c ths
}
103 e16fe40c ths
104 e16fe40c ths
void cpu_mips_clock_init (CPUState *env)
105 e16fe40c ths
{
106 e16fe40c ths
    env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
107 e16fe40c ths
    env->CP0_Compare = 0;
108 ea86e4e6 aurel32
    cpu_mips_store_count(env, 1);
109 e16fe40c ths
}