KVM: x86 emulator: Use opcode::execute for Group 1, CMPS and SCAS
authorTakuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Sat, 23 Apr 2011 09:48:02 +0000 (18:48 +0900)
committerAvi Kivity <avi@redhat.com>
Sun, 22 May 2011 12:39:40 +0000 (08:39 -0400)
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>
arch/x86/kvm/emulate.c

index 252f28348cfeb8c0619433e62a035097167ee54f..8784916abf77d93b5daa190f2ba5676a1fa60c97 100644 (file)
@@ -2512,6 +2512,72 @@ static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
        return X86EMUL_CONTINUE;
 }
 
+static int em_add(struct x86_emulate_ctxt *ctxt)
+{
+       struct decode_cache *c = &ctxt->decode;
+
+       emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags);
+       return X86EMUL_CONTINUE;
+}
+
+static int em_or(struct x86_emulate_ctxt *ctxt)
+{
+       struct decode_cache *c = &ctxt->decode;
+
+       emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags);
+       return X86EMUL_CONTINUE;
+}
+
+static int em_adc(struct x86_emulate_ctxt *ctxt)
+{
+       struct decode_cache *c = &ctxt->decode;
+
+       emulate_2op_SrcV("adc", c->src, c->dst, ctxt->eflags);
+       return X86EMUL_CONTINUE;
+}
+
+static int em_sbb(struct x86_emulate_ctxt *ctxt)
+{
+       struct decode_cache *c = &ctxt->decode;
+
+       emulate_2op_SrcV("sbb", c->src, c->dst, ctxt->eflags);
+       return X86EMUL_CONTINUE;
+}
+
+static int em_and(struct x86_emulate_ctxt *ctxt)
+{
+       struct decode_cache *c = &ctxt->decode;
+
+       emulate_2op_SrcV("and", c->src, c->dst, ctxt->eflags);
+       return X86EMUL_CONTINUE;
+}
+
+static int em_sub(struct x86_emulate_ctxt *ctxt)
+{
+       struct decode_cache *c = &ctxt->decode;
+
+       emulate_2op_SrcV("sub", c->src, c->dst, ctxt->eflags);
+       return X86EMUL_CONTINUE;
+}
+
+static int em_xor(struct x86_emulate_ctxt *ctxt)
+{
+       struct decode_cache *c = &ctxt->decode;
+
+       emulate_2op_SrcV("xor", c->src, c->dst, ctxt->eflags);
+       return X86EMUL_CONTINUE;
+}
+
+static int em_cmp(struct x86_emulate_ctxt *ctxt)
+{
+       struct decode_cache *c = &ctxt->decode;
+
+       emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
+       /* Disable writeback. */
+       c->dst.type = OP_NONE;
+       return X86EMUL_CONTINUE;
+}
+
 static int em_imul(struct x86_emulate_ctxt *ctxt)
 {
        struct decode_cache *c = &ctxt->decode;
@@ -2892,9 +2958,9 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
 #define D2bvIP(_f, _i, _p) DIP((_f) | ByteOp, _i, _p), DIP(_f, _i, _p)
 #define I2bv(_f, _e)  I((_f) | ByteOp, _e), I(_f, _e)
 
-#define D6ALU(_f) D2bv((_f) | DstMem | SrcReg | ModRM),                        \
-               D2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock),         \
-               D2bv(((_f) & ~Lock) | DstAcc | SrcImm)
+#define I6ALU(_f, _e) I2bv((_f) | DstMem | SrcReg | ModRM, _e),                \
+               I2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock, _e),     \
+               I2bv(((_f) & ~Lock) | DstAcc | SrcImm, _e)
 
 static struct opcode group7_rm1[] = {
        DI(SrcNone | ModRM | Priv, monitor),
@@ -2918,8 +2984,16 @@ static struct opcode group7_rm7[] = {
        DIP(SrcNone | ModRM, rdtscp, check_rdtsc),
        N, N, N, N, N, N,
 };
+
 static struct opcode group1[] = {
-       X7(D(Lock)), N
+       I(Lock, em_add),
+       I(Lock, em_or),
+       I(Lock, em_adc),
+       I(Lock, em_sbb),
+       I(Lock, em_and),
+       I(Lock, em_sub),
+       I(Lock, em_xor),
+       I(0, em_cmp),
 };
 
 static struct opcode group1A[] = {
@@ -2991,25 +3065,25 @@ static struct gprefix pfx_0f_6f_0f_7f = {
 
 static struct opcode opcode_table[256] = {
        /* 0x00 - 0x07 */
-       D6ALU(Lock),
+       I6ALU(Lock, em_add),
        D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
        /* 0x08 - 0x0F */
-       D6ALU(Lock),
+       I6ALU(Lock, em_or),
        D(ImplicitOps | Stack | No64), N,
        /* 0x10 - 0x17 */
-       D6ALU(Lock),
+       I6ALU(Lock, em_adc),
        D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
        /* 0x18 - 0x1F */
-       D6ALU(Lock),
+       I6ALU(Lock, em_sbb),
        D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64),
        /* 0x20 - 0x27 */
-       D6ALU(Lock), N, N,
+       I6ALU(Lock, em_and), N, N,
        /* 0x28 - 0x2F */
-       D6ALU(Lock), N, I(ByteOp | DstAcc | No64, em_das),
+       I6ALU(Lock, em_sub), N, I(ByteOp | DstAcc | No64, em_das),
        /* 0x30 - 0x37 */
-       D6ALU(Lock), N, N,
+       I6ALU(Lock, em_xor), N, N,
        /* 0x38 - 0x3F */
-       D6ALU(0), N, N,
+       I6ALU(0, em_cmp), N, N,
        /* 0x40 - 0x4F */
        X16(D(DstReg)),
        /* 0x50 - 0x57 */
@@ -3050,12 +3124,12 @@ static struct opcode opcode_table[256] = {
        I2bv(DstAcc | SrcMem | Mov | MemAbs, em_mov),
        I2bv(DstMem | SrcAcc | Mov | MemAbs, em_mov),
        I2bv(SrcSI | DstDI | Mov | String, em_mov),
-       D2bv(SrcSI | DstDI | String),
+       I2bv(SrcSI | DstDI | String, em_cmp),
        /* 0xA8 - 0xAF */
        D2bv(DstAcc | SrcImm),
        I2bv(SrcAcc | DstDI | Mov | String, em_mov),
        I2bv(SrcSI | DstAcc | Mov | String, em_mov),
-       D2bv(SrcAcc | DstDI | String),
+       I2bv(SrcAcc | DstDI | String, em_cmp),
        /* 0xB0 - 0xB7 */
        X8(I(ByteOp | DstReg | SrcImm | Mov, em_mov)),
        /* 0xB8 - 0xBF */
@@ -3179,7 +3253,7 @@ static struct opcode twobyte_table[256] = {
 #undef D2bv
 #undef D2bvIP
 #undef I2bv
-#undef D6ALU
+#undef I6ALU
 
 static unsigned imm_size(struct decode_cache *c)
 {
@@ -3715,60 +3789,27 @@ special_insn:
                goto twobyte_insn;
 
        switch (c->b) {
-       case 0x00 ... 0x05:
-             add:              /* add */
-               emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags);
-               break;
        case 0x06:              /* push es */
                rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_ES);
                break;
        case 0x07:              /* pop es */
                rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_ES);
                break;
-       case 0x08 ... 0x0d:
-             or:               /* or */
-               emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags);
-               break;
        case 0x0e:              /* push cs */
                rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_CS);
                break;
-       case 0x10 ... 0x15:
-             adc:              /* adc */
-               emulate_2op_SrcV("adc", c->src, c->dst, ctxt->eflags);
-               break;
        case 0x16:              /* push ss */
                rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_SS);
                break;
        case 0x17:              /* pop ss */
                rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_SS);
                break;
-       case 0x18 ... 0x1d:
-             sbb:              /* sbb */
-               emulate_2op_SrcV("sbb", c->src, c->dst, ctxt->eflags);
-               break;
        case 0x1e:              /* push ds */
                rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_DS);
                break;
        case 0x1f:              /* pop ds */
                rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_DS);
                break;
-       case 0x20 ... 0x25:
-             and:              /* and */
-               emulate_2op_SrcV("and", c->src, c->dst, ctxt->eflags);
-               break;
-       case 0x28 ... 0x2d:
-             sub:              /* sub */
-               emulate_2op_SrcV("sub", c->src, c->dst, ctxt->eflags);
-               break;
-       case 0x30 ... 0x35:
-             xor:              /* xor */
-               emulate_2op_SrcV("xor", c->src, c->dst, ctxt->eflags);
-               break;
-       case 0x38 ... 0x3d:
-             cmp:              /* cmp */
-               c->dst.type = OP_NONE; /* Disable writeback. */
-               emulate_2op_SrcV("cmp", c->src, c->dst, ctxt->eflags);
-               break;
        case 0x40 ... 0x47: /* inc r16/r32 */
                emulate_1op("inc", c->dst, ctxt->eflags);
                break;
@@ -3803,26 +3844,6 @@ special_insn:
                if (test_cc(c->b, ctxt->eflags))
                        jmp_rel(c, c->src.val);
                break;
-       case 0x80 ... 0x83:     /* Grp1 */
-               switch (c->modrm_reg) {
-               case 0:
-                       goto add;
-               case 1:
-                       goto or;
-               case 2:
-                       goto adc;
-               case 3:
-                       goto sbb;
-               case 4:
-                       goto and;
-               case 5:
-                       goto sub;
-               case 6:
-                       goto xor;
-               case 7:
-                       goto cmp;
-               }
-               break;
        case 0x84 ... 0x85:
        test:
                emulate_2op_SrcV("test", c->src, c->dst, ctxt->eflags);
@@ -3892,12 +3913,8 @@ special_insn:
                c->dst.bytes = c->op_bytes;
                rc = emulate_popf(ctxt, ops, &c->dst.val, c->op_bytes);
                break;
-       case 0xa6 ... 0xa7:     /* cmps */
-               goto cmp;
        case 0xa8 ... 0xa9:     /* test ax, imm */
                goto test;
-       case 0xae ... 0xaf:     /* scas */
-               goto cmp;
        case 0xc0 ... 0xc1:
                emulate_grp2(ctxt);
                break;