X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/9f0355b590ac523d0c4e67c416c3f9cf7af3d574..4e5e1215156662b2b153255c49d4640d82c5568b:/target-i386/translate.c diff --git a/target-i386/translate.c b/target-i386/translate.c index 3aa52eb795..ef10e685cc 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -21,16 +21,19 @@ #include #include #include -#include #include "qemu/host-utils.h" #include "cpu.h" #include "disas/disas.h" #include "tcg-op.h" +#include "exec/cpu_ldst.h" #include "exec/helper-proto.h" #include "exec/helper-gen.h" +#include "trace-tcg.h" + + #define PREFIX_REPZ 0x01 #define PREFIX_REPNZ 0x02 #define PREFIX_LOCK 0x04 @@ -72,8 +75,6 @@ static TCGv_ptr cpu_ptr0, cpu_ptr1; static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32; static TCGv_i64 cpu_tmp1_i64; -static uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; - #include "exec/gen-icount.h" #ifdef TARGET_X86_64 @@ -111,6 +112,7 @@ typedef struct DisasContext { int tf; /* TF cpu flag */ int singlestep_enabled; /* "hardware" single step enabled */ int jmp_opt; /* use direct block chaining for direct jumps */ + int repz_opt; /* optimize jumps within repz instructions */ int mem_index; /* select memory access functions */ uint64_t flags; /* all execution flags */ struct TranslationBlock *tb; @@ -608,14 +610,14 @@ static void gen_exts(TCGMemOp ot, TCGv reg) gen_ext_tl(reg, reg, ot, true); } -static inline void gen_op_jnz_ecx(TCGMemOp size, int label1) +static inline void gen_op_jnz_ecx(TCGMemOp size, TCGLabel *label1) { tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]); gen_extu(size, cpu_tmp0); tcg_gen_brcondi_tl(TCG_COND_NE, cpu_tmp0, 0, label1); } -static inline void gen_op_jz_ecx(TCGMemOp size, int label1) +static inline void gen_op_jz_ecx(TCGMemOp size, TCGLabel *label1) { tcg_gen_mov_tl(cpu_tmp0, cpu_regs[R_ECX]); gen_extu(size, cpu_tmp0); @@ -626,13 +628,13 @@ static void gen_helper_in_func(TCGMemOp ot, TCGv v, TCGv_i32 n) { switch (ot) { case MO_8: - gen_helper_inb(v, n); + gen_helper_inb(v, cpu_env, n); break; case MO_16: - gen_helper_inw(v, n); + gen_helper_inw(v, cpu_env, n); break; case MO_32: - gen_helper_inl(v, n); + gen_helper_inl(v, cpu_env, n); break; default: tcg_abort(); @@ -643,13 +645,13 @@ static void gen_helper_out_func(TCGMemOp ot, TCGv_i32 v, TCGv_i32 n) { switch (ot) { case MO_8: - gen_helper_outb(v, n); + gen_helper_outb(cpu_env, v, n); break; case MO_16: - gen_helper_outw(v, n); + gen_helper_outw(cpu_env, v, n); break; case MO_32: - gen_helper_outl(v, n); + gen_helper_outl(cpu_env, v, n); break; default: tcg_abort(); @@ -659,14 +661,9 @@ static void gen_helper_out_func(TCGMemOp ot, TCGv_i32 v, TCGv_i32 n) static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip, uint32_t svm_flags) { - int state_saved; target_ulong next_eip; - state_saved = 0; if (s->pe && (s->cpl > s->iopl || s->vm86)) { - gen_update_cc_op(s); - gen_jmp_im(cur_eip); - state_saved = 1; tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); switch (ot) { case MO_8: @@ -683,10 +680,8 @@ static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip, } } if(s->flags & HF_SVMI_MASK) { - if (!state_saved) { - gen_update_cc_op(s); - gen_jmp_im(cur_eip); - } + gen_update_cc_op(s); + gen_jmp_im(cur_eip); svm_flags |= (1 << (4 + ot)); next_eip = s->pc - s->cs_base; tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); @@ -1073,7 +1068,7 @@ static inline void gen_compute_eflags_c(DisasContext *s, TCGv reg) /* generate a conditional jump to label 'l1' according to jump opcode value 'b'. In the fast case, T0 is guaranted not to be used. */ -static inline void gen_jcc1_noeob(DisasContext *s, int b, int l1) +static inline void gen_jcc1_noeob(DisasContext *s, int b, TCGLabel *l1) { CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]); @@ -1091,7 +1086,7 @@ static inline void gen_jcc1_noeob(DisasContext *s, int b, int l1) /* Generate a conditional jump to label 'l1' according to jump opcode value 'b'. In the fast case, T0 is guaranted not to be used. A translation block must end soon. */ -static inline void gen_jcc1(DisasContext *s, int b, int l1) +static inline void gen_jcc1(DisasContext *s, int b, TCGLabel *l1) { CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]); @@ -1110,12 +1105,10 @@ static inline void gen_jcc1(DisasContext *s, int b, int l1) /* XXX: does not work with gdbstub "ice" single step - not a serious problem */ -static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) +static TCGLabel *gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) { - int l1, l2; - - l1 = gen_new_label(); - l2 = gen_new_label(); + TCGLabel *l1 = gen_new_label(); + TCGLabel *l2 = gen_new_label(); gen_op_jnz_ecx(s->aflag, l1); gen_set_label(l2); gen_jmp_tb(s, next_eip, 1); @@ -1163,8 +1156,9 @@ static inline void gen_cmps(DisasContext *s, TCGMemOp ot) static inline void gen_ins(DisasContext *s, TCGMemOp ot) { - if (use_icount) + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_start(); + } gen_string_movl_A0_EDI(s); /* Note: we must do this dummy write first to be restartable in case of page fault. */ @@ -1176,14 +1170,16 @@ static inline void gen_ins(DisasContext *s, TCGMemOp ot) gen_op_st_v(s, ot, cpu_T[0], cpu_A0); gen_op_movl_T0_Dshift(ot); gen_op_add_reg_T0(s->aflag, R_EDI); - if (use_icount) + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_end(); + } } static inline void gen_outs(DisasContext *s, TCGMemOp ot) { - if (use_icount) + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_start(); + } gen_string_movl_A0_ESI(s); gen_op_ld_v(s, ot, cpu_T[0], cpu_A0); @@ -1194,8 +1190,9 @@ static inline void gen_outs(DisasContext *s, TCGMemOp ot) gen_op_movl_T0_Dshift(ot); gen_op_add_reg_T0(s->aflag, R_ESI); - if (use_icount) + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_end(); + } } /* same method as Valgrind : we generate jumps to current or next @@ -1204,14 +1201,14 @@ static inline void gen_outs(DisasContext *s, TCGMemOp ot) static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \ target_ulong cur_eip, target_ulong next_eip) \ { \ - int l2;\ + TCGLabel *l2; \ gen_update_cc_op(s); \ l2 = gen_jz_ecx_string(s, next_eip); \ gen_ ## op(s, ot); \ gen_op_add_reg_im(s->aflag, R_ECX, -1); \ /* a loop would cause two single step exceptions if ECX = 1 \ before rep string_insn */ \ - if (!s->jmp_opt) \ + if (s->repz_opt) \ gen_op_jz_ecx(s->aflag, l2); \ gen_jmp(s, cur_eip); \ } @@ -1222,14 +1219,14 @@ static inline void gen_repz_ ## op(DisasContext *s, TCGMemOp ot, \ target_ulong next_eip, \ int nz) \ { \ - int l2;\ + TCGLabel *l2; \ gen_update_cc_op(s); \ l2 = gen_jz_ecx_string(s, next_eip); \ gen_ ## op(s, ot); \ gen_op_add_reg_im(s->aflag, R_ECX, -1); \ gen_update_cc_op(s); \ gen_jcc1(s, (JCC_Z << 1) | (nz ^ 1), l2); \ - if (!s->jmp_opt) \ + if (s->repz_opt) \ gen_op_jz_ecx(s->aflag, l2); \ gen_jmp(s, cur_eip); \ } @@ -1505,14 +1502,6 @@ static void gen_shift_rm_im(DisasContext *s, TCGMemOp ot, int op1, int op2, } } -static inline void tcg_gen_lshift(TCGv ret, TCGv arg1, target_long arg2) -{ - if (arg2 >= 0) - tcg_gen_shli_tl(ret, arg1, arg2); - else - tcg_gen_shri_tl(ret, arg1, -arg2); -} - static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right) { target_ulong mask = (ot == MO_64 ? 0x3f : 0x1f); @@ -2226,7 +2215,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip) static inline void gen_jcc(DisasContext *s, int b, target_ulong val, target_ulong next_eip) { - int l1, l2; + TCGLabel *l1, *l2; if (s->jmp_opt) { l1 = gen_new_label(); @@ -2299,12 +2288,9 @@ static inline void gen_op_movl_seg_T0_vm(int seg_reg) /* move T0 to seg_reg and compute if the CPU state may change. Never call this function with seg_reg == R_CS */ -static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip) +static void gen_movl_seg_T0(DisasContext *s, int seg_reg) { if (s->pe && !s->vm86) { - /* XXX: optimize by finding processor state dynamically */ - gen_update_cc_op(s); - gen_jmp_im(cur_eip); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32); /* abort translation because the addseg value may change or @@ -2620,10 +2606,10 @@ static inline void gen_sto_env_A0(DisasContext *s, int offset) static inline void gen_op_movo(int d_offset, int s_offset) { - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); - tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8); - tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8); + tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(0))); + tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(0))); + tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(1))); + tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(1))); } static inline void gen_op_movq(int d_offset, int s_offset) @@ -3073,7 +3059,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, goto illegal_op; gen_lea_modrm(env, s, modrm); if (b1 & 1) { - gen_stq_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); + gen_stq_env_A0(s, offsetof(CPUX86State, + xmm_regs[reg].XMM_Q(0))); } else { tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, xmm_regs[reg].XMM_L(0))); @@ -4412,9 +4399,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, target_ulong next_eip, tval; int rex_w, rex_r; - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { - tcg_gen_debug_insn_start(pc_start); - } s->pc = pc_start; prefixes = 0; s->override = -1; @@ -4842,21 +4826,17 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, case 6: /* div */ switch(ot) { case MO_8: - gen_jmp_im(pc_start - s->cs_base); gen_helper_divb_AL(cpu_env, cpu_T[0]); break; case MO_16: - gen_jmp_im(pc_start - s->cs_base); gen_helper_divw_AX(cpu_env, cpu_T[0]); break; default: case MO_32: - gen_jmp_im(pc_start - s->cs_base); gen_helper_divl_EAX(cpu_env, cpu_T[0]); break; #ifdef TARGET_X86_64 case MO_64: - gen_jmp_im(pc_start - s->cs_base); gen_helper_divq_EAX(cpu_env, cpu_T[0]); break; #endif @@ -4865,21 +4845,17 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, case 7: /* idiv */ switch(ot) { case MO_8: - gen_jmp_im(pc_start - s->cs_base); gen_helper_idivb_AL(cpu_env, cpu_T[0]); break; case MO_16: - gen_jmp_im(pc_start - s->cs_base); gen_helper_idivw_AX(cpu_env, cpu_T[0]); break; default: case MO_32: - gen_jmp_im(pc_start - s->cs_base); gen_helper_idivl_EAX(cpu_env, cpu_T[0]); break; #ifdef TARGET_X86_64 case MO_64: - gen_jmp_im(pc_start - s->cs_base); gen_helper_idivq_EAX(cpu_env, cpu_T[0]); break; #endif @@ -4952,12 +4928,10 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0); do_lcall: if (s->pe && !s->vm86) { - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1], tcg_const_i32(dflag - 1), - tcg_const_i32(s->pc - pc_start)); + tcg_const_tl(s->pc - s->cs_base)); } else { tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); gen_helper_lcall_real(cpu_env, cpu_tmp2_i32, cpu_T[1], @@ -4979,11 +4953,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0); do_ljmp: if (s->pe && !s->vm86) { - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1], - tcg_const_i32(s->pc - pc_start)); + tcg_const_tl(s->pc - s->cs_base)); } else { gen_op_movl_seg_T0_vm(R_CS); gen_op_jmp_v(cpu_T[1]); @@ -5150,7 +5122,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, case 0x1b0: case 0x1b1: /* cmpxchg Ev, Gv */ { - int label1, label2; + TCGLabel *label1, *label2; TCGv t0, t1, t2, a0; ot = mo_b_d(b, dflag); @@ -5212,8 +5184,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, if (dflag == MO_64) { if (!(s->cpuid_ext_features & CPUID_EXT_CX16)) goto illegal_op; - gen_jmp_im(pc_start - s->cs_base); - gen_update_cc_op(s); gen_lea_modrm(env, s, modrm); gen_helper_cmpxchg16b(cpu_env, cpu_A0); } else @@ -5221,8 +5191,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, { if (!(s->cpuid_features & CPUID_CX8)) goto illegal_op; - gen_jmp_im(pc_start - s->cs_base); - gen_update_cc_op(s); gen_lea_modrm(env, s, modrm); gen_helper_cmpxchg8b(cpu_env, cpu_A0); } @@ -5324,7 +5292,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, goto illegal_op; reg = b >> 3; ot = gen_pop_T0(s); - gen_movl_seg_T0(s, reg, pc_start - s->cs_base); + gen_movl_seg_T0(s, reg); gen_pop_update(s, ot); if (reg == R_SS) { /* if reg == SS, inhibit interrupts/trace. */ @@ -5342,7 +5310,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, case 0x1a1: /* pop fs */ case 0x1a9: /* pop gs */ ot = gen_pop_T0(s); - gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base); + gen_movl_seg_T0(s, (b >> 3) & 7); gen_pop_update(s, ot); if (s->is_jmp) { gen_jmp_im(s->pc - s->cs_base); @@ -5393,7 +5361,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, if (reg >= 6 || reg == R_CS) goto illegal_op; gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0); - gen_movl_seg_T0(s, reg, pc_start - s->cs_base); + gen_movl_seg_T0(s, reg); if (reg == R_SS) { /* if reg == SS, inhibit interrupts/trace */ /* If several instructions disable interrupts, only the @@ -5605,7 +5573,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_add_A0_im(s, 1 << ot); /* load the segment first to handle exceptions properly */ gen_op_ld_v(s, MO_16, cpu_T[0], cpu_A0); - gen_movl_seg_T0(s, op, pc_start - s->cs_base); + gen_movl_seg_T0(s, op); /* then put the data */ gen_op_mov_reg_v(ot, reg, cpu_T[1]); if (s->is_jmp) { @@ -5837,8 +5805,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, } break; case 0x0c: /* fldenv mem */ - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1)); break; case 0x0d: /* fldcw mem */ @@ -5847,8 +5813,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_helper_fldcw(cpu_env, cpu_tmp2_i32); break; case 0x0e: /* fnstenv mem */ - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1)); break; case 0x0f: /* fnstcw mem */ @@ -5857,24 +5821,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, s->mem_index, MO_LEUW); break; case 0x1d: /* fldt mem */ - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_fldt_ST0(cpu_env, cpu_A0); break; case 0x1f: /* fstpt mem */ - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_fstt_ST0(cpu_env, cpu_A0); gen_helper_fpop(cpu_env); break; case 0x2c: /* frstor mem */ - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1)); break; case 0x2e: /* fnsave mem */ - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1)); break; case 0x2f: /* fnstsw mem */ @@ -5883,13 +5839,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, s->mem_index, MO_LEUW); break; case 0x3c: /* fbld */ - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_fbld_ST0(cpu_env, cpu_A0); break; case 0x3e: /* fbstp */ - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_fbst_ST0(cpu_env, cpu_A0); gen_helper_fpop(cpu_env); break; @@ -5924,8 +5876,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, switch(rm) { case 0: /* fnop */ /* check exceptions (FreeBSD FPU probe) */ - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_fwait(cpu_env); break; default: @@ -6194,7 +6144,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, case 0x10 ... 0x13: /* fcmovxx */ case 0x18 ... 0x1b: { - int op1, l1; + int op1; + TCGLabel *l1; static const uint8_t fcmov_cc[8] = { (JCC_B << 1), (JCC_Z << 1), @@ -6281,7 +6232,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); } else { gen_ins(s, ot); - if (use_icount) { + if (s->tb->cflags & CF_USE_ICOUNT) { gen_jmp(s, s->pc - s->cs_base); } } @@ -6296,7 +6247,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); } else { gen_outs(s, ot); - if (use_icount) { + if (s->tb->cflags & CF_USE_ICOUNT) { gen_jmp(s, s->pc - s->cs_base); } } @@ -6312,12 +6263,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, tcg_gen_movi_tl(cpu_T[0], val); gen_check_io(s, ot, pc_start - s->cs_base, SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); - if (use_icount) + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_start(); + } tcg_gen_movi_i32(cpu_tmp2_i32, val); gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32); gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]); - if (use_icount) { + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); } @@ -6331,12 +6283,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, svm_is_rep(prefixes)); gen_op_mov_v_reg(ot, cpu_T[1], R_EAX); - if (use_icount) + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_start(); + } tcg_gen_movi_i32(cpu_tmp2_i32, val); tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]); gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); - if (use_icount) { + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); } @@ -6347,12 +6300,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, tcg_gen_ext16u_tl(cpu_T[0], cpu_regs[R_EDX]); gen_check_io(s, ot, pc_start - s->cs_base, SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); - if (use_icount) + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_start(); + } tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); gen_helper_in_func(ot, cpu_T[1], cpu_tmp2_i32); gen_op_mov_reg_v(ot, R_EAX, cpu_T[1]); - if (use_icount) { + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); } @@ -6365,12 +6319,13 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, svm_is_rep(prefixes)); gen_op_mov_v_reg(ot, cpu_T[1], R_EAX); - if (use_icount) + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_start(); + } tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[1]); gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); - if (use_icount) { + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); } @@ -6436,8 +6391,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, set_cc_op(s, CC_OP_EFLAGS); } } else { - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1), tcg_const_i32(s->pc - s->cs_base)); set_cc_op(s, CC_OP_EFLAGS); @@ -6890,8 +6843,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, (HF_MP_MASK | HF_TS_MASK)) { gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); } else { - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_fwait(cpu_env); } break; @@ -6920,7 +6871,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_debug(s, pc_start - s->cs_base); #else /* start debug */ - tb_flush(env); + tb_flush(CPU(x86_env_get_cpu(env))); qemu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM); #endif break; @@ -6975,7 +6926,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, goto illegal_op; gen_op_mov_v_reg(ot, cpu_T[0], reg); gen_lea_modrm(env, s, modrm); - gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); if (ot == MO_16) { gen_helper_boundw(cpu_env, cpu_A0, cpu_tmp2_i32); @@ -7011,7 +6961,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, case 0xe2: /* loop */ case 0xe3: /* jecxz */ { - int l1, l2, l3; + TCGLabel *l1, *l2, *l3; tval = (int8_t)insn_get(env, s, MO_8); next_eip = s->pc - s->cs_base; @@ -7068,10 +7018,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, case 0x131: /* rdtsc */ gen_update_cc_op(s); gen_jmp_im(pc_start - s->cs_base); - if (use_icount) + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_start(); + } gen_helper_rdtsc(cpu_env); - if (use_icount) { + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); } @@ -7088,8 +7039,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, if (!s->pe) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_sysenter(cpu_env); gen_eob(s); } @@ -7101,8 +7050,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, if (!s->pe) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1)); gen_eob(s); } @@ -7119,8 +7066,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, if (!s->pe) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1)); /* condition codes are modified only in long mode */ if (s->lma) { @@ -7166,7 +7111,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, } else { gen_svm_check_intercept(s, pc_start, SVM_EXIT_LDTR_WRITE); gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0); - gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); gen_helper_lldt(cpu_env, cpu_tmp2_i32); } @@ -7187,7 +7131,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, } else { gen_svm_check_intercept(s, pc_start, SVM_EXIT_TR_WRITE); gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0); - gen_jmp_im(pc_start - s->cs_base); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]); gen_helper_ltr(cpu_env, cpu_tmp2_i32); } @@ -7454,10 +7397,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, goto illegal_op; gen_update_cc_op(s); gen_jmp_im(pc_start - s->cs_base); - if (use_icount) + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_start(); + } gen_helper_rdtscp(cpu_env); - if (use_icount) { + if (s->tb->cflags & CF_USE_ICOUNT) { gen_io_end(); gen_jmp(s, s->pc - s->cs_base); } @@ -7507,7 +7451,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, } else #endif { - int label1; + TCGLabel *label1; TCGv t0, t1, t2, a0; if (!s->pe || s->vm86) @@ -7556,7 +7500,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, case 0x102: /* lar */ case 0x103: /* lsl */ { - int label1; + TCGLabel *label1; TCGv t0; if (!s->pe || s->vm86) goto illegal_op; @@ -7719,8 +7663,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, break; } gen_lea_modrm(env, s, modrm); - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_fxsave(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64)); break; case 1: /* fxrstor */ @@ -7732,8 +7674,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, break; } gen_lea_modrm(env, s, modrm); - gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_fxrstor(cpu_env, cpu_A0, tcg_const_i32(dflag == MO_64)); break; case 2: /* ldmxcsr */ @@ -7892,22 +7832,18 @@ void optimize_flags_init(void) offsetof(CPUX86State, regs[i]), reg_names[i]); } + + helper_lock_init(); } /* generate intermediate code in gen_opc_buf and gen_opparam_buf for - basic block 'tb'. If search_pc is TRUE, also generate PC - information for each intermediate instruction. */ -static inline void gen_intermediate_code_internal(X86CPU *cpu, - TranslationBlock *tb, - bool search_pc) + basic block 'tb'. */ +void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) { + X86CPU *cpu = x86_env_get_cpu(env); CPUState *cs = CPU(cpu); - CPUX86State *env = &cpu->env; DisasContext dc1, *dc = &dc1; target_ulong pc_ptr; - uint16_t *gen_opc_end; - CPUBreakpoint *bp; - int j, lj; uint64_t flags; target_ulong pc_start; target_ulong cs_base; @@ -7937,7 +7873,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, /* select memory access functions */ dc->mem_index = 0; if (flags & HF_SOFTMMU_MASK) { - dc->mem_index = cpu_mmu_index(env); + dc->mem_index = cpu_mmu_index(env, false); } dc->cpuid_features = env->features[FEAT_1_EDX]; dc->cpuid_ext_features = env->features[FEAT_1_ECX]; @@ -7955,6 +7891,17 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, || (flags & HF_SOFTMMU_MASK) #endif ); + /* Do not optimize repz jumps at all in icount mode, because + rep movsS instructions are execured with different paths + in !repz_opt and repz_opt modes. The first one was used + always except single step mode. And this setting + disables jumps optimization and control paths become + equivalent in run and single step modes. + Now there will be no jump optimization for repz in + record/replay modes and there will always be an + additional step for ecx=0 when icount is enabled. + */ + dc->repz_opt = !dc->jmp_opt && !(tb->cflags & CF_USE_ICOUNT); #if 0 /* check addseg logic */ if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32)) @@ -7974,44 +7921,34 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, cpu_ptr1 = tcg_temp_new_ptr(); cpu_cc_srcT = tcg_temp_local_new(); - gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE; - dc->is_jmp = DISAS_NEXT; pc_ptr = pc_start; - lj = -1; num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; - if (max_insns == 0) + if (max_insns == 0) { max_insns = CF_COUNT_MASK; + } + if (max_insns > TCG_MAX_INSNS) { + max_insns = TCG_MAX_INSNS; + } - gen_tb_start(); + gen_tb_start(tb); for(;;) { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == pc_ptr && - !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) { - gen_debug(dc, pc_ptr - dc->cs_base); - break; - } - } - } - if (search_pc) { - j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; - if (lj < j) { - lj++; - while (lj < j) - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } - tcg_ctx.gen_opc_pc[lj] = pc_ptr; - gen_opc_cc_op[lj] = dc->cc_op; - tcg_ctx.gen_opc_instr_start[lj] = 1; - tcg_ctx.gen_opc_icount[lj] = num_insns; + tcg_gen_insn_start(pc_ptr, dc->cc_op); + num_insns++; + + /* If RF is set, suppress an internally generated breakpoint. */ + if (unlikely(cpu_breakpoint_test(cs, pc_ptr, + tb->flags & HF_RF_MASK + ? BP_GDB : BP_ANY))) { + gen_debug(dc, pc_ptr - dc->cs_base); + goto done_generating; } - if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) + if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { gen_io_start(); + } pc_ptr = disas_insn(env, dc, pc_ptr); - num_insns++; /* stop translation if indicated */ if (dc->is_jmp) break; @@ -8026,8 +7963,22 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, gen_eob(dc); break; } + /* Do not cross the boundary of the pages in icount mode, + it can cause an exception. Do it only when boundary is + crossed by the first instruction in the block. + If current instruction already crossed the bound - it's ok, + because an exception hasn't stopped this code. + */ + if ((tb->cflags & CF_USE_ICOUNT) + && ((pc_ptr & TARGET_PAGE_MASK) + != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK) + || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) { + gen_jmp_im(pc_ptr - dc->cs_base); + gen_eob(dc); + break; + } /* if too long translation, stop generation too */ - if (tcg_ctx.gen_opc_ptr >= gen_opc_end || + if (tcg_op_buf_full() || (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) || num_insns >= max_insns) { gen_jmp_im(pc_ptr - dc->cs_base); @@ -8042,15 +7993,8 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, } if (tb->cflags & CF_LAST_IO) gen_io_end(); +done_generating: gen_tb_end(tb, num_insns); - *tcg_ctx.gen_opc_ptr = INDEX_op_end; - /* we don't forget to fill the last values */ - if (search_pc) { - j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; - lj++; - while (lj <= j) - tcg_ctx.gen_opc_instr_start[lj++] = 0; - } #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { @@ -8063,47 +8007,21 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu, else #endif disas_flags = !dc->code32; - log_target_disas(env, pc_start, pc_ptr - pc_start, disas_flags); + log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags); qemu_log("\n"); } #endif - if (!search_pc) { - tb->size = pc_ptr - pc_start; - tb->icount = num_insns; - } + tb->size = pc_ptr - pc_start; + tb->icount = num_insns; } -void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) +void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, + target_ulong *data) { - gen_intermediate_code_internal(x86_env_get_cpu(env), tb, false); -} - -void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb) -{ - gen_intermediate_code_internal(x86_env_get_cpu(env), tb, true); -} - -void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos) -{ - int cc_op; -#ifdef DEBUG_DISAS - if (qemu_loglevel_mask(CPU_LOG_TB_OP)) { - int i; - qemu_log("RESTORE:\n"); - for(i = 0;i <= pc_pos; i++) { - if (tcg_ctx.gen_opc_instr_start[i]) { - qemu_log("0x%04x: " TARGET_FMT_lx "\n", i, - tcg_ctx.gen_opc_pc[i]); - } - } - qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n", - pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base, - (uint32_t)tb->cs_base); - } -#endif - env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base; - cc_op = gen_opc_cc_op[pc_pos]; - if (cc_op != CC_OP_DYNAMIC) + int cc_op = data[1]; + env->eip = data[0] - tb->cs_base; + if (cc_op != CC_OP_DYNAMIC) { env->cc_op = cc_op; + } }