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