From 7dd4fcc6213d5fdff61a276c15e56912388ec818 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 20 Feb 2018 10:10:05 -0500 Subject: [PATCH] target-i386: Rewrite gen_enter inline Use gen_lea_v_seg for centralized segment base knowledge. Unify code across 32- and 64-bit. Fix note about "must save state" before using the out-of-line helpers. Backports commit 743e398e2fbf2f7183bf7a53c9d011fabcaa1770 from qemu --- qemu/target-i386/helper.h | 4 -- qemu/target-i386/seg_helper.c | 74 -------------------------- qemu/target-i386/translate.c | 98 ++++++++++++----------------------- 3 files changed, 34 insertions(+), 142 deletions(-) diff --git a/qemu/target-i386/helper.h b/qemu/target-i386/helper.h index 2ac509c5..9535b5d5 100644 --- a/qemu/target-i386/helper.h +++ b/qemu/target-i386/helper.h @@ -46,10 +46,6 @@ DEF_HELPER_FLAGS_3(set_dr, TCG_CALL_NO_WG, void, env, int, tl) DEF_HELPER_FLAGS_2(get_dr, TCG_CALL_NO_WG, tl, env, int) DEF_HELPER_2(invlpg, void, env, tl) -DEF_HELPER_4(enter_level, void, env, int, int, tl) -#ifdef TARGET_X86_64 -DEF_HELPER_4(enter64_level, void, env, int, int, tl) -#endif DEF_HELPER_2(sysenter, void, env, int) DEF_HELPER_2(sysexit, void, env, int) #ifdef TARGET_X86_64 diff --git a/qemu/target-i386/seg_helper.c b/qemu/target-i386/seg_helper.c index a962a30e..34fedf09 100644 --- a/qemu/target-i386/seg_helper.c +++ b/qemu/target-i386/seg_helper.c @@ -1376,80 +1376,6 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) return ret; } -void helper_enter_level(CPUX86State *env, int level, int data32, - target_ulong t1) -{ - target_ulong ssp; - uint32_t esp_mask, esp, ebp; - - esp_mask = get_sp_mask(env->segs[R_SS].flags); - ssp = env->segs[R_SS].base; - ebp = env->regs[R_EBP]; - esp = env->regs[R_ESP]; - if (data32) { - /* 32 bit */ - esp -= 4; - while (--level) { - esp -= 4; - ebp -= 4; - cpu_stl_data_ra(env, ssp + (esp & esp_mask), - cpu_ldl_data_ra(env, ssp + (ebp & esp_mask), - GETPC()), - GETPC()); - } - esp -= 4; - cpu_stl_data_ra(env, ssp + (esp & esp_mask), t1, GETPC()); - } else { - /* 16 bit */ - esp -= 2; - while (--level) { - esp -= 2; - ebp -= 2; - cpu_stw_data_ra(env, ssp + (esp & esp_mask), - cpu_lduw_data_ra(env, ssp + (ebp & esp_mask), - GETPC()), - GETPC()); - } - esp -= 2; - cpu_stw_data_ra(env, ssp + (esp & esp_mask), t1, GETPC()); - } -} - -#ifdef TARGET_X86_64 -void helper_enter64_level(CPUX86State *env, int level, int data64, - target_ulong t1) -{ - target_ulong esp, ebp; - - ebp = env->regs[R_EBP]; - esp = env->regs[R_ESP]; - - if (data64) { - /* 64 bit */ - esp -= 8; - while (--level) { - esp -= 8; - ebp -= 8; - cpu_stq_data_ra(env, esp, cpu_ldq_data_ra(env, ebp, GETPC()), - GETPC()); - } - esp -= 8; - cpu_stq_data_ra(env, esp, t1, GETPC()); - } else { - /* 16 bit */ - esp -= 2; - while (--level) { - esp -= 2; - ebp -= 2; - cpu_stw_data_ra(env, esp, cpu_lduw_data_ra(env, ebp, GETPC()), - GETPC()); - } - esp -= 2; - cpu_stw_data_ra(env, esp, t1, GETPC()); - } -} -#endif - void helper_lldt(CPUX86State *env, int selector) { SegmentCache *dt; diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c index f7775e91..0efdcce0 100644 --- a/qemu/target-i386/translate.c +++ b/qemu/target-i386/translate.c @@ -441,14 +441,6 @@ static inline void gen_op_mov_v_reg(TCGContext *s, TCGMemOp ot, TCGv t0, int reg } } -static inline void gen_op_movl_A0_reg(TCGContext *s, int reg) -{ - TCGv cpu_A0 = *(TCGv *)s->cpu_A0; - TCGv **cpu_regs = (TCGv **)s->cpu_regs; - - tcg_gen_mov_tl(s, cpu_A0, *cpu_regs[reg]); -} - static inline void gen_op_addl_A0_im(TCGContext *s, int32_t val) { TCGv cpu_A0 = *(TCGv *)s->cpu_A0; @@ -503,21 +495,6 @@ static inline void gen_op_add_reg_T0(TCGContext *s, TCGMemOp size, int reg) gen_op_mov_reg_v(s, size, reg, cpu_tmp0); } -static inline void gen_op_addl_A0_seg(DisasContext *s, int reg) -{ - TCGContext *tcg_ctx = s->uc->tcg_ctx; - TCGv cpu_A0 = *(TCGv *)tcg_ctx->cpu_A0; - TCGv **cpu_seg_base = (TCGv **)tcg_ctx->cpu_seg_base; - - if (CODE64(s)) { - tcg_gen_ext32u_tl(tcg_ctx, cpu_A0, cpu_A0); - tcg_gen_add_tl(tcg_ctx, cpu_A0, cpu_A0, *cpu_seg_base[reg]); - } else { - tcg_gen_add_tl(tcg_ctx, cpu_A0, cpu_A0, *cpu_seg_base[reg]); - tcg_gen_ext32u_tl(tcg_ctx, cpu_A0, cpu_A0); - } -} - static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0) { if (HOOK_EXISTS(s->uc, UC_HOOK_MEM_READ)) @@ -2644,54 +2621,47 @@ static void gen_popa(DisasContext *s) static void gen_enter(DisasContext *s, int esp_addend, int level) { - TCGMemOp ot = mo_pushpop(s, s->dflag); - int opsize = 1 << ot; + TCGMemOp d_ot = mo_pushpop(s, s->dflag); + TCGMemOp a_ot = CODE64(s) ? MO_64 : s->ss32 ? MO_32 : MO_16; + int size = 1 << d_ot; TCGContext *tcg_ctx = s->uc->tcg_ctx; TCGv cpu_A0 = *(TCGv *)tcg_ctx->cpu_A0; + TCGv cpu_tmp0 = *(TCGv *)tcg_ctx->cpu_tmp0; TCGv **cpu_T = (TCGv **)tcg_ctx->cpu_T; + TCGv **cpu_regs = (TCGv **)tcg_ctx->cpu_regs; - level &= 0x1f; -#ifdef TARGET_X86_64 - if (CODE64(s)) { - gen_op_movl_A0_reg(tcg_ctx, R_ESP); - gen_op_addq_A0_im(tcg_ctx, -opsize); - tcg_gen_mov_tl(tcg_ctx, *cpu_T[1], cpu_A0); + /* Push BP; compute FrameTemp into T1. */ + tcg_gen_subi_tl(tcg_ctx, *cpu_T[1], *cpu_regs[R_ESP], size); + gen_lea_v_seg(s, a_ot, *cpu_T[1], R_SS, -1); + gen_op_st_v(s, d_ot, *cpu_regs[R_EBP], cpu_A0); - /* push bp */ - gen_op_mov_v_reg(tcg_ctx, MO_32, *cpu_T[0], R_EBP); - gen_op_st_v(s, ot, *cpu_T[0], cpu_A0); - if (level) { - /* XXX: must save state */ - gen_helper_enter64_level(tcg_ctx, tcg_ctx->cpu_env, tcg_const_i32(tcg_ctx, level), - tcg_const_i32(tcg_ctx, (ot == MO_64)), - *cpu_T[1]); + level &= 31; + if (level != 0) { + int i; + + /* Copy level-1 pointers from the previous frame. */ + for (i = 1; i < level; ++i) { + tcg_gen_subi_tl(tcg_ctx, cpu_A0, *cpu_regs[R_EBP], size * i); + gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1); + gen_op_ld_v(s, d_ot, cpu_tmp0, cpu_A0); + + tcg_gen_subi_tl(tcg_ctx, cpu_A0, *cpu_T[1], size * i); + gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1); + gen_op_st_v(s, d_ot, cpu_tmp0, cpu_A0); } - gen_op_mov_reg_v(tcg_ctx, ot, R_EBP, *cpu_T[1]); - tcg_gen_addi_tl(tcg_ctx, *cpu_T[1], *cpu_T[1], -esp_addend + (-opsize * level)); - gen_op_mov_reg_v(tcg_ctx, MO_64, R_ESP, *cpu_T[1]); - } else -#endif - { - gen_op_movl_A0_reg(tcg_ctx, R_ESP); - gen_op_addl_A0_im(tcg_ctx, -opsize); - if (!s->ss32) - tcg_gen_ext16u_tl(tcg_ctx, cpu_A0, cpu_A0); - tcg_gen_mov_tl(tcg_ctx, *cpu_T[1], cpu_A0); - if (s->addseg) - gen_op_addl_A0_seg(s, R_SS); - /* push bp */ - gen_op_mov_v_reg(tcg_ctx, MO_32, *cpu_T[0], R_EBP); - gen_op_st_v(s, ot, *cpu_T[0], cpu_A0); - if (level) { - /* XXX: must save state */ - gen_helper_enter_level(tcg_ctx, tcg_ctx->cpu_env, tcg_const_i32(tcg_ctx, level), - tcg_const_i32(tcg_ctx, s->dflag - 1), - *cpu_T[1]); - } - gen_op_mov_reg_v(tcg_ctx, ot, R_EBP, *cpu_T[1]); - tcg_gen_addi_tl(tcg_ctx, *cpu_T[1], *cpu_T[1], -esp_addend + (-opsize * level)); - gen_op_mov_reg_v(tcg_ctx, MO_16 + s->ss32, R_ESP, *cpu_T[1]); + + /* Push the current FrameTemp as the last level. */ + tcg_gen_subi_tl(tcg_ctx, cpu_A0, *cpu_T[1], size * level); + gen_lea_v_seg(s, a_ot, cpu_A0, R_SS, -1); + gen_op_st_v(s, d_ot, *cpu_T[1], cpu_A0); } + + /* Copy the FrameTemp value to EBP. */ + gen_op_mov_reg_v(tcg_ctx, a_ot, R_EBP, *cpu_T[1]); + + /* Compute the final value of ESP. */ + tcg_gen_subi_tl(tcg_ctx, *cpu_T[1], *cpu_T[1], esp_addend + size * level); + gen_op_mov_reg_v(tcg_ctx, a_ot, R_ESP, *cpu_T[1]); } static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)