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 | } |