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,6 +2,8 @@ | ||
| 2 | #include "mips.h" | 2 | #include "mips.h" |
| 3 | #include "qemu-timer.h" | 3 | #include "qemu-timer.h" |
| 4 | 4 | ||
| 5 | +#define TIMER_FREQ 100 * 1000 * 1000 | ||
| 6 | + | ||
| 5 | void cpu_mips_irqctrl_init (void) | 7 | void cpu_mips_irqctrl_init (void) |
| 6 | { | 8 | { |
| 7 | } | 9 | } |
| @@ -24,49 +26,41 @@ uint32_t cpu_mips_get_count (CPUState *env) | @@ -24,49 +26,41 @@ uint32_t cpu_mips_get_count (CPUState *env) | ||
| 24 | else | 26 | else |
| 25 | return env->CP0_Count + | 27 | return env->CP0_Count + |
| 26 | (uint32_t)muldiv64(qemu_get_clock(vm_clock), | 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 | uint64_t now, next; | 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 | now = qemu_get_clock(vm_clock); | 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 | qemu_mod_timer(env->timer, next); | 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 | if (env->CP0_Cause & (1 << CP0Ca_DC)) | 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 | void cpu_mips_store_compare (CPUState *env, uint32_t value) | 58 | void cpu_mips_store_compare (CPUState *env, uint32_t value) |
| 66 | { | 59 | { |
| 67 | env->CP0_Compare = value; | 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 | env->CP0_Cause &= ~(1 << CP0Ca_TI); | 64 | env->CP0_Cause &= ~(1 << CP0Ca_TI); |
| 71 | qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); | 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,7 +74,7 @@ void cpu_mips_stop_count(CPUState *env) | ||
| 80 | { | 74 | { |
| 81 | /* Store the current value */ | 75 | /* Store the current value */ |
| 82 | env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock), | 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 | static void mips_timer_cb (void *opaque) | 80 | static void mips_timer_cb (void *opaque) |
| @@ -97,8 +91,8 @@ static void mips_timer_cb (void *opaque) | @@ -97,8 +91,8 @@ static void mips_timer_cb (void *opaque) | ||
| 97 | if (env->CP0_Cause & (1 << CP0Ca_DC)) | 91 | if (env->CP0_Cause & (1 << CP0Ca_DC)) |
| 98 | return; | 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 | env->CP0_Cause |= 1 << CP0Ca_TI; | 96 | env->CP0_Cause |= 1 << CP0Ca_TI; |
| 103 | qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); | 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,5 +101,5 @@ void cpu_mips_clock_init (CPUState *env) | ||
| 107 | { | 101 | { |
| 108 | env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env); | 102 | env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env); |
| 109 | env->CP0_Compare = 0; | 103 | env->CP0_Compare = 0; |
| 110 | - cpu_mips_update_count(env, 1); | 104 | + cpu_mips_store_count(env, 1); |
| 111 | } | 105 | } |