3 #include "qemu-timer.h"
5 #define TIMER_FREQ 100 * 1000 * 1000
7 void cpu_mips_irqctrl_init (void)
11 /* XXX: do not use a global */
12 uint32_t cpu_mips_get_random (CPUState
*env
)
14 static uint32_t seed
= 0;
16 seed
= seed
* 314159 + 1;
17 idx
= (seed
>> 16) % (env
->tlb
->nb_tlb
- env
->CP0_Wired
) + env
->CP0_Wired
;
22 uint32_t cpu_mips_get_count (CPUState
*env
)
24 if (env
->CP0_Cause
& (1 << CP0Ca_DC
))
25 return env
->CP0_Count
;
27 return env
->CP0_Count
+
28 (uint32_t)muldiv64(qemu_get_clock(vm_clock
),
29 TIMER_FREQ
, ticks_per_sec
);
32 static void cpu_mips_timer_update(CPUState
*env
)
37 now
= qemu_get_clock(vm_clock
);
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
);
41 qemu_mod_timer(env
->timer
, next
);
44 void cpu_mips_store_count (CPUState
*env
, uint32_t count
)
46 if (env
->CP0_Cause
& (1 << CP0Ca_DC
))
47 env
->CP0_Count
= count
;
49 /* Store new count register */
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
);
58 void cpu_mips_store_compare (CPUState
*env
, uint32_t value
)
60 env
->CP0_Compare
= value
;
61 if (!(env
->CP0_Cause
& (1 << CP0Ca_DC
)))
62 cpu_mips_timer_update(env
);
63 if (env
->insn_flags
& ISA_MIPS32R2
)
64 env
->CP0_Cause
&= ~(1 << CP0Ca_TI
);
65 qemu_irq_lower(env
->irq
[(env
->CP0_IntCtl
>> CP0IntCtl_IPTI
) & 0x7]);
68 void cpu_mips_start_count(CPUState
*env
)
70 cpu_mips_store_count(env
, env
->CP0_Count
);
73 void cpu_mips_stop_count(CPUState
*env
)
75 /* Store the current value */
76 env
->CP0_Count
+= (uint32_t)muldiv64(qemu_get_clock(vm_clock
),
77 TIMER_FREQ
, ticks_per_sec
);
80 static void mips_timer_cb (void *opaque
)
87 fprintf(logfile
, "%s\n", __func__
);
91 if (env
->CP0_Cause
& (1 << CP0Ca_DC
))
94 cpu_mips_timer_update(env
);
95 if (env
->insn_flags
& ISA_MIPS32R2
)
96 env
->CP0_Cause
|= 1 << CP0Ca_TI
;
97 qemu_irq_raise(env
->irq
[(env
->CP0_IntCtl
>> CP0IntCtl_IPTI
) & 0x7]);
100 void cpu_mips_clock_init (CPUState
*env
)
102 env
->timer
= qemu_new_timer(vm_clock
, &mips_timer_cb
, env
);
103 env
->CP0_Compare
= 0;
104 cpu_mips_store_count(env
, 1);