diff options
author | Avi Kivity <avi@qumranet.com> | 2007-11-27 12:30:56 -0500 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:53:16 -0500 |
commit | 018a98db74d4cc8967cfc570197b14bcbdddb579 (patch) | |
tree | eea371dd8c2c3060120501572da651c7bfc63f93 | |
parent | 111de5d60c589bca02b49dce076ca588618e0d1c (diff) |
KVM: x86 emulator: unify four switch statements into two
Unify the special instruction switch with the regular instruction switch,
and the two byte special instruction switch with the regular two byte
instruction switch. That makes it much easier to find an instruction or
the place an instruction needs to be added in.
Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r-- | drivers/kvm/x86_emulate.c | 342 |
1 files changed, 168 insertions, 174 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index 499d1ad42bc4..3e3eba70d5ac 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c | |||
@@ -1294,6 +1294,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
1294 | } | 1294 | } |
1295 | c->dst.orig_val = c->dst.val; | 1295 | c->dst.orig_val = c->dst.val; |
1296 | 1296 | ||
1297 | special_insn: | ||
1298 | |||
1297 | if (c->twobyte) | 1299 | if (c->twobyte) |
1298 | goto twobyte_insn; | 1300 | goto twobyte_insn; |
1299 | 1301 | ||
@@ -1378,6 +1380,52 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
1378 | goto cannot_emulate; | 1380 | goto cannot_emulate; |
1379 | c->dst.val = (s32) c->src.val; | 1381 | c->dst.val = (s32) c->src.val; |
1380 | break; | 1382 | break; |
1383 | case 0x6a: /* push imm8 */ | ||
1384 | c->src.val = 0L; | ||
1385 | c->src.val = insn_fetch(s8, 1, c->eip); | ||
1386 | emulate_push(ctxt); | ||
1387 | break; | ||
1388 | case 0x6c: /* insb */ | ||
1389 | case 0x6d: /* insw/insd */ | ||
1390 | if (kvm_emulate_pio_string(ctxt->vcpu, NULL, | ||
1391 | 1, | ||
1392 | (c->d & ByteOp) ? 1 : c->op_bytes, | ||
1393 | c->rep_prefix ? | ||
1394 | address_mask(c->regs[VCPU_REGS_RCX]) : 1, | ||
1395 | (ctxt->eflags & EFLG_DF), | ||
1396 | register_address(ctxt->es_base, | ||
1397 | c->regs[VCPU_REGS_RDI]), | ||
1398 | c->rep_prefix, | ||
1399 | c->regs[VCPU_REGS_RDX]) == 0) { | ||
1400 | c->eip = saved_eip; | ||
1401 | return -1; | ||
1402 | } | ||
1403 | return 0; | ||
1404 | case 0x6e: /* outsb */ | ||
1405 | case 0x6f: /* outsw/outsd */ | ||
1406 | if (kvm_emulate_pio_string(ctxt->vcpu, NULL, | ||
1407 | 0, | ||
1408 | (c->d & ByteOp) ? 1 : c->op_bytes, | ||
1409 | c->rep_prefix ? | ||
1410 | address_mask(c->regs[VCPU_REGS_RCX]) : 1, | ||
1411 | (ctxt->eflags & EFLG_DF), | ||
1412 | register_address(c->override_base ? | ||
1413 | *c->override_base : | ||
1414 | ctxt->ds_base, | ||
1415 | c->regs[VCPU_REGS_RSI]), | ||
1416 | c->rep_prefix, | ||
1417 | c->regs[VCPU_REGS_RDX]) == 0) { | ||
1418 | c->eip = saved_eip; | ||
1419 | return -1; | ||
1420 | } | ||
1421 | return 0; | ||
1422 | case 0x70 ... 0x7f: /* jcc (short) */ { | ||
1423 | int rel = insn_fetch(s8, 1, c->eip); | ||
1424 | |||
1425 | if (test_cc(c->b, ctxt->eflags)) | ||
1426 | JMP_REL(rel); | ||
1427 | break; | ||
1428 | } | ||
1381 | case 0x80 ... 0x83: /* Grp1 */ | 1429 | case 0x80 ... 0x83: /* Grp1 */ |
1382 | switch (c->modrm_reg) { | 1430 | switch (c->modrm_reg) { |
1383 | case 0: | 1431 | case 0: |
@@ -1434,106 +1482,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
1434 | if (rc != 0) | 1482 | if (rc != 0) |
1435 | goto done; | 1483 | goto done; |
1436 | break; | 1484 | break; |
1437 | case 0xa0 ... 0xa1: /* mov */ | ||
1438 | c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX]; | ||
1439 | c->dst.val = c->src.val; | ||
1440 | break; | ||
1441 | case 0xa2 ... 0xa3: /* mov */ | ||
1442 | c->dst.val = (unsigned long)c->regs[VCPU_REGS_RAX]; | ||
1443 | break; | ||
1444 | case 0xc0 ... 0xc1: | ||
1445 | emulate_grp2(ctxt); | ||
1446 | break; | ||
1447 | case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ | ||
1448 | mov: | ||
1449 | c->dst.val = c->src.val; | ||
1450 | break; | ||
1451 | case 0xd0 ... 0xd1: /* Grp2 */ | ||
1452 | c->src.val = 1; | ||
1453 | emulate_grp2(ctxt); | ||
1454 | break; | ||
1455 | case 0xd2 ... 0xd3: /* Grp2 */ | ||
1456 | c->src.val = c->regs[VCPU_REGS_RCX]; | ||
1457 | emulate_grp2(ctxt); | ||
1458 | break; | ||
1459 | case 0xf6 ... 0xf7: /* Grp3 */ | ||
1460 | rc = emulate_grp3(ctxt, ops); | ||
1461 | if (rc != 0) | ||
1462 | goto done; | ||
1463 | break; | ||
1464 | case 0xfe ... 0xff: /* Grp4/Grp5 */ | ||
1465 | rc = emulate_grp45(ctxt, ops); | ||
1466 | if (rc != 0) | ||
1467 | goto done; | ||
1468 | break; | ||
1469 | } | ||
1470 | |||
1471 | writeback: | ||
1472 | rc = writeback(ctxt, ops); | ||
1473 | if (rc != 0) | ||
1474 | goto done; | ||
1475 | |||
1476 | /* Commit shadow register state. */ | ||
1477 | memcpy(ctxt->vcpu->regs, c->regs, sizeof c->regs); | ||
1478 | ctxt->vcpu->rip = c->eip; | ||
1479 | |||
1480 | done: | ||
1481 | if (rc == X86EMUL_UNHANDLEABLE) { | ||
1482 | c->eip = saved_eip; | ||
1483 | return -1; | ||
1484 | } | ||
1485 | return 0; | ||
1486 | |||
1487 | special_insn: | ||
1488 | if (c->twobyte) | ||
1489 | goto twobyte_special_insn; | ||
1490 | switch (c->b) { | ||
1491 | case 0x6a: /* push imm8 */ | ||
1492 | c->src.val = 0L; | ||
1493 | c->src.val = insn_fetch(s8, 1, c->eip); | ||
1494 | emulate_push(ctxt); | ||
1495 | break; | ||
1496 | case 0x6c: /* insb */ | ||
1497 | case 0x6d: /* insw/insd */ | ||
1498 | if (kvm_emulate_pio_string(ctxt->vcpu, NULL, | ||
1499 | 1, | ||
1500 | (c->d & ByteOp) ? 1 : c->op_bytes, | ||
1501 | c->rep_prefix ? | ||
1502 | address_mask(c->regs[VCPU_REGS_RCX]) : 1, | ||
1503 | (ctxt->eflags & EFLG_DF), | ||
1504 | register_address(ctxt->es_base, | ||
1505 | c->regs[VCPU_REGS_RDI]), | ||
1506 | c->rep_prefix, | ||
1507 | c->regs[VCPU_REGS_RDX]) == 0) { | ||
1508 | c->eip = saved_eip; | ||
1509 | return -1; | ||
1510 | } | ||
1511 | return 0; | ||
1512 | case 0x6e: /* outsb */ | ||
1513 | case 0x6f: /* outsw/outsd */ | ||
1514 | if (kvm_emulate_pio_string(ctxt->vcpu, NULL, | ||
1515 | 0, | ||
1516 | (c->d & ByteOp) ? 1 : c->op_bytes, | ||
1517 | c->rep_prefix ? | ||
1518 | address_mask(c->regs[VCPU_REGS_RCX]) : 1, | ||
1519 | (ctxt->eflags & EFLG_DF), | ||
1520 | register_address(c->override_base ? | ||
1521 | *c->override_base : | ||
1522 | ctxt->ds_base, | ||
1523 | c->regs[VCPU_REGS_RSI]), | ||
1524 | c->rep_prefix, | ||
1525 | c->regs[VCPU_REGS_RDX]) == 0) { | ||
1526 | c->eip = saved_eip; | ||
1527 | return -1; | ||
1528 | } | ||
1529 | return 0; | ||
1530 | case 0x70 ... 0x7f: /* jcc (short) */ { | ||
1531 | int rel = insn_fetch(s8, 1, c->eip); | ||
1532 | |||
1533 | if (test_cc(c->b, ctxt->eflags)) | ||
1534 | JMP_REL(rel); | ||
1535 | break; | ||
1536 | } | ||
1537 | case 0x9c: /* pushf */ | 1485 | case 0x9c: /* pushf */ |
1538 | c->src.val = (unsigned long) ctxt->eflags; | 1486 | c->src.val = (unsigned long) ctxt->eflags; |
1539 | emulate_push(ctxt); | 1487 | emulate_push(ctxt); |
@@ -1541,6 +1489,13 @@ special_insn: | |||
1541 | case 0x9d: /* popf */ | 1489 | case 0x9d: /* popf */ |
1542 | c->dst.ptr = (unsigned long *) &ctxt->eflags; | 1490 | c->dst.ptr = (unsigned long *) &ctxt->eflags; |
1543 | goto pop_instruction; | 1491 | goto pop_instruction; |
1492 | case 0xa0 ... 0xa1: /* mov */ | ||
1493 | c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX]; | ||
1494 | c->dst.val = c->src.val; | ||
1495 | break; | ||
1496 | case 0xa2 ... 0xa3: /* mov */ | ||
1497 | c->dst.val = (unsigned long)c->regs[VCPU_REGS_RAX]; | ||
1498 | break; | ||
1544 | case 0xa4 ... 0xa5: /* movs */ | 1499 | case 0xa4 ... 0xa5: /* movs */ |
1545 | c->dst.type = OP_MEM; | 1500 | c->dst.type = OP_MEM; |
1546 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | 1501 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; |
@@ -1627,9 +1582,24 @@ special_insn: | |||
1627 | case 0xae ... 0xaf: /* scas */ | 1582 | case 0xae ... 0xaf: /* scas */ |
1628 | DPRINTF("Urk! I don't handle SCAS.\n"); | 1583 | DPRINTF("Urk! I don't handle SCAS.\n"); |
1629 | goto cannot_emulate; | 1584 | goto cannot_emulate; |
1585 | case 0xc0 ... 0xc1: | ||
1586 | emulate_grp2(ctxt); | ||
1587 | break; | ||
1630 | case 0xc3: /* ret */ | 1588 | case 0xc3: /* ret */ |
1631 | c->dst.ptr = &c->eip; | 1589 | c->dst.ptr = &c->eip; |
1632 | goto pop_instruction; | 1590 | goto pop_instruction; |
1591 | case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ | ||
1592 | mov: | ||
1593 | c->dst.val = c->src.val; | ||
1594 | break; | ||
1595 | case 0xd0 ... 0xd1: /* Grp2 */ | ||
1596 | c->src.val = 1; | ||
1597 | emulate_grp2(ctxt); | ||
1598 | break; | ||
1599 | case 0xd2 ... 0xd3: /* Grp2 */ | ||
1600 | c->src.val = c->regs[VCPU_REGS_RCX]; | ||
1601 | emulate_grp2(ctxt); | ||
1602 | break; | ||
1633 | case 0xe8: /* call (near) */ { | 1603 | case 0xe8: /* call (near) */ { |
1634 | long int rel; | 1604 | long int rel; |
1635 | switch (c->op_bytes) { | 1605 | switch (c->op_bytes) { |
@@ -1662,6 +1632,11 @@ special_insn: | |||
1662 | ctxt->eflags ^= EFLG_CF; | 1632 | ctxt->eflags ^= EFLG_CF; |
1663 | c->dst.type = OP_NONE; /* Disable writeback. */ | 1633 | c->dst.type = OP_NONE; /* Disable writeback. */ |
1664 | break; | 1634 | break; |
1635 | case 0xf6 ... 0xf7: /* Grp3 */ | ||
1636 | rc = emulate_grp3(ctxt, ops); | ||
1637 | if (rc != 0) | ||
1638 | goto done; | ||
1639 | break; | ||
1665 | case 0xf8: /* clc */ | 1640 | case 0xf8: /* clc */ |
1666 | ctxt->eflags &= ~EFLG_CF; | 1641 | ctxt->eflags &= ~EFLG_CF; |
1667 | c->dst.type = OP_NONE; /* Disable writeback. */ | 1642 | c->dst.type = OP_NONE; /* Disable writeback. */ |
@@ -1674,8 +1649,28 @@ special_insn: | |||
1674 | ctxt->eflags |= X86_EFLAGS_IF; | 1649 | ctxt->eflags |= X86_EFLAGS_IF; |
1675 | c->dst.type = OP_NONE; /* Disable writeback. */ | 1650 | c->dst.type = OP_NONE; /* Disable writeback. */ |
1676 | break; | 1651 | break; |
1652 | case 0xfe ... 0xff: /* Grp4/Grp5 */ | ||
1653 | rc = emulate_grp45(ctxt, ops); | ||
1654 | if (rc != 0) | ||
1655 | goto done; | ||
1656 | break; | ||
1677 | } | 1657 | } |
1678 | goto writeback; | 1658 | |
1659 | writeback: | ||
1660 | rc = writeback(ctxt, ops); | ||
1661 | if (rc != 0) | ||
1662 | goto done; | ||
1663 | |||
1664 | /* Commit shadow register state. */ | ||
1665 | memcpy(ctxt->vcpu->regs, c->regs, sizeof c->regs); | ||
1666 | ctxt->vcpu->rip = c->eip; | ||
1667 | |||
1668 | done: | ||
1669 | if (rc == X86EMUL_UNHANDLEABLE) { | ||
1670 | c->eip = saved_eip; | ||
1671 | return -1; | ||
1672 | } | ||
1673 | return 0; | ||
1679 | 1674 | ||
1680 | twobyte_insn: | 1675 | twobyte_insn: |
1681 | switch (c->b) { | 1676 | switch (c->b) { |
@@ -1737,6 +1732,23 @@ twobyte_insn: | |||
1737 | /* Disable writeback. */ | 1732 | /* Disable writeback. */ |
1738 | c->dst.type = OP_NONE; | 1733 | c->dst.type = OP_NONE; |
1739 | break; | 1734 | break; |
1735 | case 0x06: | ||
1736 | emulate_clts(ctxt->vcpu); | ||
1737 | c->dst.type = OP_NONE; | ||
1738 | break; | ||
1739 | case 0x08: /* invd */ | ||
1740 | case 0x09: /* wbinvd */ | ||
1741 | case 0x0d: /* GrpP (prefetch) */ | ||
1742 | case 0x18: /* Grp16 (prefetch/nop) */ | ||
1743 | c->dst.type = OP_NONE; | ||
1744 | break; | ||
1745 | case 0x20: /* mov cr, reg */ | ||
1746 | if (c->modrm_mod != 3) | ||
1747 | goto cannot_emulate; | ||
1748 | c->regs[c->modrm_rm] = | ||
1749 | realmode_get_cr(ctxt->vcpu, c->modrm_reg); | ||
1750 | c->dst.type = OP_NONE; /* no writeback */ | ||
1751 | break; | ||
1740 | case 0x21: /* mov from dr to reg */ | 1752 | case 0x21: /* mov from dr to reg */ |
1741 | if (c->modrm_mod != 3) | 1753 | if (c->modrm_mod != 3) |
1742 | goto cannot_emulate; | 1754 | goto cannot_emulate; |
@@ -1745,6 +1757,13 @@ twobyte_insn: | |||
1745 | goto cannot_emulate; | 1757 | goto cannot_emulate; |
1746 | c->dst.type = OP_NONE; /* no writeback */ | 1758 | c->dst.type = OP_NONE; /* no writeback */ |
1747 | break; | 1759 | break; |
1760 | case 0x22: /* mov reg, cr */ | ||
1761 | if (c->modrm_mod != 3) | ||
1762 | goto cannot_emulate; | ||
1763 | realmode_set_cr(ctxt->vcpu, | ||
1764 | c->modrm_reg, c->modrm_val, &ctxt->eflags); | ||
1765 | c->dst.type = OP_NONE; | ||
1766 | break; | ||
1748 | case 0x23: /* mov from reg to dr */ | 1767 | case 0x23: /* mov from reg to dr */ |
1749 | if (c->modrm_mod != 3) | 1768 | if (c->modrm_mod != 3) |
1750 | goto cannot_emulate; | 1769 | goto cannot_emulate; |
@@ -1754,11 +1773,58 @@ twobyte_insn: | |||
1754 | goto cannot_emulate; | 1773 | goto cannot_emulate; |
1755 | c->dst.type = OP_NONE; /* no writeback */ | 1774 | c->dst.type = OP_NONE; /* no writeback */ |
1756 | break; | 1775 | break; |
1776 | case 0x30: | ||
1777 | /* wrmsr */ | ||
1778 | msr_data = (u32)c->regs[VCPU_REGS_RAX] | ||
1779 | | ((u64)c->regs[VCPU_REGS_RDX] << 32); | ||
1780 | rc = kvm_set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data); | ||
1781 | if (rc) { | ||
1782 | kvm_x86_ops->inject_gp(ctxt->vcpu, 0); | ||
1783 | c->eip = ctxt->vcpu->rip; | ||
1784 | } | ||
1785 | rc = X86EMUL_CONTINUE; | ||
1786 | c->dst.type = OP_NONE; | ||
1787 | break; | ||
1788 | case 0x32: | ||
1789 | /* rdmsr */ | ||
1790 | rc = kvm_get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data); | ||
1791 | if (rc) { | ||
1792 | kvm_x86_ops->inject_gp(ctxt->vcpu, 0); | ||
1793 | c->eip = ctxt->vcpu->rip; | ||
1794 | } else { | ||
1795 | c->regs[VCPU_REGS_RAX] = (u32)msr_data; | ||
1796 | c->regs[VCPU_REGS_RDX] = msr_data >> 32; | ||
1797 | } | ||
1798 | rc = X86EMUL_CONTINUE; | ||
1799 | c->dst.type = OP_NONE; | ||
1800 | break; | ||
1757 | case 0x40 ... 0x4f: /* cmov */ | 1801 | case 0x40 ... 0x4f: /* cmov */ |
1758 | c->dst.val = c->dst.orig_val = c->src.val; | 1802 | c->dst.val = c->dst.orig_val = c->src.val; |
1759 | if (!test_cc(c->b, ctxt->eflags)) | 1803 | if (!test_cc(c->b, ctxt->eflags)) |
1760 | c->dst.type = OP_NONE; /* no writeback */ | 1804 | c->dst.type = OP_NONE; /* no writeback */ |
1761 | break; | 1805 | break; |
1806 | case 0x80 ... 0x8f: /* jnz rel, etc*/ { | ||
1807 | long int rel; | ||
1808 | |||
1809 | switch (c->op_bytes) { | ||
1810 | case 2: | ||
1811 | rel = insn_fetch(s16, 2, c->eip); | ||
1812 | break; | ||
1813 | case 4: | ||
1814 | rel = insn_fetch(s32, 4, c->eip); | ||
1815 | break; | ||
1816 | case 8: | ||
1817 | rel = insn_fetch(s64, 8, c->eip); | ||
1818 | break; | ||
1819 | default: | ||
1820 | DPRINTF("jnz: Invalid op_bytes\n"); | ||
1821 | goto cannot_emulate; | ||
1822 | } | ||
1823 | if (test_cc(c->b, ctxt->eflags)) | ||
1824 | JMP_REL(rel); | ||
1825 | c->dst.type = OP_NONE; | ||
1826 | break; | ||
1827 | } | ||
1762 | case 0xa3: | 1828 | case 0xa3: |
1763 | bt: /* bt */ | 1829 | bt: /* bt */ |
1764 | c->dst.type = OP_NONE; | 1830 | c->dst.type = OP_NONE; |
@@ -1828,85 +1894,13 @@ twobyte_insn: | |||
1828 | c->dst.val = (c->op_bytes == 4) ? (u32) c->src.val : | 1894 | c->dst.val = (c->op_bytes == 4) ? (u32) c->src.val : |
1829 | (u64) c->src.val; | 1895 | (u64) c->src.val; |
1830 | break; | 1896 | break; |
1831 | } | ||
1832 | goto writeback; | ||
1833 | |||
1834 | twobyte_special_insn: | ||
1835 | switch (c->b) { | ||
1836 | case 0x06: | ||
1837 | emulate_clts(ctxt->vcpu); | ||
1838 | break; | ||
1839 | case 0x08: /* invd */ | ||
1840 | break; | ||
1841 | case 0x09: /* wbinvd */ | ||
1842 | break; | ||
1843 | case 0x0d: /* GrpP (prefetch) */ | ||
1844 | case 0x18: /* Grp16 (prefetch/nop) */ | ||
1845 | break; | ||
1846 | case 0x20: /* mov cr, reg */ | ||
1847 | if (c->modrm_mod != 3) | ||
1848 | goto cannot_emulate; | ||
1849 | c->regs[c->modrm_rm] = | ||
1850 | realmode_get_cr(ctxt->vcpu, c->modrm_reg); | ||
1851 | break; | ||
1852 | case 0x22: /* mov reg, cr */ | ||
1853 | if (c->modrm_mod != 3) | ||
1854 | goto cannot_emulate; | ||
1855 | realmode_set_cr(ctxt->vcpu, | ||
1856 | c->modrm_reg, c->modrm_val, &ctxt->eflags); | ||
1857 | break; | ||
1858 | case 0x30: | ||
1859 | /* wrmsr */ | ||
1860 | msr_data = (u32)c->regs[VCPU_REGS_RAX] | ||
1861 | | ((u64)c->regs[VCPU_REGS_RDX] << 32); | ||
1862 | rc = kvm_set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data); | ||
1863 | if (rc) { | ||
1864 | kvm_x86_ops->inject_gp(ctxt->vcpu, 0); | ||
1865 | c->eip = ctxt->vcpu->rip; | ||
1866 | } | ||
1867 | rc = X86EMUL_CONTINUE; | ||
1868 | break; | ||
1869 | case 0x32: | ||
1870 | /* rdmsr */ | ||
1871 | rc = kvm_get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data); | ||
1872 | if (rc) { | ||
1873 | kvm_x86_ops->inject_gp(ctxt->vcpu, 0); | ||
1874 | c->eip = ctxt->vcpu->rip; | ||
1875 | } else { | ||
1876 | c->regs[VCPU_REGS_RAX] = (u32)msr_data; | ||
1877 | c->regs[VCPU_REGS_RDX] = msr_data >> 32; | ||
1878 | } | ||
1879 | rc = X86EMUL_CONTINUE; | ||
1880 | break; | ||
1881 | case 0x80 ... 0x8f: /* jnz rel, etc*/ { | ||
1882 | long int rel; | ||
1883 | |||
1884 | switch (c->op_bytes) { | ||
1885 | case 2: | ||
1886 | rel = insn_fetch(s16, 2, c->eip); | ||
1887 | break; | ||
1888 | case 4: | ||
1889 | rel = insn_fetch(s32, 4, c->eip); | ||
1890 | break; | ||
1891 | case 8: | ||
1892 | rel = insn_fetch(s64, 8, c->eip); | ||
1893 | break; | ||
1894 | default: | ||
1895 | DPRINTF("jnz: Invalid op_bytes\n"); | ||
1896 | goto cannot_emulate; | ||
1897 | } | ||
1898 | if (test_cc(c->b, ctxt->eflags)) | ||
1899 | JMP_REL(rel); | ||
1900 | break; | ||
1901 | } | ||
1902 | case 0xc7: /* Grp9 (cmpxchg8b) */ | 1897 | case 0xc7: /* Grp9 (cmpxchg8b) */ |
1903 | rc = emulate_grp9(ctxt, ops, memop); | 1898 | rc = emulate_grp9(ctxt, ops, memop); |
1904 | if (rc != 0) | 1899 | if (rc != 0) |
1905 | goto done; | 1900 | goto done; |
1901 | c->dst.type = OP_NONE; | ||
1906 | break; | 1902 | break; |
1907 | } | 1903 | } |
1908 | /* Disable writeback. */ | ||
1909 | c->dst.type = OP_NONE; | ||
1910 | goto writeback; | 1904 | goto writeback; |
1911 | 1905 | ||
1912 | cannot_emulate: | 1906 | cannot_emulate: |