12ec695af7284adbedcdbc08a22d818b6bdd8990cDavid 'Digit' Turner#include "hw/hw.h"
2c7169658d43ef2a0256cea9a3a1251c3c039676eDavid 'Digit' Turner#include "hw/mips/mips.h"
3409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli#include "cpu.h"
4409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli
5409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli/* Raise IRQ to CPU if necessary. It must be called every time the active
6409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli   IRQ may change */
7e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnervoid cpu_mips_update_irq(CPUOldState *env)
8409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{
9bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner    CPUState *cpu = ENV_GET_CPU(env);
10bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner
11409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    if ((env->CP0_Status & (1 << CP0St_IE)) &&
12409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli        !(env->CP0_Status & (1 << CP0St_EXL)) &&
13409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli        !(env->CP0_Status & (1 << CP0St_ERL)) &&
14409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli        !(env->hflags & MIPS_HFLAG_DM)) {
15409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli        if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
16bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner            !(cpu->interrupt_request & CPU_INTERRUPT_HARD)) {
17bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner            cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
186657678c3d86395084f6a699e73614195f06c445David 'Digit' Turner        }
19409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    } else
20bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner        cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
21409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli}
22409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli
23409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapallistatic void cpu_mips_irq_request(void *opaque, int irq, int level)
24409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{
25e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner    CPUOldState *env = (CPUOldState *)opaque;
26409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli
27409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    if (irq < 0 || irq > 7)
28409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli        return;
29409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli
30409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    if (level) {
31409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
32409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    } else {
33409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli        env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
34409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    }
35409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    cpu_mips_update_irq(env);
36409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli}
37409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli
38e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnervoid cpu_mips_irq_init_cpu(CPUOldState *env)
39409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli{
40409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    qemu_irq *qi;
41409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    int i;
42409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli
43409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    qi = qemu_allocate_irqs(cpu_mips_irq_request, env, 8);
44409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    for (i = 0; i < 8; i++) {
45409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli        env->irq[i] = qi[i];
46409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli    }
47409c7b66435cf5947cab6bf0710f92507317f22eBhanu Chetlapalli}
48