Commit 61a8c4ec3a39cf8547aba056f03574a5fac31fdd
1 parent
9746b15b
enter insn fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1135 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
92 additions
and
16 deletions
Changelog
| @@ -27,6 +27,7 @@ version 0.6.1: | @@ -27,6 +27,7 @@ version 0.6.1: | ||
| 27 | - Floppy fixes for NT4 and NT5 (Mike Nordell) | 27 | - Floppy fixes for NT4 and NT5 (Mike Nordell) |
| 28 | - NT4 IDE fixes (Ben Pfaf, Mike Nordell) | 28 | - NT4 IDE fixes (Ben Pfaf, Mike Nordell) |
| 29 | - SDL Audio support and SB16 fixes (malc) | 29 | - SDL Audio support and SB16 fixes (malc) |
| 30 | + - ENTER instruction bug fix (initial patch by Stefan Kisdaroczi) | ||
| 30 | 31 | ||
| 31 | version 0.6.0: | 32 | version 0.6.0: |
| 32 | 33 |
target-i386/exec.h
| @@ -167,6 +167,7 @@ void helper_divl_EAX_T0(uint32_t eip); | @@ -167,6 +167,7 @@ void helper_divl_EAX_T0(uint32_t eip); | ||
| 167 | void helper_idivl_EAX_T0(uint32_t eip); | 167 | void helper_idivl_EAX_T0(uint32_t eip); |
| 168 | void helper_cmpxchg8b(void); | 168 | void helper_cmpxchg8b(void); |
| 169 | void helper_cpuid(void); | 169 | void helper_cpuid(void); |
| 170 | +void helper_enter_level(int level, int data32); | ||
| 170 | void helper_sysenter(void); | 171 | void helper_sysenter(void); |
| 171 | void helper_sysexit(void); | 172 | void helper_sysexit(void); |
| 172 | void helper_rdtsc(void); | 173 | void helper_rdtsc(void); |
target-i386/helper.c
| @@ -1068,6 +1068,38 @@ void helper_cpuid(void) | @@ -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 | void helper_lldt_T0(void) | 1103 | void helper_lldt_T0(void) |
| 1072 | { | 1104 | { |
| 1073 | int selector; | 1105 | int selector; |
target-i386/op.c
| @@ -695,6 +695,11 @@ void OPPROTO op_cpuid(void) | @@ -695,6 +695,11 @@ void OPPROTO op_cpuid(void) | ||
| 695 | helper_cpuid(); | 695 | helper_cpuid(); |
| 696 | } | 696 | } |
| 697 | 697 | ||
| 698 | +void OPPROTO op_enter_level(void) | ||
| 699 | +{ | ||
| 700 | + helper_enter_level(PARAM1, PARAM2); | ||
| 701 | +} | ||
| 702 | + | ||
| 698 | void OPPROTO op_sysenter(void) | 703 | void OPPROTO op_sysenter(void) |
| 699 | { | 704 | { |
| 700 | helper_sysenter(); | 705 | helper_sysenter(); |
target-i386/translate.c
| @@ -1690,15 +1690,12 @@ static void gen_popa(DisasContext *s) | @@ -1690,15 +1690,12 @@ static void gen_popa(DisasContext *s) | ||
| 1690 | gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP](); | 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 | static void gen_enter(DisasContext *s, int esp_addend, int level) | 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 | ot = s->dflag + OT_WORD; | 1697 | ot = s->dflag + OT_WORD; |
| 1700 | level &= 0x1f; | 1698 | level &= 0x1f; |
| 1701 | - level1 = level; | ||
| 1702 | opsize = 2 << s->dflag; | 1699 | opsize = 2 << s->dflag; |
| 1703 | 1700 | ||
| 1704 | gen_op_movl_A0_ESP(); | 1701 | gen_op_movl_A0_ESP(); |
| @@ -1712,19 +1709,10 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) | @@ -1712,19 +1709,10 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) | ||
| 1712 | gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); | 1709 | gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); |
| 1713 | gen_op_st_T0_A0[ot + s->mem_index](); | 1710 | gen_op_st_T0_A0[ot + s->mem_index](); |
| 1714 | if (level) { | 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 | gen_op_mov_reg_T1[ot][R_EBP](); | 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 | gen_op_mov_reg_T1[ot][R_ESP](); | 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,7 +1625,55 @@ void test_self_modifying_code(void) | ||
| 1625 | printf("smc_code2(%d) = %d\n", i, smc_code2(i)); | 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 | static void *call_end __init_call = NULL; | 1677 | static void *call_end __init_call = NULL; |
| 1630 | 1678 | ||
| 1631 | int main(int argc, char **argv) | 1679 | int main(int argc, char **argv) |
| @@ -1653,5 +1701,6 @@ int main(int argc, char **argv) | @@ -1653,5 +1701,6 @@ int main(int argc, char **argv) | ||
| 1653 | test_exceptions(); | 1701 | test_exceptions(); |
| 1654 | test_self_modifying_code(); | 1702 | test_self_modifying_code(); |
| 1655 | test_single_step(); | 1703 | test_single_step(); |
| 1704 | + test_enter(); | ||
| 1656 | return 0; | 1705 | return 0; |
| 1657 | } | 1706 | } |