Having segs[].base as a register significantly improves code generation for real and protected modes, particularly for TBs that have multiple memory references where the segment base can be held in a hard register through the TB.
Signed-off-by: Richard Henderson <r...@twiddle.net> --- target-i386/translate.c | 71 ++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/target-i386/translate.c b/target-i386/translate.c index 73ff589..3bb77eb 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -65,6 +65,8 @@ static TCGv cpu_A0; static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT; static TCGv_i32 cpu_cc_op; static TCGv cpu_regs[CPU_NB_REGS]; +static TCGv_i32 cpu_seg_sel[6]; +static TCGv cpu_seg_base[6]; /* local temps */ static TCGv cpu_T[2]; /* local register indexes (only used inside old micro ops) */ @@ -442,12 +444,11 @@ static inline void gen_op_add_reg_T0(TCGMemOp size, int reg) static inline void gen_op_addl_A0_seg(DisasContext *s, int reg) { - tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base)); if (CODE64(s)) { tcg_gen_ext32u_tl(cpu_A0, cpu_A0); - tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); + tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_seg_base[reg]); } else { - tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); + tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_seg_base[reg]); tcg_gen_ext32u_tl(cpu_A0, cpu_A0); } } @@ -519,9 +520,7 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0, } if (ovr_seg >= 0) { - TCGv seg = tcg_temp_new(); - - tcg_gen_ld_tl(seg, cpu_env, offsetof(CPUX86State, segs[ovr_seg].base)); + TCGv seg = cpu_seg_base[ovr_seg]; if (aflag == MO_64) { tcg_gen_add_tl(cpu_A0, a0, seg); @@ -532,8 +531,6 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0, tcg_gen_add_tl(cpu_A0, a0, seg); tcg_gen_ext32u_tl(cpu_A0, cpu_A0); } - - tcg_temp_free(seg); } } @@ -2218,18 +2215,14 @@ static void gen_cmovcc1(CPUX86State *env, DisasContext *s, TCGMemOp ot, int b, static inline void gen_op_movl_T0_seg(int seg_reg) { - tcg_gen_ld32u_tl(cpu_T[0], cpu_env, - offsetof(CPUX86State,segs[seg_reg].selector)); + tcg_gen_extu_i32_tl(cpu_T[0], cpu_seg_sel[seg_reg]); } static inline void gen_op_movl_seg_T0_vm(int seg_reg) { - tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff); - tcg_gen_st32_tl(cpu_T[0], cpu_env, - offsetof(CPUX86State,segs[seg_reg].selector)); - tcg_gen_shli_tl(cpu_T[0], cpu_T[0], 4); - tcg_gen_st_tl(cpu_T[0], cpu_env, - offsetof(CPUX86State,segs[seg_reg].base)); + tcg_gen_ext16u_tl(cpu_T[0], cpu_T[0]); + tcg_gen_trunc_tl_i32(cpu_seg_sel[seg_reg], cpu_T[0]); + tcg_gen_shli_tl(cpu_seg_base[seg_reg], cpu_T[0], 4); } /* move T0 to seg_reg and compute if the CPU state may change. Never @@ -7296,21 +7289,16 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, if (s->cpl != 0) { gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { - tcg_gen_ld_tl(cpu_T[0], cpu_env, - offsetof(CPUX86State,segs[R_GS].base)); - tcg_gen_ld_tl(cpu_T[1], cpu_env, - offsetof(CPUX86State,kernelgsbase)); - tcg_gen_st_tl(cpu_T[1], cpu_env, - offsetof(CPUX86State,segs[R_GS].base)); + tcg_gen_mov_tl(cpu_T[0], cpu_seg_base[R_GS]); + tcg_gen_ld_tl(cpu_seg_base[R_GS], cpu_env, + offsetof(CPUX86State, kernelgsbase)); tcg_gen_st_tl(cpu_T[0], cpu_env, - offsetof(CPUX86State,kernelgsbase)); + offsetof(CPUX86State, kernelgsbase)); } - } else -#endif - { - goto illegal_op; + break; } - break; +#endif + goto illegal_op; case 1: /* rdtscp */ if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP)) goto illegal_op; @@ -7736,6 +7724,22 @@ void optimize_flags_init(void) [R_ESP] = "esp", #endif }; + static const char seg_base_names[6][8] = { + [R_CS] = "cs_base", + [R_DS] = "ds_base", + [R_ES] = "es_base", + [R_FS] = "fs_base", + [R_GS] = "gs_base", + [R_SS] = "ss_base", + }; + static const char seg_sel_names[6][8] = { + [R_CS] = "cs_sel", + [R_DS] = "ds_sel", + [R_ES] = "es_sel", + [R_FS] = "fs_sel", + [R_GS] = "gs_sel", + [R_SS] = "ss_sel", + }; int i; cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); @@ -7753,6 +7757,17 @@ void optimize_flags_init(void) offsetof(CPUX86State, regs[i]), reg_names[i]); } + + for (i = 0; i < 6; ++i) { + cpu_seg_base[i] + = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUX86State, segs[i].base), + seg_base_names[i]); + cpu_seg_sel[i] + = tcg_global_mem_new_i32(TCG_AREG0, + offsetof(CPUX86State, segs[i].selector), + seg_sel_names[i]); + } } /* generate intermediate code in gen_opc_buf and gen_opparam_buf for -- 1.8.3.1