|
|
1.1.1.2 ! root 1: #include "hw.h" ! 2: #include "mips.h" ! 3: #include "qemu-timer.h" 1.1 root 4: 5: void cpu_mips_irqctrl_init (void) 6: { 7: } 8: 9: /* XXX: do not use a global */ 10: uint32_t cpu_mips_get_random (CPUState *env) 11: { 12: static uint32_t seed = 0; 13: uint32_t idx; 14: seed = seed * 314159 + 1; 1.1.1.2 ! root 15: idx = (seed >> 16) % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired; 1.1 root 16: return idx; 17: } 18: 19: /* MIPS R4K timer */ 20: uint32_t cpu_mips_get_count (CPUState *env) 21: { 1.1.1.2 ! root 22: if (env->CP0_Cause & (1 << CP0Ca_DC)) ! 23: return env->CP0_Count; ! 24: else ! 25: return env->CP0_Count + ! 26: (uint32_t)muldiv64(qemu_get_clock(vm_clock), ! 27: 100 * 1000 * 1000, ticks_per_sec); 1.1 root 28: } 29: 1.1.1.2 ! root 30: void cpu_mips_store_count (CPUState *env, uint32_t count) 1.1 root 31: { 32: uint64_t now, next; 33: uint32_t tmp; 1.1.1.2 ! root 34: uint32_t compare = env->CP0_Compare; 1.1 root 35: 36: tmp = count; 37: if (count == compare) 38: tmp++; 39: 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 */ 54: qemu_mod_timer(env->timer, next); 55: } 56: 1.1.1.2 ! root 57: static void cpu_mips_update_count (CPUState *env, uint32_t count) 1.1 root 58: { 1.1.1.2 ! root 59: if (env->CP0_Cause & (1 << CP0Ca_DC)) ! 60: return; ! 61: ! 62: cpu_mips_store_count(env, count); 1.1 root 63: } 64: 65: void cpu_mips_store_compare (CPUState *env, uint32_t value) 66: { 1.1.1.2 ! root 67: 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)) ! 70: env->CP0_Cause &= ~(1 << CP0Ca_TI); ! 71: qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); ! 72: } ! 73: ! 74: void cpu_mips_start_count(CPUState *env) ! 75: { ! 76: cpu_mips_store_count(env, env->CP0_Count); ! 77: } ! 78: ! 79: void cpu_mips_stop_count(CPUState *env) ! 80: { ! 81: /* Store the current value */ ! 82: env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock(vm_clock), ! 83: 100 * 1000 * 1000, ticks_per_sec); 1.1 root 84: } 85: 86: static void mips_timer_cb (void *opaque) 87: { 88: CPUState *env; 89: 90: env = opaque; 91: #if 0 92: if (logfile) { 93: fprintf(logfile, "%s\n", __func__); 94: } 95: #endif 1.1.1.2 ! root 96: ! 97: if (env->CP0_Cause & (1 << CP0Ca_DC)) ! 98: return; ! 99: ! 100: cpu_mips_update_count(env, cpu_mips_get_count(env)); ! 101: if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR)) ! 102: env->CP0_Cause |= 1 << CP0Ca_TI; ! 103: qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); 1.1 root 104: } 105: 106: void cpu_mips_clock_init (CPUState *env) 107: { 108: env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env); 109: env->CP0_Compare = 0; 1.1.1.2 ! root 110: cpu_mips_update_count(env, 1); 1.1 root 111: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.