mirror of https://gitee.com/openkylin/qemu.git
enter insn fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1135 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
9746b15b4e
commit
61a8c4ec3a
|
@ -27,6 +27,7 @@ version 0.6.1:
|
||||||
- Floppy fixes for NT4 and NT5 (Mike Nordell)
|
- Floppy fixes for NT4 and NT5 (Mike Nordell)
|
||||||
- NT4 IDE fixes (Ben Pfaf, Mike Nordell)
|
- NT4 IDE fixes (Ben Pfaf, Mike Nordell)
|
||||||
- SDL Audio support and SB16 fixes (malc)
|
- SDL Audio support and SB16 fixes (malc)
|
||||||
|
- ENTER instruction bug fix (initial patch by Stefan Kisdaroczi)
|
||||||
|
|
||||||
version 0.6.0:
|
version 0.6.0:
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,7 @@ void helper_divl_EAX_T0(uint32_t eip);
|
||||||
void helper_idivl_EAX_T0(uint32_t eip);
|
void helper_idivl_EAX_T0(uint32_t eip);
|
||||||
void helper_cmpxchg8b(void);
|
void helper_cmpxchg8b(void);
|
||||||
void helper_cpuid(void);
|
void helper_cpuid(void);
|
||||||
|
void helper_enter_level(int level, int data32);
|
||||||
void helper_sysenter(void);
|
void helper_sysenter(void);
|
||||||
void helper_sysexit(void);
|
void helper_sysexit(void);
|
||||||
void helper_rdtsc(void);
|
void helper_rdtsc(void);
|
||||||
|
|
|
@ -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)
|
void helper_lldt_T0(void)
|
||||||
{
|
{
|
||||||
int selector;
|
int selector;
|
||||||
|
|
|
@ -695,6 +695,11 @@ void OPPROTO op_cpuid(void)
|
||||||
helper_cpuid();
|
helper_cpuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OPPROTO op_enter_level(void)
|
||||||
|
{
|
||||||
|
helper_enter_level(PARAM1, PARAM2);
|
||||||
|
}
|
||||||
|
|
||||||
void OPPROTO op_sysenter(void)
|
void OPPROTO op_sysenter(void)
|
||||||
{
|
{
|
||||||
helper_sysenter();
|
helper_sysenter();
|
||||||
|
|
|
@ -1690,15 +1690,12 @@ static void gen_popa(DisasContext *s)
|
||||||
gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
|
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)
|
static void gen_enter(DisasContext *s, int esp_addend, int level)
|
||||||
{
|
{
|
||||||
int ot, level1, addend, opsize;
|
int ot, opsize;
|
||||||
|
|
||||||
ot = s->dflag + OT_WORD;
|
ot = s->dflag + OT_WORD;
|
||||||
level &= 0x1f;
|
level &= 0x1f;
|
||||||
level1 = level;
|
|
||||||
opsize = 2 << s->dflag;
|
opsize = 2 << s->dflag;
|
||||||
|
|
||||||
gen_op_movl_A0_ESP();
|
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_mov_TN_reg[OT_LONG][0][R_EBP]();
|
||||||
gen_op_st_T0_A0[ot + s->mem_index]();
|
gen_op_st_T0_A0[ot + s->mem_index]();
|
||||||
if (level) {
|
if (level) {
|
||||||
while (level--) {
|
gen_op_enter_level(level, s->dflag);
|
||||||
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_mov_reg_T1[ot][R_EBP]();
|
gen_op_mov_reg_T1[ot][R_EBP]();
|
||||||
addend = -esp_addend;
|
gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
|
||||||
if (level1)
|
|
||||||
addend -= opsize * (level1 + 1);
|
|
||||||
gen_op_addl_T1_im(addend);
|
|
||||||
gen_op_mov_reg_T1[ot][R_ESP]();
|
gen_op_mov_reg_T1[ot][R_ESP]();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1626,6 +1626,54 @@ void test_self_modifying_code(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int enter_stack[4096];
|
||||||
|
|
||||||
|
#define TEST_ENTER(size, stack_type, level)\
|
||||||
|
{\
|
||||||
|
int esp_save, esp_val, ebp_val, ebp_save, i;\
|
||||||
|
stack_type *ptr, *stack_end, *stack_ptr;\
|
||||||
|
memset(enter_stack, 0, sizeof(enter_stack));\
|
||||||
|
stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\
|
||||||
|
ebp_val = (long)stack_ptr;\
|
||||||
|
for(i=1;i<=32;i++)\
|
||||||
|
*--stack_ptr = i;\
|
||||||
|
esp_val = (long)stack_ptr;\
|
||||||
|
asm("movl %%esp, %[esp_save]\n"\
|
||||||
|
"movl %%ebp, %[ebp_save]\n"\
|
||||||
|
"movl %[esp_val], %%esp\n"\
|
||||||
|
"movl %[ebp_val], %%ebp\n"\
|
||||||
|
"enter" size " $12, $" #level "\n"\
|
||||||
|
"movl %%esp, %[esp_val]\n"\
|
||||||
|
"movl %%ebp, %[ebp_val]\n"\
|
||||||
|
"movl %[esp_save], %%esp\n"\
|
||||||
|
"movl %[ebp_save], %%ebp\n"\
|
||||||
|
: [esp_save] "=r" (esp_save),\
|
||||||
|
[ebp_save] "=r" (ebp_save),\
|
||||||
|
[esp_val] "=r" (esp_val),\
|
||||||
|
[ebp_val] "=r" (ebp_val)\
|
||||||
|
: "[esp_val]" (esp_val),\
|
||||||
|
"[ebp_val]" (ebp_val));\
|
||||||
|
printf("level=%d:\n", level);\
|
||||||
|
printf("esp_val=0x%08lx\n", esp_val - (long)stack_end);\
|
||||||
|
printf("ebp_val=0x%08lx\n", ebp_val - (long)stack_end);\
|
||||||
|
for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\
|
||||||
|
printf("%08x\n", ptr[0]);\
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_enter(void)
|
||||||
|
{
|
||||||
|
TEST_ENTER("l", uint32_t, 0);
|
||||||
|
TEST_ENTER("l", uint32_t, 1);
|
||||||
|
TEST_ENTER("l", uint32_t, 2);
|
||||||
|
TEST_ENTER("l", uint32_t, 31);
|
||||||
|
|
||||||
|
TEST_ENTER("w", uint16_t, 0);
|
||||||
|
TEST_ENTER("w", uint16_t, 1);
|
||||||
|
TEST_ENTER("w", uint16_t, 2);
|
||||||
|
TEST_ENTER("w", uint16_t, 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *call_end __init_call = NULL;
|
static void *call_end __init_call = NULL;
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
|
@ -1653,5 +1701,6 @@ int main(int argc, char **argv)
|
||||||
test_exceptions();
|
test_exceptions();
|
||||||
test_self_modifying_code();
|
test_self_modifying_code();
|
||||||
test_single_step();
|
test_single_step();
|
||||||
|
test_enter();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue