Commit e17a36ce41bc76abecebb434850ba619f5182ba8
1 parent
03c18475
multi byte nop support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2145 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
57 additions
and
2 deletions
target-i386/translate.c
| ... | ... | @@ -1615,6 +1615,56 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ |
| 1615 | 1615 | *offset_ptr = disp; |
| 1616 | 1616 | } |
| 1617 | 1617 | |
| 1618 | +static void gen_nop_modrm(DisasContext *s, int modrm) | |
| 1619 | +{ | |
| 1620 | + int mod, rm, base, code; | |
| 1621 | + | |
| 1622 | + mod = (modrm >> 6) & 3; | |
| 1623 | + if (mod == 3) | |
| 1624 | + return; | |
| 1625 | + rm = modrm & 7; | |
| 1626 | + | |
| 1627 | + if (s->aflag) { | |
| 1628 | + | |
| 1629 | + base = rm; | |
| 1630 | + | |
| 1631 | + if (base == 4) { | |
| 1632 | + code = ldub_code(s->pc++); | |
| 1633 | + base = (code & 7); | |
| 1634 | + } | |
| 1635 | + | |
| 1636 | + switch (mod) { | |
| 1637 | + case 0: | |
| 1638 | + if (base == 5) { | |
| 1639 | + s->pc += 4; | |
| 1640 | + } | |
| 1641 | + break; | |
| 1642 | + case 1: | |
| 1643 | + s->pc++; | |
| 1644 | + break; | |
| 1645 | + default: | |
| 1646 | + case 2: | |
| 1647 | + s->pc += 4; | |
| 1648 | + break; | |
| 1649 | + } | |
| 1650 | + } else { | |
| 1651 | + switch (mod) { | |
| 1652 | + case 0: | |
| 1653 | + if (rm == 6) { | |
| 1654 | + s->pc += 2; | |
| 1655 | + } | |
| 1656 | + break; | |
| 1657 | + case 1: | |
| 1658 | + s->pc++; | |
| 1659 | + break; | |
| 1660 | + default: | |
| 1661 | + case 2: | |
| 1662 | + s->pc += 2; | |
| 1663 | + break; | |
| 1664 | + } | |
| 1665 | + } | |
| 1666 | +} | |
| 1667 | + | |
| 1618 | 1668 | /* used for LEA and MOV AX, mem */ |
| 1619 | 1669 | static void gen_add_A0_ds_seg(DisasContext *s) |
| 1620 | 1670 | { |
| ... | ... | @@ -5791,10 +5841,15 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) |
| 5791 | 5841 | gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
| 5792 | 5842 | /* nothing more to do */ |
| 5793 | 5843 | break; |
| 5794 | - default: | |
| 5795 | - goto illegal_op; | |
| 5844 | + default: /* nop (multi byte) */ | |
| 5845 | + gen_nop_modrm(s, modrm); | |
| 5846 | + break; | |
| 5796 | 5847 | } |
| 5797 | 5848 | break; |
| 5849 | + case 0x119 ... 0x11f: /* nop (multi byte) */ | |
| 5850 | + modrm = ldub_code(s->pc++); | |
| 5851 | + gen_nop_modrm(s, modrm); | |
| 5852 | + break; | |
| 5798 | 5853 | case 0x120: /* mov reg, crN */ |
| 5799 | 5854 | case 0x122: /* mov crN, reg */ |
| 5800 | 5855 | if (s->cpl != 0) { | ... | ... |