1409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#include "hw.h" 2409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#include "mips.h" 3409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#include "qemu-timer.h" 4409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 5409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#define TIMER_FREQ 100 * 1000 * 1000 6409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 7409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli/* XXX: do not use a global */ 8409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalliuint32_t cpu_mips_get_random (CPUState *env) 9409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 10409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli static uint32_t lfsr = 1; 11409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli static uint32_t prev_idx = 0; 12409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli uint32_t idx; 13409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* Don't return same value twice, so get another value */ 14409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli do { 15409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u); 16409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired; 17409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } while (idx == prev_idx); 18409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli prev_idx = idx; 19409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return idx; 20409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 21409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 22409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli/* MIPS R4K timer */ 23409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalliuint32_t cpu_mips_get_count (CPUState *env) 24409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 25409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->CP0_Cause & (1 << CP0Ca_DC)) 26409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return env->CP0_Count; 27409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli else 28409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return env->CP0_Count + 29409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli (uint32_t)muldiv64(qemu_get_clock(vm_clock), 30409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli TIMER_FREQ, get_ticks_per_sec()); 31409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 32409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 33409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapallistatic void cpu_mips_timer_update(CPUState *env) 34409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 35409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli uint64_t now, next; 36409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli uint32_t wait; 37409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 38409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli now = qemu_get_clock(vm_clock); 39409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli wait = env->CP0_Compare - env->CP0_Count - 40409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec()); 41409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ); 42409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli qemu_mod_timer(env->timer, next); 43409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 44409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 45409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapallivoid cpu_mips_store_count (CPUState *env, uint32_t count) 46409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 47409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->CP0_Cause & (1 << CP0Ca_DC)) 48409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Count = count; 49409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli else { 50409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* Store new count register */ 51409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Count = 52409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli count - (uint32_t)muldiv64(qemu_get_clock(vm_clock), 53409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli TIMER_FREQ, get_ticks_per_sec()); 54409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* Update timer timer */ 55409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cpu_mips_timer_update(env); 56409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli } 57409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 58409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 59409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapallivoid cpu_mips_store_compare (CPUState *env, uint32_t value) 60409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 61409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Compare = value; 62409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (!(env->CP0_Cause & (1 << CP0Ca_DC))) 63409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cpu_mips_timer_update(env); 64409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->insn_flags & ISA_MIPS32R2) 65409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Cause &= ~(1 << CP0Ca_TI); 66409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); 67409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 68409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 69409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapallivoid cpu_mips_start_count(CPUState *env) 70409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 71409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cpu_mips_store_count(env, env->CP0_Count); 72409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 73409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 74409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapallivoid cpu_mips_stop_count(CPUState *env) 75409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 76409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* Store the current value */ 77409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock), 78409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli TIMER_FREQ, get_ticks_per_sec()); 79409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 80409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 81409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapallistatic void mips_timer_cb (void *opaque) 82409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 83409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli CPUState *env; 84409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 85409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env = opaque; 86409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#if 0 87409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli qemu_log("%s\n", __func__); 88409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#endif 89409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 90409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->CP0_Cause & (1 << CP0Ca_DC)) 91409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli return; 92409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 93409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli /* ??? This callback should occur when the counter is exactly equal to 94409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli the comparator value. Offset the count by one to avoid immediately 95409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli retriggering the callback before any virtual time has passed. */ 96409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Count++; 97409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cpu_mips_timer_update(env); 98409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Count--; 99409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli if (env->insn_flags & ISA_MIPS32R2) 100409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Cause |= 1 << CP0Ca_TI; 101409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); 102409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 103409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli 104409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapallivoid cpu_mips_clock_init (CPUState *env) 105409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{ 106325e19d19ff9e1fc9c6acb12eeb754563fc2e251Bhanu Chetlapalli env->timer = qemu_new_timer_ns(vm_clock, &mips_timer_cb, env); 107409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli env->CP0_Compare = 0; 108409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli cpu_mips_store_count(env, 1); 109409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli} 110