target-mips: move the test for enabled interrupts to a separate function

Backports commit 71ca034a0dee69f77c8ac6ea7d21e5b6a0b0d836 from qemu
This commit is contained in:
Leon Alrae 2018-02-17 14:26:37 -05:00 committed by Lioncash
parent b9cf91307e
commit 5a60450b96
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
3 changed files with 21 additions and 16 deletions

View file

@ -57,8 +57,10 @@ static bool mips_cpu_has_work(CPUState *cs)
check for interrupts that can be taken. */ check for interrupts that can be taken. */
if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
cpu_mips_hw_interrupts_pending(env)) { cpu_mips_hw_interrupts_pending(env)) {
if (cpu_mips_hw_interrupts_enabled(env)) {
has_work = true; has_work = true;
} }
}
/* MIPS-MT has the ability to halt the CPU. */ /* MIPS-MT has the ability to halt the CPU. */
if (env->CP0_Config3 & (1 << CP0C3_MT)) { if (env->CP0_Config3 & (1 << CP0C3_MT)) {

View file

@ -643,24 +643,26 @@ static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch)
return env->hflags & MIPS_HFLAG_KSU; return env->hflags & MIPS_HFLAG_KSU;
} }
static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env) static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env)
{ {
int32_t pending; return (env->CP0_Status & (1 << CP0St_IE)) &&
int32_t status; !(env->CP0_Status & (1 << CP0St_EXL)) &&
int r; !(env->CP0_Status & (1 << CP0St_ERL)) &&
!(env->hflags & MIPS_HFLAG_DM) &&
if (!(env->CP0_Status & (1 << CP0St_IE)) ||
(env->CP0_Status & (1 << CP0St_EXL)) ||
(env->CP0_Status & (1 << CP0St_ERL)) ||
/* Note that the TCStatus IXMT field is initialized to zero, /* Note that the TCStatus IXMT field is initialized to zero,
and only MT capable cores can set it to one. So we don't and only MT capable cores can set it to one. So we don't
need to check for MT capabilities here. */ need to check for MT capabilities here. */
(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)) || !(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT));
(env->hflags & MIPS_HFLAG_DM)) {
/* Interrupts are disabled */
return 0;
} }
/* Check if there is pending and not masked out interrupt */
static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
{
int32_t pending;
int32_t status;
bool r;
pending = env->CP0_Cause & CP0Ca_IP_mask; pending = env->CP0_Cause & CP0Ca_IP_mask;
status = env->CP0_Status & CP0Ca_IP_mask; status = env->CP0_Status & CP0Ca_IP_mask;
@ -673,7 +675,7 @@ static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
/* A MIPS configured with compatibility or VInt (Vectored Interrupts) /* A MIPS configured with compatibility or VInt (Vectored Interrupts)
treats the pending lines as individual interrupt lines, the status treats the pending lines as individual interrupt lines, the status
lines are individual masks. */ lines are individual masks. */
r = pending & status; r = (pending & status) != 0;
} }
return r; return r;
} }

View file

@ -746,7 +746,8 @@ bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request) // qq
MIPSCPU *cpu = MIPS_CPU(cs->uc, cs); MIPSCPU *cpu = MIPS_CPU(cs->uc, cs);
CPUMIPSState *env = &cpu->env; CPUMIPSState *env = &cpu->env;
if (cpu_mips_hw_interrupts_pending(env)) { if (cpu_mips_hw_interrupts_enabled(env) &&
cpu_mips_hw_interrupts_pending(env)) {
/* Raise it */ /* Raise it */
cs->exception_index = EXCP_EXT_INTERRUPT; cs->exception_index = EXCP_EXT_INTERRUPT;
env->error_code = 0; env->error_code = 0;