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