Il dom 15 dic 2024, 15:45 Richard Henderson <[email protected]>
ha scritto:
> On 12/15/24 03:06, Paolo Bonzini wrote:
> > fn(s, ot);
> > gen_op_add_reg_im(s, s->aflag, R_ECX, -1);
> > + gen_update_cc_op(s);
> > +
> > + /* Leave if REP condition fails. */
> > if (is_repz_nz) {
> > int nz = (s->prefix & PREFIX_REPNZ) ? 1 : 0;
> > - gen_jcc(s, (JCC_Z << 1) | (nz ^ 1), done);
> > + gen_jcc_noeob(s, (JCC_Z << 1) | (nz ^ 1), done);
>
> The comment in gen_jcc would still seem to apply:
>
> CCPrepare cc = gen_prepare_cc(s, b, NULL);
>
> /*
> * Note that this must be _after_ gen_prepare_cc, because it
> * can change the cc_op from CC_OP_DYNAMIC to CC_OP_EFLAGS!
> */
> gen_update_cc_op(s);
>
> via any path through gen_prepare_cc that reaches gen_compute_eflags.
>
> However! Because this is JCC_Z, we will never call gen_compute_eflags, we
> will always go
> through the gen_prepare_eflags_z, which doesn't have the same problem.
>
Or more simply, fn(s, ot) must have left CC_OP_SUBx in cc_op.
This subtlety deserves a comment and maybe an assert. Perhaps
>
> gen_jcc_noeob(...);
> assert(!s->cc_op_dirty);
>
Either that or an assert(s->cc_op != CC_OP_DYNAMIC) before the call to
gen_jcc_noeob().
Paolo
>
> r~
>
>