Commit 61a8c4ec3a39cf8547aba056f03574a5fac31fdd

Authored by bellard
1 parent 9746b15b

enter insn fix


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1135 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
... ... @@ -27,6 +27,7 @@ version 0.6.1:
27 27 - Floppy fixes for NT4 and NT5 (Mike Nordell)
28 28 - NT4 IDE fixes (Ben Pfaf, Mike Nordell)
29 29 - SDL Audio support and SB16 fixes (malc)
  30 + - ENTER instruction bug fix (initial patch by Stefan Kisdaroczi)
30 31  
31 32 version 0.6.0:
32 33  
... ...
target-i386/exec.h
... ... @@ -167,6 +167,7 @@ void helper_divl_EAX_T0(uint32_t eip);
167 167 void helper_idivl_EAX_T0(uint32_t eip);
168 168 void helper_cmpxchg8b(void);
169 169 void helper_cpuid(void);
  170 +void helper_enter_level(int level, int data32);
170 171 void helper_sysenter(void);
171 172 void helper_sysexit(void);
172 173 void helper_rdtsc(void);
... ...
target-i386/helper.c
... ... @@ -1068,6 +1068,38 @@ void helper_cpuid(void)
1068 1068 }
1069 1069 }
1070 1070  
  1071 +void helper_enter_level(int level, int data32)
  1072 +{
  1073 + uint8_t *ssp;
  1074 + uint32_t esp_mask, esp, ebp;
  1075 +
  1076 + esp_mask = get_sp_mask(env->segs[R_SS].flags);
  1077 + ssp = env->segs[R_SS].base;
  1078 + ebp = EBP;
  1079 + esp = ESP;
  1080 + if (data32) {
  1081 + /* 32 bit */
  1082 + esp -= 4;
  1083 + while (--level) {
  1084 + esp -= 4;
  1085 + ebp -= 4;
  1086 + stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));
  1087 + }
  1088 + esp -= 4;
  1089 + stl(ssp + (esp & esp_mask), T1);
  1090 + } else {
  1091 + /* 16 bit */
  1092 + esp -= 2;
  1093 + while (--level) {
  1094 + esp -= 2;
  1095 + ebp -= 2;
  1096 + stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));
  1097 + }
  1098 + esp -= 2;
  1099 + stw(ssp + (esp & esp_mask), T1);
  1100 + }
  1101 +}
  1102 +
1071 1103 void helper_lldt_T0(void)
1072 1104 {
1073 1105 int selector;
... ...
target-i386/op.c
... ... @@ -695,6 +695,11 @@ void OPPROTO op_cpuid(void)
695 695 helper_cpuid();
696 696 }
697 697  
  698 +void OPPROTO op_enter_level(void)
  699 +{
  700 + helper_enter_level(PARAM1, PARAM2);
  701 +}
  702 +
698 703 void OPPROTO op_sysenter(void)
699 704 {
700 705 helper_sysenter();
... ...
target-i386/translate.c
... ... @@ -1690,15 +1690,12 @@ static void gen_popa(DisasContext *s)
1690 1690 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1691 1691 }
1692 1692  
1693   -/* NOTE: wrap around in 16 bit not fully handled */
1694   -/* XXX: check this */
1695 1693 static void gen_enter(DisasContext *s, int esp_addend, int level)
1696 1694 {
1697   - int ot, level1, addend, opsize;
  1695 + int ot, opsize;
1698 1696  
1699 1697 ot = s->dflag + OT_WORD;
1700 1698 level &= 0x1f;
1701   - level1 = level;
1702 1699 opsize = 2 << s->dflag;
1703 1700  
1704 1701 gen_op_movl_A0_ESP();
... ... @@ -1712,19 +1709,10 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
1712 1709 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1713 1710 gen_op_st_T0_A0[ot + s->mem_index]();
1714 1711 if (level) {
1715   - while (level--) {
1716   - gen_op_addl_A0_im(-opsize);
1717   - gen_op_addl_T0_im(-opsize);
1718   - gen_op_st_T0_A0[ot + s->mem_index]();
1719   - }
1720   - gen_op_addl_A0_im(-opsize);
1721   - gen_op_st_T1_A0[ot + s->mem_index]();
  1712 + gen_op_enter_level(level, s->dflag);
1722 1713 }
1723 1714 gen_op_mov_reg_T1[ot][R_EBP]();
1724   - addend = -esp_addend;
1725   - if (level1)
1726   - addend -= opsize * (level1 + 1);
1727   - gen_op_addl_T1_im(addend);
  1715 + gen_op_addl_T1_im( -esp_addend + (-opsize * level) );
1728 1716 gen_op_mov_reg_T1[ot][R_ESP]();
1729 1717 }
1730 1718  
... ...
tests/test-i386.c
... ... @@ -1625,7 +1625,55 @@ void test_self_modifying_code(void)
1625 1625 printf("smc_code2(%d) = %d\n", i, smc_code2(i));
1626 1626 }
1627 1627 }
1628   -
  1628 +
  1629 +int enter_stack[4096];
  1630 +
  1631 +#define TEST_ENTER(size, stack_type, level)\
  1632 +{\
  1633 + int esp_save, esp_val, ebp_val, ebp_save, i;\
  1634 + stack_type *ptr, *stack_end, *stack_ptr;\
  1635 + memset(enter_stack, 0, sizeof(enter_stack));\
  1636 + stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\
  1637 + ebp_val = (long)stack_ptr;\
  1638 + for(i=1;i<=32;i++)\
  1639 + *--stack_ptr = i;\
  1640 + esp_val = (long)stack_ptr;\
  1641 + asm("movl %%esp, %[esp_save]\n"\
  1642 + "movl %%ebp, %[ebp_save]\n"\
  1643 + "movl %[esp_val], %%esp\n"\
  1644 + "movl %[ebp_val], %%ebp\n"\
  1645 + "enter" size " $12, $" #level "\n"\
  1646 + "movl %%esp, %[esp_val]\n"\
  1647 + "movl %%ebp, %[ebp_val]\n"\
  1648 + "movl %[esp_save], %%esp\n"\
  1649 + "movl %[ebp_save], %%ebp\n"\
  1650 + : [esp_save] "=r" (esp_save),\
  1651 + [ebp_save] "=r" (ebp_save),\
  1652 + [esp_val] "=r" (esp_val),\
  1653 + [ebp_val] "=r" (ebp_val)\
  1654 + : "[esp_val]" (esp_val),\
  1655 + "[ebp_val]" (ebp_val));\
  1656 + printf("level=%d:\n", level);\
  1657 + printf("esp_val=0x%08lx\n", esp_val - (long)stack_end);\
  1658 + printf("ebp_val=0x%08lx\n", ebp_val - (long)stack_end);\
  1659 + for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\
  1660 + printf("%08x\n", ptr[0]);\
  1661 +}
  1662 +
  1663 +static void test_enter(void)
  1664 +{
  1665 + TEST_ENTER("l", uint32_t, 0);
  1666 + TEST_ENTER("l", uint32_t, 1);
  1667 + TEST_ENTER("l", uint32_t, 2);
  1668 + TEST_ENTER("l", uint32_t, 31);
  1669 +
  1670 + TEST_ENTER("w", uint16_t, 0);
  1671 + TEST_ENTER("w", uint16_t, 1);
  1672 + TEST_ENTER("w", uint16_t, 2);
  1673 + TEST_ENTER("w", uint16_t, 31);
  1674 +}
  1675 +
  1676 +
1629 1677 static void *call_end __init_call = NULL;
1630 1678  
1631 1679 int main(int argc, char **argv)
... ... @@ -1653,5 +1701,6 @@ int main(int argc, char **argv)
1653 1701 test_exceptions();
1654 1702 test_self_modifying_code();
1655 1703 test_single_step();
  1704 + test_enter();
1656 1705 return 0;
1657 1706 }
... ...