aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuillaume Thouvenin <guillaume.thouvenin@ext.bull.net>2007-11-26 07:49:09 -0500
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:53:15 -0500
commitd7e5117a2568f7407e98ca85155511ecfe4f0631 (patch)
tree7f9bcd5b42d4ef8f40b396ac3c979399a41dcfab
parente8d8d7fe8877c594c08f40cc7c013626cfe3e9cc (diff)
KVM: x86 emulator: cmps instruction
Add emulation for the cmps instruction. This lets OpenBSD boot on kvm. Signed-off-by: Guillaume Thouvenin <guillaume.thouvenin@ext.bull.net> Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--drivers/kvm/x86_emulate.c58
1 files changed, 56 insertions, 2 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 22fdf0ac6615..84e536603f5a 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -1535,10 +1535,31 @@ special_insn:
1535 break; 1535 break;
1536 } 1536 }
1537 if (c->rep_prefix) { 1537 if (c->rep_prefix) {
1538 /* All REP prefixes have the same first termination condition */
1538 if (c->regs[VCPU_REGS_RCX] == 0) { 1539 if (c->regs[VCPU_REGS_RCX] == 0) {
1539 ctxt->vcpu->rip = c->eip; 1540 ctxt->vcpu->rip = c->eip;
1540 goto done; 1541 goto done;
1541 } 1542 }
1543 /* The second termination condition only applies for REPE
1544 * and REPNE. Test if the repeat string operation prefix is
1545 * REPE/REPZ or REPNE/REPNZ and if it's the case it tests the
1546 * corresponding termination condition according to:
1547 * - if REPE/REPZ and ZF = 0 then done
1548 * - if REPNE/REPNZ and ZF = 1 then done
1549 */
1550 if ((c->b == 0xa6) || (c->b == 0xa7) ||
1551 (c->b == 0xae) || (c->b == 0xaf)) {
1552 if ((c->rep_prefix == REPE_PREFIX) &&
1553 ((ctxt->eflags & EFLG_ZF) == 0)) {
1554 ctxt->vcpu->rip = c->eip;
1555 goto done;
1556 }
1557 if ((c->rep_prefix == REPNE_PREFIX) &&
1558 ((ctxt->eflags & EFLG_ZF) == EFLG_ZF)) {
1559 ctxt->vcpu->rip = c->eip;
1560 goto done;
1561 }
1562 }
1542 c->regs[VCPU_REGS_RCX]--; 1563 c->regs[VCPU_REGS_RCX]--;
1543 c->eip = ctxt->vcpu->rip; 1564 c->eip = ctxt->vcpu->rip;
1544 } 1565 }
@@ -1564,8 +1585,41 @@ special_insn:
1564 : c->dst.bytes); 1585 : c->dst.bytes);
1565 break; 1586 break;
1566 case 0xa6 ... 0xa7: /* cmps */ 1587 case 0xa6 ... 0xa7: /* cmps */
1567 DPRINTF("Urk! I don't handle CMPS.\n"); 1588 c->src.type = OP_NONE; /* Disable writeback. */
1568 goto cannot_emulate; 1589 c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
1590 c->src.ptr = (unsigned long *)register_address(
1591 c->override_base ? *c->override_base :
1592 ctxt->ds_base,
1593 c->regs[VCPU_REGS_RSI]);
1594 if ((rc = ops->read_emulated((unsigned long)c->src.ptr,
1595 &c->src.val,
1596 c->src.bytes,
1597 ctxt->vcpu)) != 0)
1598 goto done;
1599
1600 c->dst.type = OP_NONE; /* Disable writeback. */
1601 c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
1602 c->dst.ptr = (unsigned long *)register_address(
1603 ctxt->es_base,
1604 c->regs[VCPU_REGS_RDI]);
1605 if ((rc = ops->read_emulated((unsigned long)c->dst.ptr,
1606 &c->dst.val,
1607 c->dst.bytes,
1608 ctxt->vcpu)) != 0)
1609 goto done;
1610
1611 DPRINTF("cmps: mem1=0x%p mem2=0x%p\n", c->src.ptr, c->dst.ptr);
1612
1613 emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
1614
1615 register_address_increment(c->regs[VCPU_REGS_RSI],
1616 (ctxt->eflags & EFLG_DF) ? -c->src.bytes
1617 : c->src.bytes);
1618 register_address_increment(c->regs[VCPU_REGS_RDI],
1619 (ctxt->eflags & EFLG_DF) ? -c->dst.bytes
1620 : c->dst.bytes);
1621
1622 break;
1569 case 0xaa ... 0xab: /* stos */ 1623 case 0xaa ... 0xab: /* stos */
1570 c->dst.type = OP_MEM; 1624 c->dst.type = OP_MEM;
1571 c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; 1625 c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;