diff options
Diffstat (limited to 'target-i386/translate.c')
-rw-r--r-- | target-i386/translate.c | 93 |
1 files changed, 34 insertions, 59 deletions
diff --git a/target-i386/translate.c b/target-i386/translate.c index 8900a0cffe..5aeac0567c 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -373,11 +373,6 @@ static inline void gen_op_mov_v_reg(TCGMemOp ot, TCGv t0, int reg) } } -static inline void gen_op_movl_A0_reg(int reg) -{ - tcg_gen_mov_tl(cpu_A0, cpu_regs[reg]); -} - static inline void gen_op_addl_A0_im(int32_t val) { tcg_gen_addi_tl(cpu_A0, cpu_A0, val); @@ -420,17 +415,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); @@ -2337,51 +2321,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_v_reg(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(cpu_env, tcg_const_i32(level), - tcg_const_i32((ot == MO_64)), - cpu_T[1]); - } - gen_op_mov_reg_v(ot, R_EBP, cpu_T[1]); - tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level)); - gen_op_mov_reg_v(MO_64, R_ESP, cpu_T[1]); - } 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_v_reg(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(cpu_env, tcg_const_i32(level), - tcg_const_i32(s->dflag - 1), - cpu_T[1]); - } - gen_op_mov_reg_v(ot, R_EBP, cpu_T[1]); - tcg_gen_addi_tl(cpu_T[1], cpu_T[1], -esp_addend + (-opsize * level)); - gen_op_mov_reg_v(MO_16 + s->ss32, R_ESP, cpu_T[1]); + /* 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) |