target/i386: Return bool from disas_insn

Instead of returning the new pc, which is present in
DisasContext, return true if an insn was translated.
This is false when we detect a page crossing and must
undo the insn under translation.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20221001140935.465607-3-richard.henderson@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
master
Richard Henderson 2022-10-01 07:09:11 -07:00 committed by Paolo Bonzini
parent ddf83b35bd
commit f66c8e8cd9
1 changed files with 23 additions and 21 deletions

View File

@ -4707,7 +4707,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b)
/* convert one instruction. s->base.is_jmp is set if the translation must
be stopped. Return the next pc value */
static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
static bool disas_insn(DisasContext *s, CPUState *cpu)
{
CPUX86State *env = cpu->env_ptr;
int b, prefixes;
@ -4734,15 +4734,16 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
break;
case 1:
gen_exception_gpf(s);
return s->pc;
return true;
case 2:
/* Restore state that may affect the next instruction. */
s->pc = s->base.pc_next;
s->cc_op_dirty = orig_cc_op_dirty;
s->cc_op = orig_cc_op;
s->base.num_insns--;
tcg_remove_ops_after(s->prev_insn_end);
s->base.is_jmp = DISAS_TOO_MANY;
return s->base.pc_next;
return false;
default:
g_assert_not_reached();
}
@ -8644,13 +8645,13 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
default:
goto unknown_op;
}
return s->pc;
return true;
illegal_op:
gen_illegal_opcode(s);
return s->pc;
return true;
unknown_op:
gen_unknown_opcode(env, s);
return s->pc;
return true;
}
void tcg_x86_init(void)
@ -8815,7 +8816,6 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
target_ulong pc_next;
#ifdef TARGET_VSYSCALL_PAGE
/*
@ -8828,21 +8828,23 @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
}
#endif
pc_next = disas_insn(dc, cpu);
dc->base.pc_next = pc_next;
if (disas_insn(dc, cpu)) {
target_ulong pc_next = dc->pc;
dc->base.pc_next = pc_next;
if (dc->base.is_jmp == DISAS_NEXT) {
if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
/*
* If single step mode, we generate only one instruction and
* generate an exception.
* If irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
* the flag and abort the translation to give the irqs a
* chance to happen.
*/
dc->base.is_jmp = DISAS_TOO_MANY;
} else if (!is_same_page(&dc->base, pc_next)) {
dc->base.is_jmp = DISAS_TOO_MANY;
if (dc->base.is_jmp == DISAS_NEXT) {
if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
/*
* If single step mode, we generate only one instruction and
* generate an exception.
* If irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
* the flag and abort the translation to give the irqs a
* chance to happen.
*/
dc->base.is_jmp = DISAS_TOO_MANY;
} else if (!is_same_page(&dc->base, pc_next)) {
dc->base.is_jmp = DISAS_TOO_MANY;
}
}
}
}