aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/x86_emulate.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-10-31 05:15:56 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:59 -0500
commit33615aa956521923eab0552994b5961cd3034042 (patch)
treedae9983159614d9bdfed6d60201e60f1a72105f0 /drivers/kvm/x86_emulate.c
parent3c118e24af821d68dca0ba81e9499820c840c133 (diff)
KVM: x86 emulator: centralize decoding of one-byte register access insns
Instructions like 'inc reg' that have the register operand encoded in the opcode are currently specially decoded. Extend decode_register_operand() to handle that case, indicated by having DstReg or SrcReg without ModRM. Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r--drivers/kvm/x86_emulate.c103
1 files changed, 46 insertions, 57 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 58ceb6616364..884e4a2e47e6 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -99,17 +99,13 @@ static u16 opcode_table[256] = {
99 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, 99 ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
100 0, 0, 0, 0, 100 0, 0, 0, 0,
101 /* 0x40 - 0x47 */ 101 /* 0x40 - 0x47 */
102 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, 102 DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
103 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
104 /* 0x48 - 0x4F */ 103 /* 0x48 - 0x4F */
105 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, 104 DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
106 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
107 /* 0x50 - 0x57 */ 105 /* 0x50 - 0x57 */
108 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, 106 SrcReg, SrcReg, SrcReg, SrcReg, SrcReg, SrcReg, SrcReg, SrcReg,
109 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
110 /* 0x58 - 0x5F */ 107 /* 0x58 - 0x5F */
111 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, 108 DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
112 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
113 /* 0x60 - 0x67 */ 109 /* 0x60 - 0x67 */
114 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ , 110 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,
115 0, 0, 0, 0, 111 0, 0, 0, 0,
@@ -525,13 +521,17 @@ static void decode_register_operand(struct operand *op,
525 int highbyte_regs, 521 int highbyte_regs,
526 int inhibit_bytereg) 522 int inhibit_bytereg)
527{ 523{
524 unsigned reg = c->modrm_reg;
525
526 if (!(c->d & ModRM))
527 reg = (c->b & 7) | ((c->rex_prefix & 1) << 3);
528 op->type = OP_REG; 528 op->type = OP_REG;
529 if ((c->d & ByteOp) && !inhibit_bytereg) { 529 if ((c->d & ByteOp) && !inhibit_bytereg) {
530 op->ptr = decode_register(c->modrm_reg, c->regs, highbyte_regs); 530 op->ptr = decode_register(reg, c->regs, highbyte_regs);
531 op->val = *(u8 *)op->ptr; 531 op->val = *(u8 *)op->ptr;
532 op->bytes = 1; 532 op->bytes = 1;
533 } else { 533 } else {
534 op->ptr = decode_register(c->modrm_reg, c->regs, 0); 534 op->ptr = decode_register(reg, c->regs, 0);
535 op->bytes = c->op_bytes; 535 op->bytes = c->op_bytes;
536 switch (op->bytes) { 536 switch (op->bytes) {
537 case 2: 537 case 2:
@@ -552,7 +552,7 @@ int
552x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) 552x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
553{ 553{
554 struct decode_cache *c = &ctxt->decode; 554 struct decode_cache *c = &ctxt->decode;
555 u8 sib, rex_prefix = 0; 555 u8 sib;
556 int rc = 0; 556 int rc = 0;
557 int mode = ctxt->mode; 557 int mode = ctxt->mode;
558 int index_reg = 0, base_reg = 0, scale, rip_relative = 0; 558 int index_reg = 0, base_reg = 0, scale, rip_relative = 0;
@@ -616,7 +616,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
616 case 0x40 ... 0x4f: /* REX */ 616 case 0x40 ... 0x4f: /* REX */
617 if (mode != X86EMUL_MODE_PROT64) 617 if (mode != X86EMUL_MODE_PROT64)
618 goto done_prefixes; 618 goto done_prefixes;
619 rex_prefix = c->b; 619 c->rex_prefix = c->b;
620 continue; 620 continue;
621 case 0xf0: /* LOCK */ 621 case 0xf0: /* LOCK */
622 c->lock_prefix = 1; 622 c->lock_prefix = 1;
@@ -631,18 +631,18 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
631 631
632 /* Any legacy prefix after a REX prefix nullifies its effect. */ 632 /* Any legacy prefix after a REX prefix nullifies its effect. */
633 633
634 rex_prefix = 0; 634 c->rex_prefix = 0;
635 } 635 }
636 636
637done_prefixes: 637done_prefixes:
638 638
639 /* REX prefix. */ 639 /* REX prefix. */
640 if (rex_prefix) { 640 if (c->rex_prefix) {
641 if (rex_prefix & 8) 641 if (c->rex_prefix & 8)
642 c->op_bytes = 8; /* REX.W */ 642 c->op_bytes = 8; /* REX.W */
643 c->modrm_reg = (rex_prefix & 4) << 1; /* REX.R */ 643 c->modrm_reg = (c->rex_prefix & 4) << 1; /* REX.R */
644 index_reg = (rex_prefix & 2) << 2; /* REX.X */ 644 index_reg = (c->rex_prefix & 2) << 2; /* REX.X */
645 c->modrm_rm = base_reg = (rex_prefix & 1) << 3; /* REG.B */ 645 c->modrm_rm = base_reg = (c->rex_prefix & 1) << 3; /* REG.B */
646 } 646 }
647 647
648 /* Opcode byte(s). */ 648 /* Opcode byte(s). */
@@ -837,7 +837,7 @@ modrm_done:
837 case SrcNone: 837 case SrcNone:
838 break; 838 break;
839 case SrcReg: 839 case SrcReg:
840 decode_register_operand(&c->src, c, rex_prefix == 0, 0); 840 decode_register_operand(&c->src, c, c->rex_prefix == 0, 0);
841 break; 841 break;
842 case SrcMem16: 842 case SrcMem16:
843 c->src.bytes = 2; 843 c->src.bytes = 2;
@@ -895,7 +895,7 @@ modrm_done:
895 /* Special instructions do their own operand decoding. */ 895 /* Special instructions do their own operand decoding. */
896 return 0; 896 return 0;
897 case DstReg: 897 case DstReg:
898 decode_register_operand(&c->dst, c, rex_prefix == 0, 898 decode_register_operand(&c->dst, c, c->rex_prefix == 0,
899 c->twobyte && (c->b == 0xb6 || c->b == 0xb7)); 899 c->twobyte && (c->b == 0xb6 || c->b == 0xb7));
900 break; 900 break;
901 case DstMem: 901 case DstMem:
@@ -1258,6 +1258,32 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1258 cmp: /* cmp */ 1258 cmp: /* cmp */
1259 emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags); 1259 emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
1260 break; 1260 break;
1261 case 0x40 ... 0x47: /* inc r16/r32 */
1262 emulate_1op("inc", c->dst, ctxt->eflags);
1263 break;
1264 case 0x48 ... 0x4f: /* dec r16/r32 */
1265 emulate_1op("dec", c->dst, ctxt->eflags);
1266 break;
1267 case 0x50 ... 0x57: /* push reg */
1268 c->dst.type = OP_MEM;
1269 c->dst.bytes = c->op_bytes;
1270 c->dst.val = c->src.val;
1271 register_address_increment(c->regs[VCPU_REGS_RSP],
1272 -c->op_bytes);
1273 c->dst.ptr = (void *) register_address(
1274 ctxt->ss_base, c->regs[VCPU_REGS_RSP]);
1275 break;
1276 case 0x58 ... 0x5f: /* pop reg */
1277 pop_instruction:
1278 if ((rc = ops->read_std(register_address(ctxt->ss_base,
1279 c->regs[VCPU_REGS_RSP]), c->dst.ptr,
1280 c->op_bytes, ctxt->vcpu)) != 0)
1281 goto done;
1282
1283 register_address_increment(c->regs[VCPU_REGS_RSP],
1284 c->op_bytes);
1285 c->dst.type = OP_NONE; /* Disable writeback. */
1286 break;
1261 case 0x63: /* movsxd */ 1287 case 0x63: /* movsxd */
1262 if (ctxt->mode != X86EMUL_MODE_PROT64) 1288 if (ctxt->mode != X86EMUL_MODE_PROT64)
1263 goto cannot_emulate; 1289 goto cannot_emulate;
@@ -1373,43 +1399,6 @@ special_insn:
1373 if (c->twobyte) 1399 if (c->twobyte)
1374 goto twobyte_special_insn; 1400 goto twobyte_special_insn;
1375 switch (c->b) { 1401 switch (c->b) {
1376 case 0x40 ... 0x47: /* inc r16/r32 */
1377 c->dst.bytes = c->op_bytes;
1378 c->dst.ptr = (unsigned long *)&c->regs[c->b & 0x7];
1379 c->dst.val = *c->dst.ptr;
1380 emulate_1op("inc", c->dst, ctxt->eflags);
1381 break;
1382 case 0x48 ... 0x4f: /* dec r16/r32 */
1383 c->dst.bytes = c->op_bytes;
1384 c->dst.ptr = (unsigned long *)&c->regs[c->b & 0x7];
1385 c->dst.val = *c->dst.ptr;
1386 emulate_1op("dec", c->dst, ctxt->eflags);
1387 break;
1388 case 0x50 ... 0x57: /* push reg */
1389 if (c->op_bytes == 2)
1390 c->src.val = (u16) c->regs[c->b & 0x7];
1391 else
1392 c->src.val = (u32) c->regs[c->b & 0x7];
1393 c->dst.type = OP_MEM;
1394 c->dst.bytes = c->op_bytes;
1395 c->dst.val = c->src.val;
1396 register_address_increment(c->regs[VCPU_REGS_RSP],
1397 -c->op_bytes);
1398 c->dst.ptr = (void *) register_address(
1399 ctxt->ss_base, c->regs[VCPU_REGS_RSP]);
1400 break;
1401 case 0x58 ... 0x5f: /* pop reg */
1402 c->dst.ptr = (unsigned long *)&c->regs[c->b & 0x7];
1403 pop_instruction:
1404 if ((rc = ops->read_std(register_address(ctxt->ss_base,
1405 c->regs[VCPU_REGS_RSP]), c->dst.ptr,
1406 c->op_bytes, ctxt->vcpu)) != 0)
1407 goto done;
1408
1409 register_address_increment(c->regs[VCPU_REGS_RSP],
1410 c->op_bytes);
1411 c->dst.type = OP_NONE; /* Disable writeback. */
1412 break;
1413 case 0x6a: /* push imm8 */ 1402 case 0x6a: /* push imm8 */
1414 c->src.val = 0L; 1403 c->src.val = 0L;
1415 c->src.val = insn_fetch(s8, 1, c->eip); 1404 c->src.val = insn_fetch(s8, 1, c->eip);