summaryrefslogtreecommitdiffstats
path: root/target/sparc/int64_helper.c
diff options
context:
space:
mode:
authorPhilippe Mathieu-Daudé2021-04-28 16:16:54 +0200
committerMark Cave-Ayland2021-05-04 23:45:53 +0200
commit10fb1340b161682d64320a5976f88f68472410bf (patch)
tree27f6e9ebcde6e481677b518e72df757a15ca86dc /target/sparc/int64_helper.c
parenthw/sparc64: Fix code style for checkpatch.pl (diff)
downloadqemu-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.c66
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);