target/i386: [tcg] Port to DisasContextBase

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002098212.22386.17313318023406046314.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Lluís Vilanova 2017-07-14 11:29:42 +03:00 committed by Richard Henderson
parent bb2e0039dc
commit 6cf147aa29
1 changed files with 69 additions and 71 deletions

View File

@ -95,6 +95,8 @@ static int x86_64_hregs;
#endif #endif
typedef struct DisasContext { typedef struct DisasContext {
DisasContextBase base;
/* current insn context */ /* current insn context */
int override; /* -1 if no override */ int override; /* -1 if no override */
int prefix; int prefix;
@ -102,8 +104,6 @@ typedef struct DisasContext {
TCGMemOp dflag; TCGMemOp dflag;
target_ulong pc_start; target_ulong pc_start;
target_ulong pc; /* pc = eip + cs_base */ target_ulong pc; /* pc = eip + cs_base */
int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
static state change (stop translation) */
/* current block context */ /* current block context */
target_ulong cs_base; /* base of CS segment */ target_ulong cs_base; /* base of CS segment */
int pe; /* protected mode */ int pe; /* protected mode */
@ -124,12 +124,10 @@ typedef struct DisasContext {
int cpl; int cpl;
int iopl; int iopl;
int tf; /* TF cpu flag */ int tf; /* TF cpu flag */
int singlestep_enabled; /* "hardware" single step enabled */
int jmp_opt; /* use direct block chaining for direct jumps */ int jmp_opt; /* use direct block chaining for direct jumps */
int repz_opt; /* optimize jumps within repz instructions */ int repz_opt; /* optimize jumps within repz instructions */
int mem_index; /* select memory access functions */ int mem_index; /* select memory access functions */
uint64_t flags; /* all execution flags */ uint64_t flags; /* all execution flags */
struct TranslationBlock *tb;
int popl_esp_hack; /* for correct popl with esp base handling */ int popl_esp_hack; /* for correct popl with esp base handling */
int rip_offset; /* only used in x86_64, but left for simplicity */ int rip_offset; /* only used in x86_64, but left for simplicity */
int cpuid_features; int cpuid_features;
@ -1119,7 +1117,7 @@ static void gen_bpt_io(DisasContext *s, TCGv_i32 t_port, int ot)
static inline void gen_ins(DisasContext *s, TCGMemOp ot) static inline void gen_ins(DisasContext *s, TCGMemOp ot)
{ {
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_start(); gen_io_start();
} }
gen_string_movl_A0_EDI(s); gen_string_movl_A0_EDI(s);
@ -1134,14 +1132,14 @@ static inline void gen_ins(DisasContext *s, TCGMemOp ot)
gen_op_movl_T0_Dshift(ot); gen_op_movl_T0_Dshift(ot);
gen_op_add_reg_T0(s->aflag, R_EDI); gen_op_add_reg_T0(s->aflag, R_EDI);
gen_bpt_io(s, cpu_tmp2_i32, ot); gen_bpt_io(s, cpu_tmp2_i32, ot);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_end(); gen_io_end();
} }
} }
static inline void gen_outs(DisasContext *s, TCGMemOp ot) static inline void gen_outs(DisasContext *s, TCGMemOp ot)
{ {
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_start(); gen_io_start();
} }
gen_string_movl_A0_ESI(s); gen_string_movl_A0_ESI(s);
@ -1154,7 +1152,7 @@ static inline void gen_outs(DisasContext *s, TCGMemOp ot)
gen_op_movl_T0_Dshift(ot); gen_op_movl_T0_Dshift(ot);
gen_op_add_reg_T0(s->aflag, R_ESI); gen_op_add_reg_T0(s->aflag, R_ESI);
gen_bpt_io(s, cpu_tmp2_i32, ot); gen_bpt_io(s, cpu_tmp2_i32, ot);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_end(); gen_io_end();
} }
} }
@ -2137,7 +2135,7 @@ static inline int insn_const_size(TCGMemOp ot)
static inline bool use_goto_tb(DisasContext *s, target_ulong pc) static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
{ {
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
return (pc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK) || return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) ||
(pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK); (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
#else #else
return true; return true;
@ -2152,8 +2150,8 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
/* jump to same page: we can use a direct jump */ /* jump to same page: we can use a direct jump */
tcg_gen_goto_tb(tb_num); tcg_gen_goto_tb(tb_num);
gen_jmp_im(eip); gen_jmp_im(eip);
tcg_gen_exit_tb((uintptr_t)s->tb + tb_num); tcg_gen_exit_tb((uintptr_t)s->base.tb + tb_num);
s->is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
} else { } else {
/* jump to another page */ /* jump to another page */
gen_jmp_im(eip); gen_jmp_im(eip);
@ -2244,12 +2242,12 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg)
stop as a special handling must be done to disable hardware stop as a special handling must be done to disable hardware
interrupts for the next instruction */ interrupts for the next instruction */
if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS)) { if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS)) {
s->is_jmp = DISAS_TOO_MANY; s->base.is_jmp = DISAS_TOO_MANY;
} }
} else { } else {
gen_op_movl_seg_T0_vm(seg_reg); gen_op_movl_seg_T0_vm(seg_reg);
if (seg_reg == R_SS) { if (seg_reg == R_SS) {
s->is_jmp = DISAS_TOO_MANY; s->base.is_jmp = DISAS_TOO_MANY;
} }
} }
} }
@ -2422,7 +2420,7 @@ static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
gen_update_cc_op(s); gen_update_cc_op(s);
gen_jmp_im(cur_eip); gen_jmp_im(cur_eip);
gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno)); gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
s->is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
} }
/* Generate #UD for the current instruction. The assumption here is that /* Generate #UD for the current instruction. The assumption here is that
@ -2460,7 +2458,7 @@ static void gen_interrupt(DisasContext *s, int intno,
gen_jmp_im(cur_eip); gen_jmp_im(cur_eip);
gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno), gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
tcg_const_i32(next_eip - cur_eip)); tcg_const_i32(next_eip - cur_eip));
s->is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
} }
static void gen_debug(DisasContext *s, target_ulong cur_eip) static void gen_debug(DisasContext *s, target_ulong cur_eip)
@ -2468,7 +2466,7 @@ static void gen_debug(DisasContext *s, target_ulong cur_eip)
gen_update_cc_op(s); gen_update_cc_op(s);
gen_jmp_im(cur_eip); gen_jmp_im(cur_eip);
gen_helper_debug(cpu_env); gen_helper_debug(cpu_env);
s->is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
} }
static void gen_set_hflag(DisasContext *s, uint32_t mask) static void gen_set_hflag(DisasContext *s, uint32_t mask)
@ -2524,10 +2522,10 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, TCGv jr)
gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK); gen_reset_hflag(s, HF_INHIBIT_IRQ_MASK);
} }
if (s->tb->flags & HF_RF_MASK) { if (s->base.tb->flags & HF_RF_MASK) {
gen_helper_reset_rf(cpu_env); gen_helper_reset_rf(cpu_env);
} }
if (s->singlestep_enabled) { if (s->base.singlestep_enabled) {
gen_helper_debug(cpu_env); gen_helper_debug(cpu_env);
} else if (recheck_tf) { } else if (recheck_tf) {
gen_helper_rechecking_single_step(cpu_env); gen_helper_rechecking_single_step(cpu_env);
@ -2543,7 +2541,7 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, TCGv jr)
} else { } else {
tcg_gen_exit_tb(0); tcg_gen_exit_tb(0);
} }
s->is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
} }
static inline void static inline void
@ -4417,7 +4415,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
} }
} }
/* convert one instruction. s->is_jmp is set if the translation must /* convert one instruction. s->base.is_jmp is set if the translation must
be stopped. Return the next pc value */ be stopped. Return the next pc value */
static target_ulong disas_insn(CPUX86State *env, DisasContext *s, static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
target_ulong pc_start) target_ulong pc_start)
@ -5377,7 +5375,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_movl_seg_T0(s, reg); gen_movl_seg_T0(s, reg);
gen_pop_update(s, ot); gen_pop_update(s, ot);
/* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */ /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
if (s->is_jmp) { if (s->base.is_jmp) {
gen_jmp_im(s->pc - s->cs_base); gen_jmp_im(s->pc - s->cs_base);
if (reg == R_SS) { if (reg == R_SS) {
s->tf = 0; s->tf = 0;
@ -5392,7 +5390,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
ot = gen_pop_T0(s); ot = gen_pop_T0(s);
gen_movl_seg_T0(s, (b >> 3) & 7); gen_movl_seg_T0(s, (b >> 3) & 7);
gen_pop_update(s, ot); gen_pop_update(s, ot);
if (s->is_jmp) { if (s->base.is_jmp) {
gen_jmp_im(s->pc - s->cs_base); gen_jmp_im(s->pc - s->cs_base);
gen_eob(s); gen_eob(s);
} }
@ -5443,7 +5441,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0); gen_ldst_modrm(env, s, modrm, MO_16, OR_TMP0, 0);
gen_movl_seg_T0(s, reg); gen_movl_seg_T0(s, reg);
/* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */ /* Note that reg == R_SS in gen_movl_seg_T0 always sets is_jmp. */
if (s->is_jmp) { if (s->base.is_jmp) {
gen_jmp_im(s->pc - s->cs_base); gen_jmp_im(s->pc - s->cs_base);
if (reg == R_SS) { if (reg == R_SS) {
s->tf = 0; s->tf = 0;
@ -5652,7 +5650,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_movl_seg_T0(s, op); gen_movl_seg_T0(s, op);
/* then put the data */ /* then put the data */
gen_op_mov_reg_v(ot, reg, cpu_T1); gen_op_mov_reg_v(ot, reg, cpu_T1);
if (s->is_jmp) { if (s->base.is_jmp) {
gen_jmp_im(s->pc - s->cs_base); gen_jmp_im(s->pc - s->cs_base);
gen_eob(s); gen_eob(s);
} }
@ -6308,7 +6306,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); gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
} else { } else {
gen_ins(s, ot); gen_ins(s, ot);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_jmp(s, s->pc - s->cs_base); gen_jmp(s, s->pc - s->cs_base);
} }
} }
@ -6323,7 +6321,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); gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
} else { } else {
gen_outs(s, ot); gen_outs(s, ot);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_jmp(s, s->pc - s->cs_base); gen_jmp(s, s->pc - s->cs_base);
} }
} }
@ -6339,14 +6337,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
tcg_gen_movi_tl(cpu_T0, val); tcg_gen_movi_tl(cpu_T0, val);
gen_check_io(s, ot, pc_start - s->cs_base, gen_check_io(s, ot, pc_start - s->cs_base,
SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_start(); gen_io_start();
} }
tcg_gen_movi_i32(cpu_tmp2_i32, val); tcg_gen_movi_i32(cpu_tmp2_i32, val);
gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32); gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
gen_op_mov_reg_v(ot, R_EAX, cpu_T1); gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
gen_bpt_io(s, cpu_tmp2_i32, ot); gen_bpt_io(s, cpu_tmp2_i32, ot);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_end(); gen_io_end();
gen_jmp(s, s->pc - s->cs_base); gen_jmp(s, s->pc - s->cs_base);
} }
@ -6360,14 +6358,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
svm_is_rep(prefixes)); svm_is_rep(prefixes));
gen_op_mov_v_reg(ot, cpu_T1, R_EAX); gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_start(); gen_io_start();
} }
tcg_gen_movi_i32(cpu_tmp2_i32, val); tcg_gen_movi_i32(cpu_tmp2_i32, val);
tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1); tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
gen_bpt_io(s, cpu_tmp2_i32, ot); gen_bpt_io(s, cpu_tmp2_i32, ot);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_end(); gen_io_end();
gen_jmp(s, s->pc - s->cs_base); gen_jmp(s, s->pc - s->cs_base);
} }
@ -6378,14 +6376,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]); tcg_gen_ext16u_tl(cpu_T0, cpu_regs[R_EDX]);
gen_check_io(s, ot, pc_start - s->cs_base, gen_check_io(s, ot, pc_start - s->cs_base,
SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes)); SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_start(); gen_io_start();
} }
tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32); gen_helper_in_func(ot, cpu_T1, cpu_tmp2_i32);
gen_op_mov_reg_v(ot, R_EAX, cpu_T1); gen_op_mov_reg_v(ot, R_EAX, cpu_T1);
gen_bpt_io(s, cpu_tmp2_i32, ot); gen_bpt_io(s, cpu_tmp2_i32, ot);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_end(); gen_io_end();
gen_jmp(s, s->pc - s->cs_base); gen_jmp(s, s->pc - s->cs_base);
} }
@ -6398,14 +6396,14 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
svm_is_rep(prefixes)); svm_is_rep(prefixes));
gen_op_mov_v_reg(ot, cpu_T1, R_EAX); gen_op_mov_v_reg(ot, cpu_T1, R_EAX);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_start(); gen_io_start();
} }
tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0); tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T0);
tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1); tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T1);
gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32); gen_helper_out_func(ot, cpu_tmp2_i32, cpu_tmp3_i32);
gen_bpt_io(s, cpu_tmp2_i32, ot); gen_bpt_io(s, cpu_tmp2_i32, ot);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_end(); gen_io_end();
gen_jmp(s, s->pc - s->cs_base); gen_jmp(s, s->pc - s->cs_base);
} }
@ -6944,7 +6942,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_update_cc_op(s); gen_update_cc_op(s);
gen_jmp_im(pc_start - s->cs_base); gen_jmp_im(pc_start - s->cs_base);
gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start)); gen_helper_pause(cpu_env, tcg_const_i32(s->pc - pc_start));
s->is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
} }
break; break;
case 0x9b: /* fwait */ case 0x9b: /* fwait */
@ -7113,11 +7111,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
case 0x131: /* rdtsc */ case 0x131: /* rdtsc */
gen_update_cc_op(s); gen_update_cc_op(s);
gen_jmp_im(pc_start - s->cs_base); gen_jmp_im(pc_start - s->cs_base);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_start(); gen_io_start();
} }
gen_helper_rdtsc(cpu_env); gen_helper_rdtsc(cpu_env);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_end(); gen_io_end();
gen_jmp(s, s->pc - s->cs_base); gen_jmp(s, s->pc - s->cs_base);
} }
@ -7189,7 +7187,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_update_cc_op(s); gen_update_cc_op(s);
gen_jmp_im(pc_start - s->cs_base); gen_jmp_im(pc_start - s->cs_base);
gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start)); gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
s->is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
} }
break; break;
case 0x100: case 0x100:
@ -7372,7 +7370,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1), gen_helper_vmrun(cpu_env, tcg_const_i32(s->aflag - 1),
tcg_const_i32(s->pc - pc_start)); tcg_const_i32(s->pc - pc_start));
tcg_gen_exit_tb(0); tcg_gen_exit_tb(0);
s->is_jmp = DISAS_NORETURN; s->base.is_jmp = DISAS_NORETURN;
break; break;
case 0xd9: /* VMMCALL */ case 0xd9: /* VMMCALL */
@ -7572,11 +7570,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
} }
gen_update_cc_op(s); gen_update_cc_op(s);
gen_jmp_im(pc_start - s->cs_base); gen_jmp_im(pc_start - s->cs_base);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_start(); gen_io_start();
} }
gen_helper_rdtscp(cpu_env); gen_helper_rdtscp(cpu_env);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_end(); gen_io_end();
gen_jmp(s, s->pc - s->cs_base); gen_jmp(s, s->pc - s->cs_base);
} }
@ -7941,24 +7939,24 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_update_cc_op(s); gen_update_cc_op(s);
gen_jmp_im(pc_start - s->cs_base); gen_jmp_im(pc_start - s->cs_base);
if (b & 2) { if (b & 2) {
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_start(); gen_io_start();
} }
gen_op_mov_v_reg(ot, cpu_T0, rm); gen_op_mov_v_reg(ot, cpu_T0, rm);
gen_helper_write_crN(cpu_env, tcg_const_i32(reg), gen_helper_write_crN(cpu_env, tcg_const_i32(reg),
cpu_T0); cpu_T0);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_end(); gen_io_end();
} }
gen_jmp_im(s->pc - s->cs_base); gen_jmp_im(s->pc - s->cs_base);
gen_eob(s); gen_eob(s);
} else { } else {
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_start(); gen_io_start();
} }
gen_helper_read_crN(cpu_T0, cpu_env, tcg_const_i32(reg)); gen_helper_read_crN(cpu_T0, cpu_env, tcg_const_i32(reg));
gen_op_mov_reg_v(ot, rm, cpu_T0); gen_op_mov_reg_v(ot, rm, cpu_T0);
if (s->tb->cflags & CF_USE_ICOUNT) { if (s->base.tb->cflags & CF_USE_ICOUNT) {
gen_io_end(); gen_io_end();
} }
} }
@ -8384,15 +8382,13 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
{ {
CPUX86State *env = cs->env_ptr; CPUX86State *env = cs->env_ptr;
DisasContext dc1, *dc = &dc1; DisasContext dc1, *dc = &dc1;
target_ulong pc_ptr;
uint32_t flags; uint32_t flags;
target_ulong pc_start;
target_ulong cs_base; target_ulong cs_base;
int num_insns; int num_insns;
int max_insns; int max_insns;
/* generate intermediate code */ /* generate intermediate code */
pc_start = tb->pc; dc->base.pc_first = tb->pc;
cs_base = tb->cs_base; cs_base = tb->cs_base;
flags = tb->flags; flags = tb->flags;
@ -8405,11 +8401,11 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
dc->cpl = (flags >> HF_CPL_SHIFT) & 3; dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
dc->iopl = (flags >> IOPL_SHIFT) & 3; dc->iopl = (flags >> IOPL_SHIFT) & 3;
dc->tf = (flags >> TF_SHIFT) & 1; dc->tf = (flags >> TF_SHIFT) & 1;
dc->singlestep_enabled = cs->singlestep_enabled; dc->base.singlestep_enabled = cs->singlestep_enabled;
dc->cc_op = CC_OP_DYNAMIC; dc->cc_op = CC_OP_DYNAMIC;
dc->cc_op_dirty = false; dc->cc_op_dirty = false;
dc->cs_base = cs_base; dc->cs_base = cs_base;
dc->tb = tb; dc->base.tb = tb;
dc->popl_esp_hack = 0; dc->popl_esp_hack = 0;
/* select memory access functions */ /* select memory access functions */
dc->mem_index = 0; dc->mem_index = 0;
@ -8459,8 +8455,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
cpu_ptr1 = tcg_temp_new_ptr(); cpu_ptr1 = tcg_temp_new_ptr();
cpu_cc_srcT = tcg_temp_local_new(); cpu_cc_srcT = tcg_temp_local_new();
dc->is_jmp = DISAS_NEXT; dc->base.is_jmp = DISAS_NEXT;
pc_ptr = pc_start; dc->base.pc_next = dc->base.pc_first;
num_insns = 0; num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK; max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) { if (max_insns == 0) {
@ -8472,37 +8468,38 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
gen_tb_start(tb); gen_tb_start(tb);
for(;;) { for(;;) {
tcg_gen_insn_start(pc_ptr, dc->cc_op); tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
num_insns++; num_insns++;
/* If RF is set, suppress an internally generated breakpoint. */ /* If RF is set, suppress an internally generated breakpoint. */
if (unlikely(cpu_breakpoint_test(cs, pc_ptr, if (unlikely(cpu_breakpoint_test(cs, dc->base.pc_next,
tb->flags & HF_RF_MASK tb->flags & HF_RF_MASK
? BP_GDB : BP_ANY))) { ? BP_GDB : BP_ANY))) {
gen_debug(dc, pc_ptr - dc->cs_base); gen_debug(dc, dc->base.pc_next - dc->cs_base);
/* The address covered by the breakpoint must be included in /* The address covered by the breakpoint must be included in
[tb->pc, tb->pc + tb->size) in order to for it to be [tb->pc, tb->pc + tb->size) in order to for it to be
properly cleared -- thus we increment the PC here so that properly cleared -- thus we increment the PC here so that
the logic setting tb->size below does the right thing. */ the logic setting tb->size below does the right thing. */
pc_ptr += 1; dc->base.pc_next += 1;
goto done_generating; goto done_generating;
} }
if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start(); gen_io_start();
} }
pc_ptr = disas_insn(env, dc, pc_ptr); dc->base.pc_next = disas_insn(env, dc, dc->base.pc_next);
/* stop translation if indicated */ /* stop translation if indicated */
if (dc->is_jmp) if (dc->base.is_jmp) {
break; break;
}
/* if single step mode, we generate only one instruction and /* if single step mode, we generate only one instruction and
generate an exception */ generate an exception */
/* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
the flag and abort the translation to give the irqs a the flag and abort the translation to give the irqs a
change to be happen */ change to be happen */
if (dc->tf || dc->singlestep_enabled || if (dc->tf || dc->base.singlestep_enabled ||
(flags & HF_INHIBIT_IRQ_MASK)) { (flags & HF_INHIBIT_IRQ_MASK)) {
gen_jmp_im(pc_ptr - dc->cs_base); gen_jmp_im(dc->base.pc_next - dc->cs_base);
gen_eob(dc); gen_eob(dc);
break; break;
} }
@ -8513,23 +8510,23 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
because an exception hasn't stopped this code. because an exception hasn't stopped this code.
*/ */
if ((tb->cflags & CF_USE_ICOUNT) if ((tb->cflags & CF_USE_ICOUNT)
&& ((pc_ptr & TARGET_PAGE_MASK) && ((dc->base.pc_next & TARGET_PAGE_MASK)
!= ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK) != ((dc->base.pc_next + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
|| (pc_ptr & ~TARGET_PAGE_MASK) == 0)) { || (dc->base.pc_next & ~TARGET_PAGE_MASK) == 0)) {
gen_jmp_im(pc_ptr - dc->cs_base); gen_jmp_im(dc->base.pc_next - dc->cs_base);
gen_eob(dc); gen_eob(dc);
break; break;
} }
/* if too long translation, stop generation too */ /* if too long translation, stop generation too */
if (tcg_op_buf_full() || if (tcg_op_buf_full() ||
(pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) || (dc->base.pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32) ||
num_insns >= max_insns) { num_insns >= max_insns) {
gen_jmp_im(pc_ptr - dc->cs_base); gen_jmp_im(dc->base.pc_next - dc->cs_base);
gen_eob(dc); gen_eob(dc);
break; break;
} }
if (singlestep) { if (singlestep) {
gen_jmp_im(pc_ptr - dc->cs_base); gen_jmp_im(dc->base.pc_next - dc->cs_base);
gen_eob(dc); gen_eob(dc);
break; break;
} }
@ -8541,24 +8538,25 @@ done_generating:
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM) if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
&& qemu_log_in_addr_range(pc_start)) { && qemu_log_in_addr_range(dc->base.pc_first)) {
int disas_flags; int disas_flags;
qemu_log_lock(); qemu_log_lock();
qemu_log("----------------\n"); qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start)); qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
#ifdef TARGET_X86_64 #ifdef TARGET_X86_64
if (dc->code64) if (dc->code64)
disas_flags = 2; disas_flags = 2;
else else
#endif #endif
disas_flags = !dc->code32; disas_flags = !dc->code32;
log_target_disas(cs, pc_start, pc_ptr - pc_start, disas_flags); log_target_disas(cs, dc->base.pc_first, dc->base.pc_next - dc->base.pc_first,
disas_flags);
qemu_log("\n"); qemu_log("\n");
qemu_log_unlock(); qemu_log_unlock();
} }
#endif #endif
tb->size = pc_ptr - pc_start; tb->size = dc->base.pc_next - dc->base.pc_first;
tb->icount = num_insns; tb->icount = num_insns;
} }