diff options
author | Avi Kivity <avi@redhat.com> | 2010-08-18 12:20:21 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:51:14 -0400 |
commit | 39f21ee546cf7d563d813c5fb4473431c1d8fce7 (patch) | |
tree | 0761137083bb141e1f48c711e0c424cb94842089 /arch/x86/kvm/emulate.c | |
parent | 48bb5d3c401679e41e7a7f06ca31b3e54a6168f7 (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.c | 109 |
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 | ||
2544 | static 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 | |||
2554 | static 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 | } | ||
2589 | done: | ||
2590 | return rc; | ||
2591 | } | ||
2592 | |||
2544 | int | 2593 | int |
2545 | x86_decode_insn(struct x86_emulate_ctxt *ctxt) | 2594 | x86_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: |