Revision ea86e4e6
b/hw/mips_timer.c | ||
---|---|---|
2 | 2 |
#include "mips.h" |
3 | 3 |
#include "qemu-timer.h" |
4 | 4 |
|
5 |
#define TIMER_FREQ 100 * 1000 * 1000 |
|
6 |
|
|
5 | 7 |
void cpu_mips_irqctrl_init (void) |
6 | 8 |
{ |
7 | 9 |
} |
... | ... | |
24 | 26 |
else |
25 | 27 |
return env->CP0_Count + |
26 | 28 |
(uint32_t)muldiv64(qemu_get_clock(vm_clock), |
27 |
100 * 1000 * 1000, ticks_per_sec);
|
|
29 |
TIMER_FREQ, ticks_per_sec);
|
|
28 | 30 |
} |
29 | 31 |
|
30 |
void cpu_mips_store_count (CPUState *env, uint32_t count)
|
|
32 |
static void cpu_mips_timer_update(CPUState *env)
|
|
31 | 33 |
{ |
32 | 34 |
uint64_t now, next; |
33 |
uint32_t tmp; |
|
34 |
uint32_t compare = env->CP0_Compare; |
|
35 |
uint32_t wait; |
|
35 | 36 |
|
36 |
tmp = count; |
|
37 |
if (count == compare) |
|
38 |
tmp++; |
|
39 | 37 |
now = qemu_get_clock(vm_clock); |
40 |
next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000); |
|
41 |
if (next == now) |
|
42 |
next++; |
|
43 |
#if 0 |
|
44 |
if (logfile) { |
|
45 |
fprintf(logfile, "%s: 0x%08" PRIx64 " %08x %08x => 0x%08" PRIx64 "\n", |
|
46 |
__func__, now, count, compare, next - now); |
|
47 |
} |
|
48 |
#endif |
|
49 |
/* Store new count and compare registers */ |
|
50 |
env->CP0_Compare = compare; |
|
51 |
env->CP0_Count = |
|
52 |
count - (uint32_t)muldiv64(now, 100 * 1000 * 1000, ticks_per_sec); |
|
53 |
/* Adjust timer */ |
|
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); |
|
54 | 41 |
qemu_mod_timer(env->timer, next); |
55 | 42 |
} |
56 | 43 |
|
57 |
static void cpu_mips_update_count (CPUState *env, uint32_t count)
|
|
44 |
void cpu_mips_store_count (CPUState *env, uint32_t count)
|
|
58 | 45 |
{ |
59 | 46 |
if (env->CP0_Cause & (1 << CP0Ca_DC)) |
60 |
return; |
|
61 |
|
|
62 |
cpu_mips_store_count(env, count); |
|
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 |
} |
|
63 | 56 |
} |
64 | 57 |
|
65 | 58 |
void cpu_mips_store_compare (CPUState *env, uint32_t value) |
66 | 59 |
{ |
67 | 60 |
env->CP0_Compare = value; |
68 |
cpu_mips_update_count(env, cpu_mips_get_count(env)); |
|
69 |
if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) |
|
61 |
if (!(env->CP0_Cause & (1 << CP0Ca_DC))) |
|
62 |
cpu_mips_timer_update(env); |
|
63 |
if (env->insn_flags & ISA_MIPS32R2) |
|
70 | 64 |
env->CP0_Cause &= ~(1 << CP0Ca_TI); |
71 | 65 |
qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); |
72 | 66 |
} |
... | ... | |
80 | 74 |
{ |
81 | 75 |
/* Store the current value */ |
82 | 76 |
env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock), |
83 |
100 * 1000 * 1000, ticks_per_sec);
|
|
77 |
TIMER_FREQ, ticks_per_sec);
|
|
84 | 78 |
} |
85 | 79 |
|
86 | 80 |
static void mips_timer_cb (void *opaque) |
... | ... | |
97 | 91 |
if (env->CP0_Cause & (1 << CP0Ca_DC)) |
98 | 92 |
return; |
99 | 93 |
|
100 |
cpu_mips_update_count(env, cpu_mips_get_count(env));
|
|
101 |
if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
|
|
94 |
cpu_mips_timer_update(env);
|
|
95 |
if (env->insn_flags & ISA_MIPS32R2)
|
|
102 | 96 |
env->CP0_Cause |= 1 << CP0Ca_TI; |
103 | 97 |
qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); |
104 | 98 |
} |
... | ... | |
107 | 101 |
{ |
108 | 102 |
env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env); |
109 | 103 |
env->CP0_Compare = 0; |
110 |
cpu_mips_update_count(env, 1);
|
|
104 |
cpu_mips_store_count(env, 1);
|
|
111 | 105 |
} |
Also available in: Unified diff