aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2011-09-13 03:45:41 -0400
committerAvi Kivity <avi@redhat.com>2011-09-25 12:52:48 -0400
commita99455499a86bde28fccd84e2119be9cd7c23a3f (patch)
treecea278f1fa7d9edb1581e0704b44da23be7561cc /arch
parentf09ed83e211d253809e575e05bd4de1e335c0cb2 (diff)
KVM: x86 emulator: split dst decode to a generic decode_operand()
Instead of decoding each operand using its own code, use a generic function. Start with the destination operand. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/emulate.c146
1 files changed, 87 insertions, 59 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 58172fb9a09a..6a6aed9a29df 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -29,6 +29,22 @@
29#include "tss.h" 29#include "tss.h"
30 30
31/* 31/*
32 * Operand types
33 */
34#define OpNone 0
35#define OpImplicit 1 /* No generic decode */
36#define OpReg 2 /* Register */
37#define OpMem 3 /* Memory */
38#define OpAcc 4 /* Accumulator: AL/AX/EAX/RAX */
39#define OpDI 5 /* ES:DI/EDI/RDI */
40#define OpMem64 6 /* Memory, 64-bit */
41#define OpImmUByte 7 /* Zero-extended 8-bit immediate */
42#define OpDX 8 /* DX register */
43
44#define OpBits 4 /* Width of operand field */
45#define OpMask ((1 << OpBits) - 1)
46
47/*
32 * Opcode effective-address decode tables. 48 * Opcode effective-address decode tables.
33 * Note that we only emulate instructions that have at least one memory 49 * Note that we only emulate instructions that have at least one memory
34 * operand (excluding implicit stack references). We assume that stack 50 * operand (excluding implicit stack references). We assume that stack
@@ -40,15 +56,16 @@
40/* Operand sizes: 8-bit operands or specified/overridden size. */ 56/* Operand sizes: 8-bit operands or specified/overridden size. */
41#define ByteOp (1<<0) /* 8-bit operands. */ 57#define ByteOp (1<<0) /* 8-bit operands. */
42/* Destination operand type. */ 58/* Destination operand type. */
43#define ImplicitOps (1<<1) /* Implicit in opcode. No generic decode. */ 59#define DstShift 1
44#define DstReg (2<<1) /* Register operand. */ 60#define ImplicitOps (OpImplicit << DstShift)
45#define DstMem (3<<1) /* Memory operand. */ 61#define DstReg (OpReg << DstShift)
46#define DstAcc (4<<1) /* Destination Accumulator */ 62#define DstMem (OpMem << DstShift)
47#define DstDI (5<<1) /* Destination is in ES:(E)DI */ 63#define DstAcc (OpAcc << DstShift)
48#define DstMem64 (6<<1) /* 64bit memory operand */ 64#define DstDI (OpDI << DstShift)
49#define DstImmUByte (7<<1) /* 8-bit unsigned immediate operand */ 65#define DstMem64 (OpMem64 << DstShift)
50#define DstDX (8<<1) /* Destination is in DX register */ 66#define DstImmUByte (OpImmUByte << DstShift)
51#define DstMask (0xf<<1) 67#define DstDX (OpDX << DstShift)
68#define DstMask (OpMask << DstShift)
52/* Source operand type. */ 69/* Source operand type. */
53#define SrcNone (0<<5) /* No source operand. */ 70#define SrcNone (0<<5) /* No source operand. */
54#define SrcReg (1<<5) /* Register operand. */ 71#define SrcReg (1<<5) /* Register operand. */
@@ -3316,6 +3333,66 @@ done:
3316 return rc; 3333 return rc;
3317} 3334}
3318 3335
3336static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
3337 unsigned d)
3338{
3339 int rc = X86EMUL_CONTINUE;
3340
3341 switch (d) {
3342 case OpReg:
3343 decode_register_operand(ctxt, op,
3344 ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
3345 break;
3346 case OpImmUByte:
3347 op->type = OP_IMM;
3348 op->addr.mem.ea = ctxt->_eip;
3349 op->bytes = 1;
3350 op->val = insn_fetch(u8, ctxt);
3351 break;
3352 case OpMem:
3353 case OpMem64:
3354 *op = ctxt->memop;
3355 ctxt->memopp = op;
3356 if (d == OpMem64)
3357 op->bytes = 8;
3358 else
3359 op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
3360 if (ctxt->d & BitOp)
3361 fetch_bit_operand(ctxt);
3362 op->orig_val = op->val;
3363 break;
3364 case OpAcc:
3365 op->type = OP_REG;
3366 op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
3367 op->addr.reg = &ctxt->regs[VCPU_REGS_RAX];
3368 fetch_register_operand(op);
3369 op->orig_val = op->val;
3370 break;
3371 case OpDI:
3372 op->type = OP_MEM;
3373 op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
3374 op->addr.mem.ea =
3375 register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
3376 op->addr.mem.seg = VCPU_SREG_ES;
3377 op->val = 0;
3378 break;
3379 case OpDX:
3380 op->type = OP_REG;
3381 op->bytes = 2;
3382 op->addr.reg = &ctxt->regs[VCPU_REGS_RDX];
3383 fetch_register_operand(op);
3384 break;
3385 case OpImplicit:
3386 /* Special instructions do their own operand decoding. */
3387 default:
3388 op->type = OP_NONE; /* Disable writeback. */
3389 break;
3390 }
3391
3392done:
3393 return rc;
3394}
3395
3319int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) 3396int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
3320{ 3397{
3321 int rc = X86EMUL_CONTINUE; 3398 int rc = X86EMUL_CONTINUE;
@@ -3602,56 +3679,7 @@ done_prefixes:
3602 goto done; 3679 goto done;
3603 3680
3604 /* Decode and fetch the destination operand: register or memory. */ 3681 /* Decode and fetch the destination operand: register or memory. */
3605 switch (ctxt->d & DstMask) { 3682 rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
3606 case DstReg:
3607 decode_register_operand(ctxt, &ctxt->dst,
3608 ctxt->twobyte && (ctxt->b == 0xb6 || ctxt->b == 0xb7));
3609 break;
3610 case DstImmUByte:
3611 ctxt->dst.type = OP_IMM;
3612 ctxt->dst.addr.mem.ea = ctxt->_eip;
3613 ctxt->dst.bytes = 1;
3614 ctxt->dst.val = insn_fetch(u8, ctxt);
3615 break;
3616 case DstMem:
3617 case DstMem64:
3618 ctxt->dst = ctxt->memop;
3619 ctxt->memopp = &ctxt->dst;
3620 if ((ctxt->d & DstMask) == DstMem64)
3621 ctxt->dst.bytes = 8;
3622 else
3623 ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
3624 if (ctxt->d & BitOp)
3625 fetch_bit_operand(ctxt);
3626 ctxt->dst.orig_val = ctxt->dst.val;
3627 break;
3628 case DstAcc:
3629 ctxt->dst.type = OP_REG;
3630 ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
3631 ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RAX];
3632 fetch_register_operand(&ctxt->dst);
3633 ctxt->dst.orig_val = ctxt->dst.val;
3634 break;
3635 case DstDI:
3636 ctxt->dst.type = OP_MEM;
3637 ctxt->dst.bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
3638 ctxt->dst.addr.mem.ea =
3639 register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
3640 ctxt->dst.addr.mem.seg = VCPU_SREG_ES;
3641 ctxt->dst.val = 0;
3642 break;
3643 case DstDX:
3644 ctxt->dst.type = OP_REG;
3645 ctxt->dst.bytes = 2;
3646 ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
3647 fetch_register_operand(&ctxt->dst);
3648 break;
3649 case ImplicitOps:
3650 /* Special instructions do their own operand decoding. */
3651 default:
3652 ctxt->dst.type = OP_NONE; /* Disable writeback. */
3653 break;
3654 }
3655 3683
3656done: 3684done:
3657 if (ctxt->memopp && ctxt->memopp->type == OP_MEM && ctxt->rip_relative) 3685 if (ctxt->memopp && ctxt->memopp->type == OP_MEM && ctxt->rip_relative)