From bbba9594e84f60707558cce9cd3e4d70b9bd0fec Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 10 Apr 2024 12:29:52 +0200 Subject: [PATCH] target/i386: cleanup cc_op changes for REP/REPZ/REPNZ gen_update_cc_op must be called before control flow splits. Do it where the jump on ECX!=0 is translated. On the other hand, remove the call before gen_jcc1, which takes care of it already, and explain why REPZ/REPNZ need not use CC_OP_DYNAMIC---the translation block ends before any control-flow-dependent cc_op could be observed. Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 3f1d2858fc..466fee38c0 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -1242,11 +1242,15 @@ static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1) } /* XXX: does not work with gdbstub "ice" single step - not a - serious problem */ + serious problem. The caller can jump to the returned label + to stop the REP but, if the flags have changed, it has to call + gen_update_cc_op before doing so. */ static TCGLabel *gen_jz_ecx_string(DisasContext *s) { TCGLabel *l1 = gen_new_label(); TCGLabel *l2 = gen_new_label(); + + gen_update_cc_op(s); gen_op_jnz_ecx(s, l1); gen_set_label(l2); gen_jmp_rel_csize(s, 0, 1); @@ -1342,7 +1346,6 @@ static void gen_repz(DisasContext *s, MemOp ot, void (*fn)(DisasContext *s, MemOp ot)) { TCGLabel *l2; - gen_update_cc_op(s); l2 = gen_jz_ecx_string(s); fn(s, ot); gen_op_add_reg_im(s, s->aflag, R_ECX, -1); @@ -1364,15 +1367,18 @@ static void gen_repz2(DisasContext *s, MemOp ot, int nz, void (*fn)(DisasContext *s, MemOp ot)) { TCGLabel *l2; - gen_update_cc_op(s); l2 = gen_jz_ecx_string(s); fn(s, ot); gen_op_add_reg_im(s, s->aflag, R_ECX, -1); - gen_update_cc_op(s); gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); if (s->repz_opt) { gen_op_jz_ecx(s, l2); } + /* + * Only one iteration is done at a time, so the translation + * block ends unconditionally after this instruction and there + * is no control flow junction - no need to set CC_OP_DYNAMIC. + */ gen_jmp_rel_csize(s, -cur_insn_len(s), 0); }