diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 3e46be8d78..ee53623439 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -113,7 +113,6 @@ typedef struct DisasContext { #endif bool vex_w; /* used by AVX even on 32-bit processors */ bool jmp_opt; /* use direct block chaining for direct jumps */ - bool repz_opt; /* optimize jumps within repz instructions */ bool cc_op_dirty; CCOp cc_op; /* current CC operation */ @@ -1206,23 +1205,6 @@ static inline void gen_jcc(DisasContext *s, int b, TCGLabel *l1) } } -/* XXX: does not work with gdbstub "ice" single step - not a - 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); - gen_set_label(l1); - return l2; -} - static void gen_stos(DisasContext *s, MemOp ot) { gen_string_movl_A0_EDI(s); @@ -1314,27 +1296,25 @@ static void do_gen_rep(DisasContext *s, MemOp ot, void (*fn)(DisasContext *s, MemOp ot), bool is_repz_nz) { - TCGLabel *l2; - l2 = gen_jz_ecx_string(s); + TCGLabel *done = gen_new_label(); + + gen_update_cc_op(s); + gen_op_jz_ecx(s, done); + fn(s, ot); gen_op_add_reg_im(s, s->aflag, R_ECX, -1); if (is_repz_nz) { int nz = (s->prefix & PREFIX_REPNZ) ? 1 : 0; - gen_jcc(s, (JCC_Z << 1) | (nz ^ 1), l2); + gen_jcc(s, (JCC_Z << 1) | (nz ^ 1), done); } - /* - * A loop would cause two single step exceptions if ECX = 1 - * before rep string_insn - */ - if (s->repz_opt) { - gen_op_jz_ecx(s, l2); - } - /* - * For CMPS/SCAS there is no need to set CC_OP_DYNAMIC: only one iteration - * is done at a time, so the translation block ends unconditionally after - * this instruction and there is no control flow junction. - */ + + /* Go to the main loop but reenter the same instruction. */ gen_jmp_rel_csize(s, -cur_insn_len(s), 0); + + /* CX/ECX/RCX is zero, or REPZ/REPNZ broke the repetition. */ + gen_set_label(done); + set_cc_op(s, CC_OP_DYNAMIC); + gen_jmp_rel_csize(s, 0, 1); } static void gen_repz(DisasContext *s, MemOp ot, @@ -3665,20 +3645,6 @@ static void i386_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) dc->cpuid_xsave_features = env->features[FEAT_XSAVE]; dc->jmp_opt = !((cflags & CF_NO_GOTO_TB) || (flags & (HF_RF_MASK | HF_TF_MASK | HF_INHIBIT_IRQ_MASK))); - /* - * If jmp_opt, we want to handle each string instruction individually. - * For icount also disable repz optimization so that each iteration - * is accounted separately. - * - * FIXME: this is messy; it makes REP string instructions a lot less - * efficient than they should be and it gets in the way of correct - * handling of RF (interrupts or traps arriving after any iteration - * of a repeated string instruction but the last should set RF to 1). - * Perhaps it would be more efficient if REP string instructions were - * always at the beginning of the TB, or even their own TB? That - * would even allow accounting up to 64k iterations at once for icount. - */ - dc->repz_opt = !dc->jmp_opt && !(cflags & CF_USE_ICOUNT); dc->T0 = tcg_temp_new(); dc->T1 = tcg_temp_new();