aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdgar E. Iglesias <edgar@axis.com>2010-07-24 13:40:05 +0200
committerEdgar E. Iglesias <edgar.iglesias@gmail.com>2010-07-24 13:40:05 +0200
commit36388314febad3d7675ab919287f03733a560ff6 (patch)
tree7becf392376dc244c812b5ccd23fd7c227124a0b
parentb2178704e46d061b6162ebd37a19e0db02ccbd77 (diff)
mips: Correct MIPS interrupt glue logic for icount
When hw interrupt pending bits in CP0_Cause are set, the CPU should see the hw interrupt line as active. The CPU may or may not take the interrupt based on internal state (global irq mask etc) but the glue logic shouldn't care. This fixes MIPS external hw interrupts in combination with -icount. Signed-off-by: Edgar E. Iglesias <edgar@axis.com>
-rw-r--r--hw/mips_int.c23
-rw-r--r--target-mips/cpu.h3
-rw-r--r--target-mips/op_helper.c11
3 files changed, 6 insertions, 31 deletions
diff --git a/hw/mips_int.c b/hw/mips_int.c
index c30954caaf..80488baeba 100644
--- a/hw/mips_int.c
+++ b/hw/mips_int.c
@@ -24,22 +24,6 @@
#include "mips_cpudevs.h"
#include "cpu.h"
-/* Raise IRQ to CPU if necessary. It must be called every time the active
- IRQ may change */
-void cpu_mips_update_irq(CPUState *env)
-{
- if ((env->CP0_Status & (1 << CP0St_IE)) &&
- !(env->CP0_Status & (1 << CP0St_EXL)) &&
- !(env->CP0_Status & (1 << CP0St_ERL)) &&
- !(env->hflags & MIPS_HFLAG_DM)) {
- if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
- !(env->interrupt_request & CPU_INTERRUPT_HARD)) {
- cpu_interrupt(env, CPU_INTERRUPT_HARD);
- }
- } else
- cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
-}
-
static void cpu_mips_irq_request(void *opaque, int irq, int level)
{
CPUState *env = (CPUState *)opaque;
@@ -52,7 +36,12 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
} else {
env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
}
- cpu_mips_update_irq(env);
+
+ if (env->CP0_Cause & CP0Ca_IP_mask) {
+ cpu_interrupt(env, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ }
}
void cpu_mips_irq_init_cpu(CPUState *env)
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 81051aa004..157885082a 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -597,9 +597,6 @@ void cpu_mips_store_compare (CPUState *env, uint32_t value);
void cpu_mips_start_count(CPUState *env);
void cpu_mips_stop_count(CPUState *env);
-/* mips_int.c */
-void cpu_mips_update_irq (CPUState *env);
-
/* helper.c */
int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int mmu_idx, int is_softmmu);
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 8ae510adc1..c9632248a0 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1313,7 +1313,6 @@ void helper_mtc0_status (target_ulong arg1)
default: cpu_abort(env, "Invalid MMU mode!\n"); break;
}
}
- cpu_mips_update_irq(env);
}
void helper_mttc0_status(target_ulong arg1)
@@ -1359,12 +1358,6 @@ void helper_mtc0_cause (target_ulong arg1)
else
cpu_mips_start_count(env);
}
-
- /* Handle the software interrupt as an hardware one, as they
- are very similar */
- if (arg1 & CP0Ca_IP_mask) {
- cpu_mips_update_irq(env);
- }
}
void helper_mtc0_ebase (target_ulong arg1)
@@ -1793,8 +1786,6 @@ target_ulong helper_di (void)
target_ulong t0 = env->CP0_Status;
env->CP0_Status = t0 & ~(1 << CP0St_IE);
- cpu_mips_update_irq(env);
-
return t0;
}
@@ -1803,8 +1794,6 @@ target_ulong helper_ei (void)
target_ulong t0 = env->CP0_Status;
env->CP0_Status = t0 | (1 << CP0St_IE);
- cpu_mips_update_irq(env);
-
return t0;
}