diff options
author | Philippe Mathieu-Daudé | 2021-04-28 16:16:54 +0200 |
---|---|---|
committer | Mark Cave-Ayland | 2021-05-04 23:45:53 +0200 |
commit | 10fb1340b161682d64320a5976f88f68472410bf (patch) | |
tree | 27f6e9ebcde6e481677b518e72df757a15ca86dc /target/sparc/int64_helper.c | |
parent | hw/sparc64: Fix code style for checkpatch.pl (diff) | |
download | qemu-10fb1340b161682d64320a5976f88f68472410bf.tar.gz qemu-10fb1340b161682d64320a5976f88f68472410bf.tar.xz qemu-10fb1340b161682d64320a5976f88f68472410bf.zip |
hw/sparc*: Move cpu_check_irqs() to target/sparc/
Since cpu_check_irqs() doesn't reference to anything outside
of CPUSPARCState, it better belongs to the architectural code
in target/, rather than the hardware specific code in hw/.
Note: while we moved the trace events, we don't rename them.
Remark: this allows us to build the leon3 machine stand alone,
fixing this link failure (because cpu_check_irqs is defined in
hw/sparc/sun4m.c which is only built when CONFIG_SUN4M is selected):
/usr/bin/ld: target_sparc_win_helper.c.o: in function `cpu_put_psr':
target/sparc/win_helper.c:91: undefined reference to `cpu_check_irqs'
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20210428141655.387430-5-f4bug@amsat.org>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Diffstat (limited to 'target/sparc/int64_helper.c')
-rw-r--r-- | target/sparc/int64_helper.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/target/sparc/int64_helper.c b/target/sparc/int64_helper.c index 7fb8ab211c..793e57c536 100644 --- a/target/sparc/int64_helper.c +++ b/target/sparc/int64_helper.c @@ -62,6 +62,72 @@ static const char * const excp_names[0x80] = { }; #endif +void cpu_check_irqs(CPUSPARCState *env) +{ + CPUState *cs; + uint32_t pil = env->pil_in | + (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER)); + + /* We should be holding the BQL before we mess with IRQs */ + g_assert(qemu_mutex_iothread_locked()); + + /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */ + if (env->ivec_status & 0x20) { + return; + } + cs = env_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) { + trace_sparc64_cpu_check_irqs_reset_irq(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))) { + trace_sparc64_cpu_check_irqs_noset_irq(env->tl, + cpu_tsptr(env)->tt, + new_interrupt); + } else if (old_interrupt != new_interrupt) { + env->interrupt_index = new_interrupt; + trace_sparc64_cpu_check_irqs_set_irq(i, old_interrupt, + new_interrupt); + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } + break; + } + } + } else if (cs->interrupt_request & CPU_INTERRUPT_HARD) { + trace_sparc64_cpu_check_irqs_disabled(pil, env->pil_in, env->softint, + env->interrupt_index); + env->interrupt_index = 0; + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } +} + void sparc_cpu_do_interrupt(CPUState *cs) { SPARCCPU *cpu = SPARC_CPU(cs); |