Commit ea86e4e6007af70a5e23c4f93eea9d0732e3bcb0
1 parent
1570de2d
Optimize MIPS timer read/write functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4190 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
25 additions
and
31 deletions
hw/mips_timer.c
... | ... | @@ -2,6 +2,8 @@ |
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,49 +26,41 @@ uint32_t cpu_mips_get_count (CPUState *env) |
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,7 +74,7 @@ void cpu_mips_stop_count(CPUState *env) |
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,8 +91,8 @@ 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,5 +101,5 @@ void cpu_mips_clock_init (CPUState *env) |
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 | } | ... | ... |