diff options
author | Avi Kivity <avi@redhat.com> | 2011-09-13 03:45:41 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-09-25 12:52:48 -0400 |
commit | a99455499a86bde28fccd84e2119be9cd7c23a3f (patch) | |
tree | cea278f1fa7d9edb1581e0704b44da23be7561cc /arch | |
parent | f09ed83e211d253809e575e05bd4de1e335c0cb2 (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.c | 146 |
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 | ||
3336 | static 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 | |||
3392 | done: | ||
3393 | return rc; | ||
3394 | } | ||
3395 | |||
3319 | int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) | 3396 | int 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 | ||
3656 | done: | 3684 | done: |
3657 | if (ctxt->memopp && ctxt->memopp->type == OP_MEM && ctxt->rip_relative) | 3685 | if (ctxt->memopp && ctxt->memopp->type == OP_MEM && ctxt->rip_relative) |