diff options
Diffstat (limited to 'target-i386')
-rw-r--r-- | target-i386/exec.h | 1 | ||||
-rw-r--r-- | target-i386/helper.c | 32 | ||||
-rw-r--r-- | target-i386/op.c | 5 | ||||
-rw-r--r-- | target-i386/translate.c | 18 |
4 files changed, 41 insertions, 15 deletions
diff --git a/target-i386/exec.h b/target-i386/exec.h index 61af5468e7..c0c8ca0db7 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -167,6 +167,7 @@ void helper_divl_EAX_T0(uint32_t eip); void helper_idivl_EAX_T0(uint32_t eip); void helper_cmpxchg8b(void); void helper_cpuid(void); +void helper_enter_level(int level, int data32); void helper_sysenter(void); void helper_sysexit(void); void helper_rdtsc(void); diff --git a/target-i386/helper.c b/target-i386/helper.c index 41ebaf221e..e6686da722 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1068,6 +1068,38 @@ void helper_cpuid(void) } } +void helper_enter_level(int level, int data32) +{ + uint8_t *ssp; + uint32_t esp_mask, esp, ebp; + + esp_mask = get_sp_mask(env->segs[R_SS].flags); + ssp = env->segs[R_SS].base; + ebp = EBP; + esp = ESP; + if (data32) { + /* 32 bit */ + esp -= 4; + while (--level) { + esp -= 4; + ebp -= 4; + stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask))); + } + esp -= 4; + stl(ssp + (esp & esp_mask), T1); + } else { + /* 16 bit */ + esp -= 2; + while (--level) { + esp -= 2; + ebp -= 2; + stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask))); + } + esp -= 2; + stw(ssp + (esp & esp_mask), T1); + } +} + void helper_lldt_T0(void) { int selector; diff --git a/target-i386/op.c b/target-i386/op.c index 9ea00a7571..21d4d82991 100644 --- a/target-i386/op.c +++ b/target-i386/op.c @@ -695,6 +695,11 @@ void OPPROTO op_cpuid(void) helper_cpuid(); } +void OPPROTO op_enter_level(void) +{ + helper_enter_level(PARAM1, PARAM2); +} + void OPPROTO op_sysenter(void) { helper_sysenter(); diff --git a/target-i386/translate.c b/target-i386/translate.c index bd2a61b0e5..5b8f213123 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -1690,15 +1690,12 @@ static void gen_popa(DisasContext *s) gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP](); } -/* NOTE: wrap around in 16 bit not fully handled */ -/* XXX: check this */ static void gen_enter(DisasContext *s, int esp_addend, int level) { - int ot, level1, addend, opsize; + int ot, opsize; ot = s->dflag + OT_WORD; level &= 0x1f; - level1 = level; opsize = 2 << s->dflag; gen_op_movl_A0_ESP(); @@ -1712,19 +1709,10 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); gen_op_st_T0_A0[ot + s->mem_index](); if (level) { - while (level--) { - gen_op_addl_A0_im(-opsize); - gen_op_addl_T0_im(-opsize); - gen_op_st_T0_A0[ot + s->mem_index](); - } - gen_op_addl_A0_im(-opsize); - gen_op_st_T1_A0[ot + s->mem_index](); + gen_op_enter_level(level, s->dflag); } gen_op_mov_reg_T1[ot][R_EBP](); - addend = -esp_addend; - if (level1) - addend -= opsize * (level1 + 1); - gen_op_addl_T1_im(addend); + gen_op_addl_T1_im( -esp_addend + (-opsize * level) ); gen_op_mov_reg_T1[ot][R_ESP](); } |