summaryrefslogtreecommitdiff
path: root/target-i386
diff options
context:
space:
mode:
Diffstat (limited to 'target-i386')
-rw-r--r--target-i386/exec.h1
-rw-r--r--target-i386/helper.c32
-rw-r--r--target-i386/op.c5
-rw-r--r--target-i386/translate.c18
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]();
}