the PC (for whatever reason), so there's no need to do it again on
exiting the TB. */
EXIT_PC_UPDATED,
+ EXIT_PC_UPDATED_NOCHAIN,
/* We are exiting the TB, but have neither emitted a goto_tb, nor
updated the PC for the next instruction to be executed. */
#endif
}
+static bool use_exit_tb(DisasContext *ctx)
+{
+ return ((ctx->tb->cflags & CF_LAST_IO)
+ || ctx->singlestep_enabled
+ || singlestep);
+}
+
static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
{
/* Suppress goto_tb in the case of single-steping and IO. */
- if ((ctx->tb->cflags & CF_LAST_IO)
- || ctx->singlestep_enabled || singlestep) {
+ if (unlikely(use_exit_tb(ctx))) {
return false;
}
#ifndef CONFIG_USER_ONLY
tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, ps));
tcg_temp_free(tmp);
- break;
+
+ /* Allow interrupts to be recognized right away. */
+ tcg_gen_movi_i64(cpu_pc, ctx->pc);
+ return EXIT_PC_UPDATED_NOCHAIN;
case 0x36:
/* RDPS */
need the page permissions check. We'll see the existence of
the page when we create the TB, and we'll flush all TBs if
we change the PAL base register. */
- if (!ctx->singlestep_enabled && !(ctx->tb->cflags & CF_LAST_IO)) {
+ if (!use_exit_tb(ctx)) {
tcg_gen_goto_tb(0);
tcg_gen_movi_i64(cpu_pc, entry);
tcg_gen_exit_tb((uintptr_t)ctx->tb);
tcg_gen_andi_i64(tmp, vb, 1);
tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUAlphaState, pal_mode));
tcg_gen_andi_i64(cpu_pc, vb, ~3);
- ret = EXIT_PC_UPDATED;
+ /* Allow interrupts to be recognized right away. */
+ ret = EXIT_PC_UPDATED_NOCHAIN;
break;
#else
goto invalid_opc;
tcg_gen_movi_i64(cpu_pc, ctx.pc);
/* FALLTHRU */
case EXIT_PC_UPDATED:
+ if (!use_exit_tb(&ctx)) {
+ tcg_gen_lookup_and_goto_ptr(cpu_pc);
+ break;
+ }
+ /* FALLTHRU */
+ case EXIT_PC_UPDATED_NOCHAIN:
if (ctx.singlestep_enabled) {
gen_excp_1(EXCP_DEBUG, 0);
} else {