void cpu_check_irqs(CPUState *env) { uint32_t pil = env->pil_in | (env->softint & ~SOFTINT_TIMER) | ((env->softint & SOFTINT_TIMER) << 14); if (pil && (env->interrupt_index == 0 || (env->interrupt_index & ~15) == TT_EXTINT)) { unsigned int i; for (i = 15; i > 0; i--) { if (pil & (1 << i)) { int old_interrupt = env->interrupt_index; env->interrupt_index = TT_EXTINT | i; if (old_interrupt != env->interrupt_index) { CPUIRQ_DPRINTF("Set CPU IRQ %d\n", i); cpu_interrupt(env, CPU_INTERRUPT_HARD); } break; } } } else if (!pil && (env->interrupt_index & ~15) == TT_EXTINT) { CPUIRQ_DPRINTF("Reset CPU IRQ %d\n", env->interrupt_index & 15); env->interrupt_index = 0; cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); } }
static void cpu_set_ivec_irq(void *opaque, int irq, int level) { SPARCCPU *cpu = opaque; CPUSPARCState *env = &cpu->env; CPUState *cs; if (level) { if (!(env->ivec_status & 0x20)) { CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq); cs = CPU(cpu); cs->halted = 0; env->interrupt_index = TT_IVEC; env->ivec_status |= 0x20; env->ivec_data[0] = (0x1f << 6) | irq; env->ivec_data[1] = 0; env->ivec_data[2] = 0; cpu_interrupt(cs, CPU_INTERRUPT_HARD); } } else { if (env->ivec_status & 0x20) { CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq); cs = CPU(cpu); env->ivec_status &= ~0x20; cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); } } }
void cpu_check_irqs(CPUSPARCState *env) { CPUState *cs; uint32_t pil = env->pil_in | (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER)); /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */ if (env->ivec_status & 0x20) { return; } cs = CPU(sparc_env_get_cpu(env)); /* check if TM or SM in SOFTINT are set setting these also causes interrupt 14 */ if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) { pil |= 1 << 14; } /* The bit corresponding to psrpil is (1<< psrpil), the next bit is (2 << psrpil). */ if (pil < (2 << env->psrpil)){ if (cs->interrupt_request & CPU_INTERRUPT_HARD) { CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n", env->interrupt_index); env->interrupt_index = 0; cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); } return; } if (cpu_interrupts_enabled(env)) { unsigned int i; for (i = 15; i > env->psrpil; i--) { if (pil & (1 << i)) { int old_interrupt = env->interrupt_index; int new_interrupt = TT_EXTINT | i; if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) { CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d " "current %x >= pending %x\n", env->tl, cpu_tsptr(env)->tt, new_interrupt); } else if (old_interrupt != new_interrupt) { env->interrupt_index = new_interrupt; CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i, old_interrupt, new_interrupt); cpu_interrupt(cs, CPU_INTERRUPT_HARD); } break; } } } else if (cs->interrupt_request & CPU_INTERRUPT_HARD) { CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x " "current interrupt %x\n", pil, env->pil_in, env->softint, env->interrupt_index); env->interrupt_index = 0; cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); } }
static void cpu_set_irq(void *opaque, int irq, int level) { CPUState *env = opaque; if (level) { CPUIRQ_DPRINTF("Raise CPU IRQ %d\n", irq); env->pil_in |= 1 << irq; cpu_kick_irq(env); } else { CPUIRQ_DPRINTF("Lower CPU IRQ %d\n", irq); env->pil_in &= ~(1 << irq); cpu_check_irqs(env); } }
void cpu_check_irqs(CPUState *env) { uint32_t pil = env->pil_in | (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER)); /* check if TM or SM in SOFTINT are set setting these also causes interrupt 14 */ if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) { pil |= 1 << 14; } if (!pil) { if (env->interrupt_request & CPU_INTERRUPT_HARD) { CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n", env->interrupt_index); env->interrupt_index = 0; cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); } return; } if (cpu_interrupts_enabled(env)) { unsigned int i; for (i = 15; i > env->psrpil; i--) { if (pil & (1 << i)) { int old_interrupt = env->interrupt_index; int new_interrupt = TT_EXTINT | i; if (env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt) { CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d " "current %x >= pending %x\n", env->tl, cpu_tsptr(env)->tt, new_interrupt); } else if (old_interrupt != new_interrupt) { env->interrupt_index = new_interrupt; CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i, old_interrupt, new_interrupt); cpu_interrupt(env, CPU_INTERRUPT_HARD); } break; } } } else { CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x " "current interrupt %x\n", pil, env->pil_in, env->softint, env->interrupt_index); } }
static void hstick_irq(void *opaque) { CPUSPARCState *env = opaque; CPUTimer* timer = env->hstick; if (timer->disabled) { CPUIRQ_DPRINTF("hstick_irq: softint disabled\n"); return; } else { CPUIRQ_DPRINTF("hstick: fire\n"); } env->softint |= SOFTINT_STIMER; cpu_kick_irq(env); }
static void stick_irq(void *opaque) { SPARCCPU *cpu = opaque; CPUSPARCState *env = &cpu->env; CPUTimer* timer = env->stick; if (timer->disabled) { CPUIRQ_DPRINTF("stick_irq: softint disabled\n"); return; } else { CPUIRQ_DPRINTF("stick: fire\n"); } env->softint |= SOFTINT_STIMER; cpu_kick_irq(cpu); }