Commit ea86e4e6007af70a5e23c4f93eea9d0732e3bcb0

Authored by aurel32
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 }
... ...