env->irq[i] = qi[i];
}
}
+
+void cpu_mips_soft_irq(CPUState *env, int irq, int level)
+{
+ if (irq < 0 || irq > 2) {
+ return;
+ }
+
+ qemu_set_irq(env->irq[irq], level);
+}
void cpu_mips_start_count(CPUState *env);
void cpu_mips_stop_count(CPUState *env);
+/* mips_int.c */
+void cpu_mips_soft_irq(CPUState *env, int irq, int level);
+
/* helper.c */
int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int mmu_idx, int is_softmmu);
DEF_HELPER_2(raise_exception_err, void, i32, int)
DEF_HELPER_1(raise_exception, void, i32)
-DEF_HELPER_0(interrupt_restart, void)
#ifdef TARGET_MIPS64
DEF_HELPER_3(ldl, tl, tl, tl, int)
helper_raise_exception_err(exception, 0);
}
-void helper_interrupt_restart (void)
-{
- if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
- !(env->CP0_Status & (1 << CP0St_ERL)) &&
- !(env->hflags & MIPS_HFLAG_DM) &&
- (env->CP0_Status & (1 << CP0St_IE)) &&
- (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask)) {
- env->CP0_Cause &= ~(0x1f << CP0Ca_EC);
- helper_raise_exception(EXCP_EXT_INTERRUPT);
- }
-}
-
#if !defined(CONFIG_USER_ONLY)
static void do_restore_state (void *pc_ptr)
{
{
uint32_t mask = 0x00C00300;
uint32_t old = env->CP0_Cause;
+ int i;
if (env->insn_flags & ISA_MIPS32R2)
mask |= 1 << CP0Ca_DC;
else
cpu_mips_start_count(env);
}
+
+ /* Set/reset software interrupts */
+ for (i = 0 ; i < 2 ; i++) {
+ if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) {
+ cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i)));
+ }
+ }
}
void helper_mtc0_ebase (target_ulong arg1)
switch (sel) {
case 0:
save_cpu_state(ctx, 1);
+ /* Mark as an IO operation because we may trigger a software
+ interrupt. */
+ if (use_icount) {
+ gen_io_start();
+ }
gen_helper_mtc0_cause(arg);
+ if (use_icount) {
+ gen_io_end();
+ }
+ /* Stop translation as we may have triggered an intetrupt */
+ ctx->bstate = BS_STOP;
rn = "Cause";
break;
default:
} else {
switch (ctx.bstate) {
case BS_STOP:
- gen_helper_interrupt_restart();
gen_goto_tb(&ctx, 0, ctx.pc);
break;
case BS_NONE:
gen_goto_tb(&ctx, 0, ctx.pc);
break;
case BS_EXCP:
- gen_helper_interrupt_restart();
tcg_gen_exit_tb(0);
break;
case BS_BRANCH: