aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-mips/cpu.c4
-rw-r--r--target-mips/cpu.h29
-rw-r--r--target-mips/helper.c3
3 files changed, 20 insertions, 16 deletions
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index 37880d20e0..bbfee4509f 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -58,7 +58,9 @@ static bool mips_cpu_has_work(CPUState *cs)
check for interrupts that can be taken. */
if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
cpu_mips_hw_interrupts_pending(env)) {
- has_work = true;
+ if (cpu_mips_hw_interrupts_enabled(env)) {
+ has_work = true;
+ }
}
/* MIPS-MT has the ability to halt the CPU. */
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index f32a0fd737..3799d26d22 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -637,23 +637,24 @@ static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch)
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;
- int32_t status;
- int r;
-
- if (!(env->CP0_Status & (1 << CP0St_IE)) ||
- (env->CP0_Status & (1 << CP0St_EXL)) ||
- (env->CP0_Status & (1 << CP0St_ERL)) ||
+ return (env->CP0_Status & (1 << CP0St_IE)) &&
+ !(env->CP0_Status & (1 << CP0St_EXL)) &&
+ !(env->CP0_Status & (1 << CP0St_ERL)) &&
+ !(env->hflags & MIPS_HFLAG_DM) &&
/* Note that the TCStatus IXMT field is initialized to zero,
and only MT capable cores can set it to one. So we don't
need to check for MT capabilities here. */
- (env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)) ||
- (env->hflags & MIPS_HFLAG_DM)) {
- /* Interrupts are disabled */
- return 0;
- }
+ !(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT));
+}
+
+/* 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;
status = env->CP0_Status & CP0Ca_IP_mask;
@@ -667,7 +668,7 @@ static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
/* A MIPS configured with compatibility or VInt (Vectored Interrupts)
treats the pending lines as individual interrupt lines, the status
lines are individual masks. */
- r = pending & status;
+ r = (pending & status) != 0;
}
return r;
}
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 01c4461573..2d86323911 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -759,7 +759,8 @@ bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
MIPSCPU *cpu = MIPS_CPU(cs);
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 */
cs->exception_index = EXCP_EXT_INTERRUPT;
env->error_code = 0;