gen_io_end();
}
/* Break the TB to be able to take timer interrupts immediately
- after reading count. */
- ctx->bstate = BS_STOP;
+ after reading count. BS_STOP isn't sufficient, we need to ensure
+ we break completely out of translated code. */
+ gen_save_pc(ctx->pc + 4);
+ ctx->bstate = BS_EXCP;
rn = "Count";
break;
/* 6,7 are implementation dependent */
case 0:
save_cpu_state(ctx, 1);
gen_helper_mtc0_cause(cpu_env, arg);
+ /* Stop translation as we may have triggered an interrupt. BS_STOP
+ * isn't sufficient, we need to ensure we break out of translated
+ * code to check for pending interrupts. */
+ gen_save_pc(ctx->pc + 4);
+ ctx->bstate = BS_EXCP;
rn = "Cause";
break;
default:
/* For simplicity assume that all writes can cause interrupts. */
if (ctx->tb->cflags & CF_USE_ICOUNT) {
gen_io_end();
- ctx->bstate = BS_STOP;
+ /* BS_STOP isn't sufficient, we need to ensure we break out of
+ * translated code to check for pending interrupts. */
+ gen_save_pc(ctx->pc + 4);
+ ctx->bstate = BS_EXCP;
}
return;
gen_io_end();
}
/* Break the TB to be able to take timer interrupts immediately
- after reading count. */
- ctx->bstate = BS_STOP;
+ after reading count. BS_STOP isn't sufficient, we need to ensure
+ we break completely out of translated code. */
+ gen_save_pc(ctx->pc + 4);
+ ctx->bstate = BS_EXCP;
rn = "Count";
break;
/* 6,7 are implementation dependent */
if (ctx->tb->cflags & CF_USE_ICOUNT) {
gen_io_end();
}
- /* Stop translation as we may have triggered an intetrupt */
- ctx->bstate = BS_STOP;
+ /* Stop translation as we may have triggered an intetrupt. BS_STOP
+ * isn't sufficient, we need to ensure we break out of translated
+ * code to check for pending interrupts. */
+ gen_save_pc(ctx->pc + 4);
+ ctx->bstate = BS_EXCP;
rn = "Cause";
break;
default:
/* For simplicity assume that all writes can cause interrupts. */
if (ctx->tb->cflags & CF_USE_ICOUNT) {
gen_io_end();
- ctx->bstate = BS_STOP;
+ /* BS_STOP isn't sufficient, we need to ensure we break out of
+ * translated code to check for pending interrupts. */
+ gen_save_pc(ctx->pc + 4);
+ ctx->bstate = BS_EXCP;
}
return;
save_cpu_state(ctx, 1);
gen_helper_ei(t0, cpu_env);
gen_store_gpr(t0, rs);
- /* Stop translation as we may have switched the execution mode */
- ctx->bstate = BS_STOP;
+ /* BS_STOP isn't sufficient, we need to ensure we break out
+ of translated code to check for pending interrupts. */
+ gen_save_pc(ctx->pc + 4);
+ ctx->bstate = BS_EXCP;
tcg_temp_free(t0);
}
break;
save_cpu_state(ctx, 1);
gen_helper_ei(t0, cpu_env);
gen_store_gpr(t0, rt);
- /* Stop translation as we may have switched
- the execution mode. */
- ctx->bstate = BS_STOP;
+ /* BS_STOP isn't sufficient, we need to ensure we break out
+ of translated code to check for pending interrupts. */
+ gen_save_pc(ctx->pc + 4);
+ ctx->bstate = BS_EXCP;
break;
default: /* Invalid */
MIPS_INVAL("mfmc0");