mirror of https://gitee.com/openkylin/qemu.git
target/hppa: Avoid squishing DISAS_IAQ_N_STALE_EXIT
Within a delay slot, we were squishing both DISAS_IAQ_N_STALE and DISAS_IAQ_N_STALE_EXIT to DISAS_IAQ_N_UPDATED. This lost the required exit to the main loop, and could result in interrupts never being delivered. Tested-by: Sven Schnelle <svens@stackframe.org> Reported-by: Sven Schnelle <svens@stackframe.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
8b088d3f8a
commit
c5d0aec25f
|
@ -347,6 +347,7 @@ static int expand_shl11(int val)
|
||||||
/* Similarly, but we want to return to the main loop immediately
|
/* Similarly, but we want to return to the main loop immediately
|
||||||
to recognize unmasked interrupts. */
|
to recognize unmasked interrupts. */
|
||||||
#define DISAS_IAQ_N_STALE_EXIT DISAS_TARGET_2
|
#define DISAS_IAQ_N_STALE_EXIT DISAS_TARGET_2
|
||||||
|
#define DISAS_EXIT DISAS_TARGET_3
|
||||||
|
|
||||||
/* global register indexes */
|
/* global register indexes */
|
||||||
static TCGv_reg cpu_gr[32];
|
static TCGv_reg cpu_gr[32];
|
||||||
|
@ -4218,19 +4219,31 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
||||||
ctx->iaoq_b = ctx->iaoq_n;
|
ctx->iaoq_b = ctx->iaoq_n;
|
||||||
ctx->base.pc_next += 4;
|
ctx->base.pc_next += 4;
|
||||||
|
|
||||||
if (ret == DISAS_NORETURN || ret == DISAS_IAQ_N_UPDATED) {
|
switch (ret) {
|
||||||
return;
|
case DISAS_NORETURN:
|
||||||
}
|
case DISAS_IAQ_N_UPDATED:
|
||||||
if (ctx->iaoq_f == -1) {
|
break;
|
||||||
tcg_gen_mov_reg(cpu_iaoq_f, cpu_iaoq_b);
|
|
||||||
copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
|
case DISAS_NEXT:
|
||||||
|
case DISAS_IAQ_N_STALE:
|
||||||
|
case DISAS_IAQ_N_STALE_EXIT:
|
||||||
|
if (ctx->iaoq_f == -1) {
|
||||||
|
tcg_gen_mov_reg(cpu_iaoq_f, cpu_iaoq_b);
|
||||||
|
copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
|
tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
|
||||||
#endif
|
#endif
|
||||||
nullify_save(ctx);
|
nullify_save(ctx);
|
||||||
ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
|
ctx->base.is_jmp = (ret == DISAS_IAQ_N_STALE_EXIT
|
||||||
} else if (ctx->iaoq_b == -1) {
|
? DISAS_EXIT
|
||||||
tcg_gen_mov_reg(cpu_iaoq_b, ctx->iaoq_n_var);
|
: DISAS_IAQ_N_UPDATED);
|
||||||
|
} else if (ctx->iaoq_b == -1) {
|
||||||
|
tcg_gen_mov_reg(cpu_iaoq_b, ctx->iaoq_n_var);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4252,11 +4265,12 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
|
||||||
case DISAS_IAQ_N_UPDATED:
|
case DISAS_IAQ_N_UPDATED:
|
||||||
if (ctx->base.singlestep_enabled) {
|
if (ctx->base.singlestep_enabled) {
|
||||||
gen_excp_1(EXCP_DEBUG);
|
gen_excp_1(EXCP_DEBUG);
|
||||||
} else if (is_jmp == DISAS_IAQ_N_STALE_EXIT) {
|
} else if (is_jmp != DISAS_IAQ_N_STALE_EXIT) {
|
||||||
tcg_gen_exit_tb(NULL, 0);
|
|
||||||
} else {
|
|
||||||
tcg_gen_lookup_and_goto_ptr();
|
tcg_gen_lookup_and_goto_ptr();
|
||||||
}
|
}
|
||||||
|
/* FALLTHRU */
|
||||||
|
case DISAS_EXIT:
|
||||||
|
tcg_gen_exit_tb(NULL, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
|
|
Loading…
Reference in New Issue