diff options
author | Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp> | 2011-04-23 05:48:02 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-05-22 08:39:40 -0400 |
commit | d67fc27ae2bdc2d2fb6c8ec4238a12b502b95cc7 (patch) | |
tree | 3a5f9d3eef0a94587516eb139c13162e33d6443c /arch/x86/kvm | |
parent | 6e2ca7d1802bf8ed9908435e34daa116662e7790 (diff) |
KVM: x86 emulator: Use opcode::execute for Group 1, CMPS and SCAS
The following instructions are changed to use opcode::execute.
Group 1 (80-83)
ADD (00-05), OR (08-0D), ADC (10-15), SBB (18-1D), AND (20-25),
SUB (28-2D), XOR (30-35), CMP (38-3D)
CMPS (A6-A7), SCAS (AE-AF)
The last two do the same as CMP in the emulator, so em_cmp() is used.
Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/emulate.c | 161 |
1 files changed, 89 insertions, 72 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 252f28348cfe..8784916abf77 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -2512,6 +2512,72 @@ static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt) | |||
2512 | return X86EMUL_CONTINUE; | 2512 | return X86EMUL_CONTINUE; |
2513 | } | 2513 | } |
2514 | 2514 | ||
2515 | static int em_add(struct x86_emulate_ctxt *ctxt) | ||
2516 | { | ||
2517 | struct decode_cache *c = &ctxt->decode; | ||
2518 | |||
2519 | emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags); | ||
2520 | return X86EMUL_CONTINUE; | ||
2521 | } | ||
2522 | |||
2523 | static int em_or(struct x86_emulate_ctxt *ctxt) | ||
2524 | { | ||
2525 | struct decode_cache *c = &ctxt->decode; | ||
2526 | |||
2527 | emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags); | ||
2528 | return X86EMUL_CONTINUE; | ||
2529 | } | ||
2530 | |||
2531 | static int em_adc(struct x86_emulate_ctxt *ctxt) | ||
2532 | { | ||
2533 | struct decode_cache *c = &ctxt->decode; | ||
2534 | |||
2535 | emulate_2op_SrcV("adc", c->src, c->dst, ctxt->eflags); | ||
2536 | return X86EMUL_CONTINUE; | ||
2537 | } | ||
2538 | |||
2539 | static int em_sbb(struct x86_emulate_ctxt *ctxt) | ||
2540 | { | ||
2541 | struct decode_cache *c = &ctxt->decode; | ||
2542 | |||
2543 | emulate_2op_SrcV("sbb", c->src, c->dst, ctxt->eflags); | ||
2544 | return X86EMUL_CONTINUE; | ||
2545 | } | ||
2546 | |||
2547 | static int em_and(struct x86_emulate_ctxt *ctxt) | ||
2548 | { | ||
2549 | struct decode_cache *c = &ctxt->decode; | ||
2550 | |||
2551 | emulate_2op_SrcV("and", c->src, c->dst, ctxt->eflags); | ||
2552 | return X86EMUL_CONTINUE; | ||
2553 | } | ||
2554 | |||
2555 | static int em_sub(struct x86_emulate_ctxt *ctxt) | ||
2556 | { | ||
2557 | struct decode_cache *c = &ctxt->decode; | ||
2558 | |||
2559 | emulate_2op_SrcV("sub", c->src, c->dst, ctxt->eflags); | ||
2560 | return X86EMUL_CONTINUE; | ||
2561 | } | ||
2562 | |||
2563 | static int em_xor(struct x86_emulate_ctxt *ctxt) | ||
2564 | { | ||
2565 | struct decode_cache *c = &ctxt->decode; | ||
2566 | |||
2567 | emulate_2op_SrcV("xor", c->src, c->dst, ctxt->eflags); | ||
2568 | return X86EMUL_CONTINUE; | ||
2569 | } | ||
2570 | |||
2571 | static int em_cmp(struct x86_emulate_ctxt *ctxt) | ||
2572 | { | ||
2573 | struct decode_cache *c = &ctxt->decode; | ||
2574 | |||
2575 | emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags); | ||
2576 | /* Disable writeback. */ | ||
2577 | c->dst.type = OP_NONE; | ||
2578 | return X86EMUL_CONTINUE; | ||
2579 | } | ||
2580 | |||
2515 | static int em_imul(struct x86_emulate_ctxt *ctxt) | 2581 | static int em_imul(struct x86_emulate_ctxt *ctxt) |
2516 | { | 2582 | { |
2517 | struct decode_cache *c = &ctxt->decode; | 2583 | struct decode_cache *c = &ctxt->decode; |
@@ -2892,9 +2958,9 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt) | |||
2892 | #define D2bvIP(_f, _i, _p) DIP((_f) | ByteOp, _i, _p), DIP(_f, _i, _p) | 2958 | #define D2bvIP(_f, _i, _p) DIP((_f) | ByteOp, _i, _p), DIP(_f, _i, _p) |
2893 | #define I2bv(_f, _e) I((_f) | ByteOp, _e), I(_f, _e) | 2959 | #define I2bv(_f, _e) I((_f) | ByteOp, _e), I(_f, _e) |
2894 | 2960 | ||
2895 | #define D6ALU(_f) D2bv((_f) | DstMem | SrcReg | ModRM), \ | 2961 | #define I6ALU(_f, _e) I2bv((_f) | DstMem | SrcReg | ModRM, _e), \ |
2896 | D2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock), \ | 2962 | I2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock, _e), \ |
2897 | D2bv(((_f) & ~Lock) | DstAcc | SrcImm) | 2963 | I2bv(((_f) & ~Lock) | DstAcc | SrcImm, _e) |
2898 | 2964 | ||
2899 | static struct opcode group7_rm1[] = { | 2965 | static struct opcode group7_rm1[] = { |
2900 | DI(SrcNone | ModRM | Priv, monitor), | 2966 | DI(SrcNone | ModRM | Priv, monitor), |
@@ -2918,8 +2984,16 @@ static struct opcode group7_rm7[] = { | |||
2918 | DIP(SrcNone | ModRM, rdtscp, check_rdtsc), | 2984 | DIP(SrcNone | ModRM, rdtscp, check_rdtsc), |
2919 | N, N, N, N, N, N, | 2985 | N, N, N, N, N, N, |
2920 | }; | 2986 | }; |
2987 | |||
2921 | static struct opcode group1[] = { | 2988 | static struct opcode group1[] = { |
2922 | X7(D(Lock)), N | 2989 | I(Lock, em_add), |
2990 | I(Lock, em_or), | ||
2991 | I(Lock, em_adc), | ||
2992 | I(Lock, em_sbb), | ||
2993 | I(Lock, em_and), | ||
2994 | I(Lock, em_sub), | ||
2995 | I(Lock, em_xor), | ||
2996 | I(0, em_cmp), | ||
2923 | }; | 2997 | }; |
2924 | 2998 | ||
2925 | static struct opcode group1A[] = { | 2999 | static struct opcode group1A[] = { |
@@ -2991,25 +3065,25 @@ static struct gprefix pfx_0f_6f_0f_7f = { | |||
2991 | 3065 | ||
2992 | static struct opcode opcode_table[256] = { | 3066 | static struct opcode opcode_table[256] = { |
2993 | /* 0x00 - 0x07 */ | 3067 | /* 0x00 - 0x07 */ |
2994 | D6ALU(Lock), | 3068 | I6ALU(Lock, em_add), |
2995 | D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64), | 3069 | D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64), |
2996 | /* 0x08 - 0x0F */ | 3070 | /* 0x08 - 0x0F */ |
2997 | D6ALU(Lock), | 3071 | I6ALU(Lock, em_or), |
2998 | D(ImplicitOps | Stack | No64), N, | 3072 | D(ImplicitOps | Stack | No64), N, |
2999 | /* 0x10 - 0x17 */ | 3073 | /* 0x10 - 0x17 */ |
3000 | D6ALU(Lock), | 3074 | I6ALU(Lock, em_adc), |
3001 | D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64), | 3075 | D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64), |
3002 | /* 0x18 - 0x1F */ | 3076 | /* 0x18 - 0x1F */ |
3003 | D6ALU(Lock), | 3077 | I6ALU(Lock, em_sbb), |
3004 | D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64), | 3078 | D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64), |
3005 | /* 0x20 - 0x27 */ | 3079 | /* 0x20 - 0x27 */ |
3006 | D6ALU(Lock), N, N, | 3080 | I6ALU(Lock, em_and), N, N, |
3007 | /* 0x28 - 0x2F */ | 3081 | /* 0x28 - 0x2F */ |
3008 | D6ALU(Lock), N, I(ByteOp | DstAcc | No64, em_das), | 3082 | I6ALU(Lock, em_sub), N, I(ByteOp | DstAcc | No64, em_das), |
3009 | /* 0x30 - 0x37 */ | 3083 | /* 0x30 - 0x37 */ |
3010 | D6ALU(Lock), N, N, | 3084 | I6ALU(Lock, em_xor), N, N, |
3011 | /* 0x38 - 0x3F */ | 3085 | /* 0x38 - 0x3F */ |
3012 | D6ALU(0), N, N, | 3086 | I6ALU(0, em_cmp), N, N, |
3013 | /* 0x40 - 0x4F */ | 3087 | /* 0x40 - 0x4F */ |
3014 | X16(D(DstReg)), | 3088 | X16(D(DstReg)), |
3015 | /* 0x50 - 0x57 */ | 3089 | /* 0x50 - 0x57 */ |
@@ -3050,12 +3124,12 @@ static struct opcode opcode_table[256] = { | |||
3050 | I2bv(DstAcc | SrcMem | Mov | MemAbs, em_mov), | 3124 | I2bv(DstAcc | SrcMem | Mov | MemAbs, em_mov), |
3051 | I2bv(DstMem | SrcAcc | Mov | MemAbs, em_mov), | 3125 | I2bv(DstMem | SrcAcc | Mov | MemAbs, em_mov), |
3052 | I2bv(SrcSI | DstDI | Mov | String, em_mov), | 3126 | I2bv(SrcSI | DstDI | Mov | String, em_mov), |
3053 | D2bv(SrcSI | DstDI | String), | 3127 | I2bv(SrcSI | DstDI | String, em_cmp), |
3054 | /* 0xA8 - 0xAF */ | 3128 | /* 0xA8 - 0xAF */ |
3055 | D2bv(DstAcc | SrcImm), | 3129 | D2bv(DstAcc | SrcImm), |
3056 | I2bv(SrcAcc | DstDI | Mov | String, em_mov), | 3130 | I2bv(SrcAcc | DstDI | Mov | String, em_mov), |
3057 | I2bv(SrcSI | DstAcc | Mov | String, em_mov), | 3131 | I2bv(SrcSI | DstAcc | Mov | String, em_mov), |
3058 | D2bv(SrcAcc | DstDI | String), | 3132 | I2bv(SrcAcc | DstDI | String, em_cmp), |
3059 | /* 0xB0 - 0xB7 */ | 3133 | /* 0xB0 - 0xB7 */ |
3060 | X8(I(ByteOp | DstReg | SrcImm | Mov, em_mov)), | 3134 | X8(I(ByteOp | DstReg | SrcImm | Mov, em_mov)), |
3061 | /* 0xB8 - 0xBF */ | 3135 | /* 0xB8 - 0xBF */ |
@@ -3179,7 +3253,7 @@ static struct opcode twobyte_table[256] = { | |||
3179 | #undef D2bv | 3253 | #undef D2bv |
3180 | #undef D2bvIP | 3254 | #undef D2bvIP |
3181 | #undef I2bv | 3255 | #undef I2bv |
3182 | #undef D6ALU | 3256 | #undef I6ALU |
3183 | 3257 | ||
3184 | static unsigned imm_size(struct decode_cache *c) | 3258 | static unsigned imm_size(struct decode_cache *c) |
3185 | { | 3259 | { |
@@ -3715,60 +3789,27 @@ special_insn: | |||
3715 | goto twobyte_insn; | 3789 | goto twobyte_insn; |
3716 | 3790 | ||
3717 | switch (c->b) { | 3791 | switch (c->b) { |
3718 | case 0x00 ... 0x05: | ||
3719 | add: /* add */ | ||
3720 | emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags); | ||
3721 | break; | ||
3722 | case 0x06: /* push es */ | 3792 | case 0x06: /* push es */ |
3723 | rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_ES); | 3793 | rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_ES); |
3724 | break; | 3794 | break; |
3725 | case 0x07: /* pop es */ | 3795 | case 0x07: /* pop es */ |
3726 | rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_ES); | 3796 | rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_ES); |
3727 | break; | 3797 | break; |
3728 | case 0x08 ... 0x0d: | ||
3729 | or: /* or */ | ||
3730 | emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags); | ||
3731 | break; | ||
3732 | case 0x0e: /* push cs */ | 3798 | case 0x0e: /* push cs */ |
3733 | rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_CS); | 3799 | rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_CS); |
3734 | break; | 3800 | break; |
3735 | case 0x10 ... 0x15: | ||
3736 | adc: /* adc */ | ||
3737 | emulate_2op_SrcV("adc", c->src, c->dst, ctxt->eflags); | ||
3738 | break; | ||
3739 | case 0x16: /* push ss */ | 3801 | case 0x16: /* push ss */ |
3740 | rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_SS); | 3802 | rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_SS); |
3741 | break; | 3803 | break; |
3742 | case 0x17: /* pop ss */ | 3804 | case 0x17: /* pop ss */ |
3743 | rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_SS); | 3805 | rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_SS); |
3744 | break; | 3806 | break; |
3745 | case 0x18 ... 0x1d: | ||
3746 | sbb: /* sbb */ | ||
3747 | emulate_2op_SrcV("sbb", c->src, c->dst, ctxt->eflags); | ||
3748 | break; | ||
3749 | case 0x1e: /* push ds */ | 3807 | case 0x1e: /* push ds */ |
3750 | rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_DS); | 3808 | rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_DS); |
3751 | break; | 3809 | break; |
3752 | case 0x1f: /* pop ds */ | 3810 | case 0x1f: /* pop ds */ |
3753 | rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_DS); | 3811 | rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_DS); |
3754 | break; | 3812 | break; |
3755 | case 0x20 ... 0x25: | ||
3756 | and: /* and */ | ||
3757 | emulate_2op_SrcV("and", c->src, c->dst, ctxt->eflags); | ||
3758 | break; | ||
3759 | case 0x28 ... 0x2d: | ||
3760 | sub: /* sub */ | ||
3761 | emulate_2op_SrcV("sub", c->src, c->dst, ctxt->eflags); | ||
3762 | break; | ||
3763 | case 0x30 ... 0x35: | ||
3764 | xor: /* xor */ | ||
3765 | emulate_2op_SrcV("xor", c->src, c->dst, ctxt->eflags); | ||
3766 | break; | ||
3767 | case 0x38 ... 0x3d: | ||
3768 | cmp: /* cmp */ | ||
3769 | c->dst.type = OP_NONE; /* Disable writeback. */ | ||
3770 | emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags); | ||
3771 | break; | ||
3772 | case 0x40 ... 0x47: /* inc r16/r32 */ | 3813 | case 0x40 ... 0x47: /* inc r16/r32 */ |
3773 | emulate_1op("inc", c->dst, ctxt->eflags); | 3814 | emulate_1op("inc", c->dst, ctxt->eflags); |
3774 | break; | 3815 | break; |
@@ -3803,26 +3844,6 @@ special_insn: | |||
3803 | if (test_cc(c->b, ctxt->eflags)) | 3844 | if (test_cc(c->b, ctxt->eflags)) |
3804 | jmp_rel(c, c->src.val); | 3845 | jmp_rel(c, c->src.val); |
3805 | break; | 3846 | break; |
3806 | case 0x80 ... 0x83: /* Grp1 */ | ||
3807 | switch (c->modrm_reg) { | ||
3808 | case 0: | ||
3809 | goto add; | ||
3810 | case 1: | ||
3811 | goto or; | ||
3812 | case 2: | ||
3813 | goto adc; | ||
3814 | case 3: | ||
3815 | goto sbb; | ||
3816 | case 4: | ||
3817 | goto and; | ||
3818 | case 5: | ||
3819 | goto sub; | ||
3820 | case 6: | ||
3821 | goto xor; | ||
3822 | case 7: | ||
3823 | goto cmp; | ||
3824 | } | ||
3825 | break; | ||
3826 | case 0x84 ... 0x85: | 3847 | case 0x84 ... 0x85: |
3827 | test: | 3848 | test: |
3828 | emulate_2op_SrcV("test", c->src, c->dst, ctxt->eflags); | 3849 | emulate_2op_SrcV("test", c->src, c->dst, ctxt->eflags); |
@@ -3892,12 +3913,8 @@ special_insn: | |||
3892 | c->dst.bytes = c->op_bytes; | 3913 | c->dst.bytes = c->op_bytes; |
3893 | rc = emulate_popf(ctxt, ops, &c->dst.val, c->op_bytes); | 3914 | rc = emulate_popf(ctxt, ops, &c->dst.val, c->op_bytes); |
3894 | break; | 3915 | break; |
3895 | case 0xa6 ... 0xa7: /* cmps */ | ||
3896 | goto cmp; | ||
3897 | case 0xa8 ... 0xa9: /* test ax, imm */ | 3916 | case 0xa8 ... 0xa9: /* test ax, imm */ |
3898 | goto test; | 3917 | goto test; |
3899 | case 0xae ... 0xaf: /* scas */ | ||
3900 | goto cmp; | ||
3901 | case 0xc0 ... 0xc1: | 3918 | case 0xc0 ... 0xc1: |
3902 | emulate_grp2(ctxt); | 3919 | emulate_grp2(ctxt); |
3903 | break; | 3920 | break; |