aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-08-18 12:20:21 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:51:14 -0400
commit39f21ee546cf7d563d813c5fb4473431c1d8fce7 (patch)
tree0761137083bb141e1f48c711e0c424cb94842089 /arch/x86/kvm/emulate.c
parent48bb5d3c401679e41e7a7f06ca31b3e54a6168f7 (diff)
KVM: x86 emulator: consolidate immediate decode into a function
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c109
1 files changed, 64 insertions, 45 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index ed192d220201..95543a6beb53 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2541,6 +2541,55 @@ static struct opcode twobyte_table[256] = {
2541#undef GD 2541#undef GD
2542#undef I 2542#undef I
2543 2543
2544static unsigned imm_size(struct decode_cache *c)
2545{
2546 unsigned size;
2547
2548 size = (c->d & ByteOp) ? 1 : c->op_bytes;
2549 if (size == 8)
2550 size = 4;
2551 return size;
2552}
2553
2554static int decode_imm(struct x86_emulate_ctxt *ctxt, struct operand *op,
2555 unsigned size, bool sign_extension)
2556{
2557 struct decode_cache *c = &ctxt->decode;
2558 struct x86_emulate_ops *ops = ctxt->ops;
2559 int rc = X86EMUL_CONTINUE;
2560
2561 op->type = OP_IMM;
2562 op->bytes = size;
2563 op->addr.mem = c->eip;
2564 /* NB. Immediates are sign-extended as necessary. */
2565 switch (op->bytes) {
2566 case 1:
2567 op->val = insn_fetch(s8, 1, c->eip);
2568 break;
2569 case 2:
2570 op->val = insn_fetch(s16, 2, c->eip);
2571 break;
2572 case 4:
2573 op->val = insn_fetch(s32, 4, c->eip);
2574 break;
2575 }
2576 if (!sign_extension) {
2577 switch (op->bytes) {
2578 case 1:
2579 op->val &= 0xff;
2580 break;
2581 case 2:
2582 op->val &= 0xffff;
2583 break;
2584 case 4:
2585 op->val &= 0xffffffff;
2586 break;
2587 }
2588 }
2589done:
2590 return rc;
2591}
2592
2544int 2593int
2545x86_decode_insn(struct x86_emulate_ctxt *ctxt) 2594x86_decode_insn(struct x86_emulate_ctxt *ctxt)
2546{ 2595{
@@ -2730,52 +2779,19 @@ done_prefixes:
2730 c->src = memop; 2779 c->src = memop;
2731 break; 2780 break;
2732 case SrcImmU16: 2781 case SrcImmU16:
2733 c->src.bytes = 2; 2782 rc = decode_imm(ctxt, &c->src, 2, false);
2734 goto srcimm; 2783 break;
2735 case SrcImm: 2784 case SrcImm:
2785 rc = decode_imm(ctxt, &c->src, imm_size(c), true);
2786 break;
2736 case SrcImmU: 2787 case SrcImmU:
2737 c->src.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; 2788 rc = decode_imm(ctxt, &c->src, imm_size(c), false);
2738 if (c->src.bytes == 8)
2739 c->src.bytes = 4;
2740 srcimm:
2741 c->src.type = OP_IMM;
2742 c->src.addr.mem = c->eip;
2743 /* NB. Immediates are sign-extended as necessary. */
2744 switch (c->src.bytes) {
2745 case 1:
2746 c->src.val = insn_fetch(s8, 1, c->eip);
2747 break;
2748 case 2:
2749 c->src.val = insn_fetch(s16, 2, c->eip);
2750 break;
2751 case 4:
2752 c->src.val = insn_fetch(s32, 4, c->eip);
2753 break;
2754 }
2755 if ((c->d & SrcMask) == SrcImmU
2756 || (c->d & SrcMask) == SrcImmU16) {
2757 switch (c->src.bytes) {
2758 case 1:
2759 c->src.val &= 0xff;
2760 break;
2761 case 2:
2762 c->src.val &= 0xffff;
2763 break;
2764 case 4:
2765 c->src.val &= 0xffffffff;
2766 break;
2767 }
2768 }
2769 break; 2789 break;
2770 case SrcImmByte: 2790 case SrcImmByte:
2791 rc = decode_imm(ctxt, &c->src, 1, true);
2792 break;
2771 case SrcImmUByte: 2793 case SrcImmUByte:
2772 c->src.type = OP_IMM; 2794 rc = decode_imm(ctxt, &c->src, 1, false);
2773 c->src.addr.mem = c->eip;
2774 c->src.bytes = 1;
2775 if ((c->d & SrcMask) == SrcImmByte)
2776 c->src.val = insn_fetch(s8, 1, c->eip);
2777 else
2778 c->src.val = insn_fetch(u8, 1, c->eip);
2779 break; 2795 break;
2780 case SrcAcc: 2796 case SrcAcc:
2781 c->src.type = OP_REG; 2797 c->src.type = OP_REG;
@@ -2807,6 +2823,9 @@ done_prefixes:
2807 break; 2823 break;
2808 } 2824 }
2809 2825
2826 if (rc != X86EMUL_CONTINUE)
2827 goto done;
2828
2810 /* 2829 /*
2811 * Decode and fetch the second source operand: register, memory 2830 * Decode and fetch the second source operand: register, memory
2812 * or immediate. 2831 * or immediate.
@@ -2819,10 +2838,7 @@ done_prefixes:
2819 c->src2.val = c->regs[VCPU_REGS_RCX] & 0x8; 2838 c->src2.val = c->regs[VCPU_REGS_RCX] & 0x8;
2820 break; 2839 break;
2821 case Src2ImmByte: 2840 case Src2ImmByte:
2822 c->src2.type = OP_IMM; 2841 rc = decode_imm(ctxt, &c->src2, 1, true);
2823 c->src2.addr.mem = c->eip;
2824 c->src2.bytes = 1;
2825 c->src2.val = insn_fetch(u8, 1, c->eip);
2826 break; 2842 break;
2827 case Src2One: 2843 case Src2One:
2828 c->src2.bytes = 1; 2844 c->src2.bytes = 1;
@@ -2830,6 +2846,9 @@ done_prefixes:
2830 break; 2846 break;
2831 } 2847 }
2832 2848
2849 if (rc != X86EMUL_CONTINUE)
2850 goto done;
2851
2833 /* Decode and fetch the destination operand: register or memory. */ 2852 /* Decode and fetch the destination operand: register or memory. */
2834 switch (c->d & DstMask) { 2853 switch (c->d & DstMask) {
2835 case DstReg: 2854 case DstReg: