target/hppa: Simplify TB end

Minimize the amount of code in hppa_tr_translate_insn advancing the
insn queue for the next insn.  Move the goto_tb path to hppa_tr_tb_stop.

Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-03-22 20:13:40 -10:00
parent d08ad0e0f0
commit dbdccbdf81

View File

@ -4700,54 +4700,31 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
} }
} }
/* Advance the insn queue. Note that this check also detects /* If the TranslationBlock must end, do so. */
a priority change within the instruction queue. */ ctx->base.pc_next += 4;
if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) { if (ret != DISAS_NEXT) {
if (use_goto_tb(ctx, ctx->iaoq_b, ctx->iaoq_n) return;
&& (ctx->null_cond.c == TCG_COND_NEVER
|| ctx->null_cond.c == TCG_COND_ALWAYS)) {
nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
ctx->base.is_jmp = ret = DISAS_NORETURN;
} else {
ctx->base.is_jmp = ret = DISAS_IAQ_N_STALE;
}
} }
/* Note this also detects a priority change. */
if (ctx->iaoq_b != ctx->iaoq_f + 4) {
ctx->base.is_jmp = DISAS_IAQ_N_STALE;
return;
}
/*
* Advance the insn queue.
* The only exit now is DISAS_TOO_MANY from the translator loop.
*/
ctx->iaoq_f = ctx->iaoq_b; ctx->iaoq_f = ctx->iaoq_b;
ctx->iaoq_b = ctx->iaoq_n; ctx->iaoq_b = ctx->iaoq_n;
ctx->base.pc_next += 4; if (ctx->iaoq_b == -1) {
if (ctx->iaoq_n_var) {
switch (ret) { copy_iaoq_entry(ctx, cpu_iaoq_b, -1, ctx->iaoq_n_var);
case DISAS_NORETURN: } else {
case DISAS_IAQ_N_UPDATED: tcg_gen_addi_i64(cpu_iaoq_b, cpu_iaoq_b, 4);
break; tcg_gen_andi_i64(cpu_iaoq_b, cpu_iaoq_b,
gva_offset_mask(ctx->tb_flags));
case DISAS_NEXT:
case DISAS_IAQ_N_STALE:
case DISAS_IAQ_N_STALE_EXIT:
if (ctx->iaoq_f == -1) {
install_iaq_entries(ctx, -1, cpu_iaoq_b,
ctx->iaoq_n, ctx->iaoq_n_var);
#ifndef CONFIG_USER_ONLY
tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
#endif
nullify_save(ctx);
ctx->base.is_jmp = (ret == DISAS_IAQ_N_STALE_EXIT
? DISAS_EXIT
: DISAS_IAQ_N_UPDATED);
} else if (ctx->iaoq_b == -1) {
if (ctx->iaoq_n_var) {
copy_iaoq_entry(ctx, cpu_iaoq_b, -1, ctx->iaoq_n_var);
} else {
tcg_gen_addi_i64(cpu_iaoq_b, cpu_iaoq_b, 4);
tcg_gen_andi_i64(cpu_iaoq_b, cpu_iaoq_b,
gva_offset_mask(ctx->tb_flags));
}
} }
break;
default:
g_assert_not_reached();
} }
} }
@ -4755,23 +4732,51 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
{ {
DisasContext *ctx = container_of(dcbase, DisasContext, base); DisasContext *ctx = container_of(dcbase, DisasContext, base);
DisasJumpType is_jmp = ctx->base.is_jmp; DisasJumpType is_jmp = ctx->base.is_jmp;
uint64_t fi, bi;
TCGv_i64 fv, bv;
TCGv_i64 fs;
/* Assume the insn queue has not been advanced. */
fi = ctx->iaoq_b;
fv = cpu_iaoq_b;
fs = fi == -1 ? cpu_iasq_b : NULL;
bi = ctx->iaoq_n;
bv = ctx->iaoq_n_var;
switch (is_jmp) { switch (is_jmp) {
case DISAS_NORETURN: case DISAS_NORETURN:
break; break;
case DISAS_TOO_MANY: case DISAS_TOO_MANY:
case DISAS_IAQ_N_STALE: /* The insn queue has not been advanced. */
case DISAS_IAQ_N_STALE_EXIT: bi = fi;
install_iaq_entries(ctx, ctx->iaoq_f, cpu_iaoq_f, bv = fv;
ctx->iaoq_b, cpu_iaoq_b); fi = ctx->iaoq_f;
nullify_save(ctx); fv = NULL;
fs = NULL;
/* FALLTHRU */ /* FALLTHRU */
case DISAS_IAQ_N_UPDATED: case DISAS_IAQ_N_STALE:
if (is_jmp != DISAS_IAQ_N_STALE_EXIT) { if (use_goto_tb(ctx, fi, bi)
tcg_gen_lookup_and_goto_ptr(); && (ctx->null_cond.c == TCG_COND_NEVER
|| ctx->null_cond.c == TCG_COND_ALWAYS)) {
nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
gen_goto_tb(ctx, 0, fi, bi);
break; break;
} }
/* FALLTHRU */ /* FALLTHRU */
case DISAS_IAQ_N_STALE_EXIT:
install_iaq_entries(ctx, fi, fv, bi, bv);
if (fs) {
tcg_gen_mov_i64(cpu_iasq_f, fs);
}
nullify_save(ctx);
if (is_jmp == DISAS_IAQ_N_STALE_EXIT) {
tcg_gen_exit_tb(NULL, 0);
break;
}
/* FALLTHRU */
case DISAS_IAQ_N_UPDATED:
tcg_gen_lookup_and_goto_ptr();
break;
case DISAS_EXIT: case DISAS_EXIT:
tcg_gen_exit_tb(NULL, 0); tcg_gen_exit_tb(NULL, 0);
break; break;