diff options
Diffstat (limited to 'target-alpha')
-rw-r--r-- | target-alpha/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-alpha/cpu.c | 1 | ||||
-rw-r--r-- | target-alpha/helper.c | 44 |
3 files changed, 46 insertions, 0 deletions
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h index 0caa362f5b..b01c6c82eb 100644 --- a/target-alpha/cpu-qom.h +++ b/target-alpha/cpu-qom.h @@ -79,6 +79,7 @@ extern const struct VMStateDescription vmstate_alpha_cpu; #endif void alpha_cpu_do_interrupt(CPUState *cpu); +bool alpha_cpu_exec_interrupt(CPUState *cpu, int int_req); void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags); hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c index 2491f0a301..a98b7d8d72 100644 --- a/target-alpha/cpu.c +++ b/target-alpha/cpu.c @@ -284,6 +284,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data) cc->class_by_name = alpha_cpu_class_by_name; cc->has_work = alpha_cpu_has_work; cc->do_interrupt = alpha_cpu_do_interrupt; + cc->cpu_exec_interrupt = alpha_cpu_exec_interrupt; cc->dump_state = alpha_cpu_dump_state; cc->set_pc = alpha_cpu_set_pc; cc->gdb_read_register = alpha_cpu_gdb_read_register; diff --git a/target-alpha/helper.c b/target-alpha/helper.c index 7c053a3eae..a8aa782a2a 100644 --- a/target-alpha/helper.c +++ b/target-alpha/helper.c @@ -470,6 +470,50 @@ void alpha_cpu_do_interrupt(CPUState *cs) #endif /* !USER_ONLY */ } +bool alpha_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + AlphaCPU *cpu = ALPHA_CPU(cs); + CPUAlphaState *env = &cpu->env; + int idx = -1; + + /* We never take interrupts while in PALmode. */ + if (env->pal_mode) { + return false; + } + + /* Fall through the switch, collecting the highest priority + interrupt that isn't masked by the processor status IPL. */ + /* ??? This hard-codes the OSF/1 interrupt levels. */ + switch (env->ps & PS_INT_MASK) { + case 0 ... 3: + if (interrupt_request & CPU_INTERRUPT_HARD) { + idx = EXCP_DEV_INTERRUPT; + } + /* FALLTHRU */ + case 4: + if (interrupt_request & CPU_INTERRUPT_TIMER) { + idx = EXCP_CLK_INTERRUPT; + } + /* FALLTHRU */ + case 5: + if (interrupt_request & CPU_INTERRUPT_SMP) { + idx = EXCP_SMP_INTERRUPT; + } + /* FALLTHRU */ + case 6: + if (interrupt_request & CPU_INTERRUPT_MCHK) { + idx = EXCP_MCHK; + } + } + if (idx >= 0) { + cs->exception_index = idx; + env->error_code = 0; + alpha_cpu_do_interrupt(cs); + return true; + } + return false; +} + void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, int flags) { |