Optimize MIPS timer read/write functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4190 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									1570de2df1
								
							
						
					
					
						commit
						ea86e4e600
					
				| @ -2,6 +2,8 @@ | ||||
| #include "mips.h" | ||||
| #include "qemu-timer.h" | ||||
| 
 | ||||
| #define TIMER_FREQ	100 * 1000 * 1000 | ||||
| 
 | ||||
| void cpu_mips_irqctrl_init (void) | ||||
| { | ||||
| } | ||||
| @ -24,49 +26,41 @@ uint32_t cpu_mips_get_count (CPUState *env) | ||||
|     else | ||||
|         return env->CP0_Count + | ||||
|             (uint32_t)muldiv64(qemu_get_clock(vm_clock), | ||||
|                                100 * 1000 * 1000, ticks_per_sec); | ||||
|                                TIMER_FREQ, ticks_per_sec); | ||||
| } | ||||
| 
 | ||||
| static void cpu_mips_timer_update(CPUState *env) | ||||
| { | ||||
|     uint64_t now, next; | ||||
|     uint32_t wait; | ||||
| 
 | ||||
|     now = qemu_get_clock(vm_clock); | ||||
|     wait = env->CP0_Compare - env->CP0_Count - | ||||
| 	    (uint32_t)muldiv64(now, TIMER_FREQ, ticks_per_sec); | ||||
|     next = now + muldiv64(wait, ticks_per_sec, TIMER_FREQ); | ||||
|     qemu_mod_timer(env->timer, next); | ||||
| } | ||||
| 
 | ||||
| void cpu_mips_store_count (CPUState *env, uint32_t count) | ||||
| { | ||||
|     uint64_t now, next; | ||||
|     uint32_t tmp; | ||||
|     uint32_t compare = env->CP0_Compare; | ||||
| 
 | ||||
|     tmp = count; | ||||
|     if (count == compare) | ||||
|         tmp++; | ||||
|     now = qemu_get_clock(vm_clock); | ||||
|     next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000); | ||||
|     if (next == now) | ||||
| 	next++; | ||||
| #if 0 | ||||
|     if (logfile) { | ||||
|         fprintf(logfile, "%s: 0x%08" PRIx64 " %08x %08x => 0x%08" PRIx64 "\n", | ||||
|                 __func__, now, count, compare, next - now); | ||||
|     } | ||||
| #endif | ||||
|     /* Store new count and compare registers */ | ||||
|     env->CP0_Compare = compare; | ||||
|     env->CP0_Count = | ||||
|         count - (uint32_t)muldiv64(now, 100 * 1000 * 1000, ticks_per_sec); | ||||
|     /* Adjust timer */ | ||||
|     qemu_mod_timer(env->timer, next); | ||||
| } | ||||
| 
 | ||||
| static void cpu_mips_update_count (CPUState *env, uint32_t count) | ||||
| { | ||||
|     if (env->CP0_Cause & (1 << CP0Ca_DC)) | ||||
|         return; | ||||
| 
 | ||||
|     cpu_mips_store_count(env, count); | ||||
|         env->CP0_Count = count; | ||||
|     else { | ||||
|         /* Store new count register */ | ||||
|         env->CP0_Count = | ||||
|             count - (uint32_t)muldiv64(qemu_get_clock(vm_clock), | ||||
|                                        TIMER_FREQ, ticks_per_sec); | ||||
|         /* Update timer timer */ | ||||
|         cpu_mips_timer_update(env); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void cpu_mips_store_compare (CPUState *env, uint32_t value) | ||||
| { | ||||
|     env->CP0_Compare = value; | ||||
|     cpu_mips_update_count(env, cpu_mips_get_count(env)); | ||||
|     if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) | ||||
|     if (!(env->CP0_Cause & (1 << CP0Ca_DC))) | ||||
|         cpu_mips_timer_update(env); | ||||
|     if (env->insn_flags & ISA_MIPS32R2) | ||||
|         env->CP0_Cause &= ~(1 << CP0Ca_TI); | ||||
|     qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); | ||||
| } | ||||
| @ -80,7 +74,7 @@ void cpu_mips_stop_count(CPUState *env) | ||||
| { | ||||
|     /* Store the current value */ | ||||
|     env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock), | ||||
|                                          100 * 1000 * 1000, ticks_per_sec); | ||||
|                                          TIMER_FREQ, ticks_per_sec); | ||||
| } | ||||
| 
 | ||||
| static void mips_timer_cb (void *opaque) | ||||
| @ -97,8 +91,8 @@ static void mips_timer_cb (void *opaque) | ||||
|     if (env->CP0_Cause & (1 << CP0Ca_DC)) | ||||
|         return; | ||||
| 
 | ||||
|     cpu_mips_update_count(env, cpu_mips_get_count(env)); | ||||
|     if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) | ||||
|     cpu_mips_timer_update(env); | ||||
|     if (env->insn_flags & ISA_MIPS32R2) | ||||
|         env->CP0_Cause |= 1 << CP0Ca_TI; | ||||
|     qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); | ||||
| } | ||||
| @ -107,5 +101,5 @@ void cpu_mips_clock_init (CPUState *env) | ||||
| { | ||||
|     env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env); | ||||
|     env->CP0_Compare = 0; | ||||
|     cpu_mips_update_count(env, 1); | ||||
|     cpu_mips_store_count(env, 1); | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 aurel32
						aurel32