[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 47/60] target-i386: Rewrite gen_enter inline
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH v2 47/60] target-i386: Rewrite gen_enter inline |
Date: |
Fri, 29 Nov 2013 16:00:34 +1300 |
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.
Signed-off-by: Richard Henderson <address@hidden>
---
target-i386/helper.h | 4 ---
target-i386/seg_helper.c | 68 -------------------------------------
target-i386/translate.c | 88 +++++++++++++++++++-----------------------------
3 files changed, 34 insertions(+), 126 deletions(-)
diff --git a/target-i386/helper.h b/target-i386/helper.h
index 3775abe..c8acc64 100644
--- a/target-i386/helper.h
+++ b/target-i386/helper.h
@@ -45,10 +45,6 @@ DEF_HELPER_1(clts, void, env)
DEF_HELPER_3(movl_drN_T0, void, env, int, tl)
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_1(sysenter, void, env)
DEF_HELPER_2(sysexit, void, env, int)
#ifdef TARGET_X86_64
diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c
index e789102..115937c 100644
--- a/target-i386/seg_helper.c
+++ b/target-i386/seg_helper.c
@@ -1268,74 +1268,6 @@ void do_interrupt_x86_hardirq(CPUX86State *env, int
intno, int is_hw)
do_interrupt_all(x86_env_get_cpu(env), intno, 0, 0, 0, is_hw);
}
-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(env, ssp + (esp & esp_mask),
- cpu_ldl_data(env, ssp + (ebp & esp_mask)));
- }
- esp -= 4;
- cpu_stl_data(env, ssp + (esp & esp_mask), t1);
- } else {
- /* 16 bit */
- esp -= 2;
- while (--level) {
- esp -= 2;
- ebp -= 2;
- cpu_stw_data(env, ssp + (esp & esp_mask),
- cpu_lduw_data(env, ssp + (ebp & esp_mask)));
- }
- esp -= 2;
- cpu_stw_data(env, ssp + (esp & esp_mask), t1);
- }
-}
-
-#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(env, esp, cpu_ldq_data(env, ebp));
- }
- esp -= 8;
- cpu_stq_data(env, esp, t1);
- } else {
- /* 16 bit */
- esp -= 2;
- while (--level) {
- esp -= 2;
- ebp -= 2;
- cpu_stw_data(env, esp, cpu_lduw_data(env, ebp));
- }
- esp -= 2;
- cpu_stw_data(env, esp, t1);
- }
-}
-#endif
-
void helper_lldt(CPUX86State *env, int selector)
{
SegmentCache *dt;
diff --git a/target-i386/translate.c b/target-i386/translate.c
index a4f38ab..fa707c1 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -442,17 +442,6 @@ static inline void gen_op_add_reg_T0(TCGMemOp size, int
reg)
gen_op_mov_reg_v(size, reg, cpu_tmp0);
}
-static inline void gen_op_addl_A0_seg(DisasContext *s, int reg)
-{
- if (CODE64(s)) {
- tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
- tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_seg_base[reg]);
- } else {
- tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_seg_base[reg]);
- tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
- }
-}
-
static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0)
{
tcg_gen_qemu_ld_tl(t0, a0, s->mem_index, idx | MO_LE);
@@ -2374,51 +2363,42 @@ 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;
- level &= 0x1f;
-#ifdef TARGET_X86_64
- if (CODE64(s)) {
- gen_op_movl_A0_reg(R_ESP);
- gen_op_addq_A0_im(-opsize);
- tcg_gen_mov_tl(cpu_T[1], cpu_A0);
-
- /* push bp */
- gen_op_mov_TN_reg(MO_32, 0, R_EBP);
- gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
- if (level) {
- /* XXX: must save state */
- gen_helper_enter64_level(cpu_env, tcg_const_i32(level),
- tcg_const_i32((ot == MO_64)),
- cpu_T[1]);
- }
- gen_op_mov_reg_T1(ot, R_EBP);
- tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
- gen_op_mov_reg_T1(MO_64, R_ESP);
- } else
-#endif
- {
- gen_op_movl_A0_reg(R_ESP);
- gen_op_addl_A0_im(-opsize);
- if (!s->ss32)
- tcg_gen_ext16u_tl(cpu_A0, cpu_A0);
- tcg_gen_mov_tl(cpu_T[1], cpu_A0);
- if (s->addseg)
- gen_op_addl_A0_seg(s, R_SS);
- /* push bp */
- gen_op_mov_TN_reg(MO_32, 0, R_EBP);
- gen_op_st_v(s, ot, cpu_T[0], cpu_A0);
- if (level) {
- /* XXX: must save state */
- gen_helper_enter_level(cpu_env, tcg_const_i32(level),
- tcg_const_i32(s->dflag - 1),
- cpu_T[1]);
- }
- gen_op_mov_reg_T1(ot, R_EBP);
- tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level));
- gen_op_mov_reg_T1(MO_16 + s->ss32, R_ESP);
+ /* Push BP; compute FrameTemp into T1. */
+ tcg_gen_subi_tl(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);
+
+ 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(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(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);
+ }
+
+ /* Push the current FrameTemp as the last level. */
+ tcg_gen_subi_tl(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(a_ot, R_EBP, cpu_T[1]);
+
+ /* Compute the final value of ESP. */
+ tcg_gen_subi_tl(cpu_T[1], cpu_T[1], esp_addend + size * level);
+ gen_op_mov_reg_v(a_ot, R_ESP, cpu_T[1]);
}
static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
--
1.8.3.1
- [Qemu-devel] [PATCH v2 51/60] target-i386: Remove gen_op_mov_reg_T1, (continued)
- [Qemu-devel] [PATCH v2 51/60] target-i386: Remove gen_op_mov_reg_T1, Richard Henderson, 2013/11/28
- [Qemu-devel] [PATCH v2 52/60] target-i386: Remove gen_op_addl_T0_T1, Richard Henderson, 2013/11/28
- [Qemu-devel] [PATCH v2 53/60] target-i386: Remove gen_op_mov_TN_reg, Richard Henderson, 2013/11/28
- [Qemu-devel] [PATCH v2 54/60] target-i386: Remove gen_op_mov_reg_A0, Richard Henderson, 2013/11/28
- [Qemu-devel] [PATCH v2 55/60] target-i386: Remove gen_op_movl_A0_reg, Richard Henderson, 2013/11/28
- [Qemu-devel] [PATCH v2 56/60] target-i386: Tidy gen_add_A0_im, Richard Henderson, 2013/11/28
- [Qemu-devel] [PATCH v2 57/60] target-i386: Tidy some size computation, Richard Henderson, 2013/11/28
- [Qemu-devel] [PATCH v2 58/60] target-i386: Rename gen_op_jmp_T0 to gen_op_jmp_v, Richard Henderson, 2013/11/28
- [Qemu-devel] [PATCH v2 59/60] target-i386: Tidy ljmp, Richard Henderson, 2013/11/28
- [Qemu-devel] [PATCH v2 60/60] target-i386: Deconstruct the cpu_T array, Richard Henderson, 2013/11/28
- [Qemu-devel] [PATCH v2 47/60] target-i386: Rewrite gen_enter inline,
Richard Henderson <=
- [Qemu-devel] [PATCH v2 46/60] target-i386: Use gen_lea_v_seg in pusha/popa, Richard Henderson, 2013/11/28
- [Qemu-devel] [PATCH v2 34/60] target-i386: Change gen_op_j*z_ecx size parameter to TCGMemOp, Richard Henderson, 2013/11/28