aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-11-27 12:30:56 -0500
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:53:16 -0500
commit018a98db74d4cc8967cfc570197b14bcbdddb579 (patch)
treeeea371dd8c2c3060120501572da651c7bfc63f93
parent111de5d60c589bca02b49dce076ca588618e0d1c (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.c342
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
1297special_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
1471writeback:
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
1480done:
1481 if (rc == X86EMUL_UNHANDLEABLE) {
1482 c->eip = saved_eip;
1483 return -1;
1484 }
1485 return 0;
1486
1487special_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