]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/x86/kvm/emulate.c
KVM: x86 emulator: mix decode bits from opcode and group decode tables
[mv-sheeva.git] / arch / x86 / kvm / emulate.c
index 0526be187191960818e51cc86b457db63c6c5389..ef2b5af33a377ba8dd773845712047a5e79ff58d 100644 (file)
  */
 
 /* Operand sizes: 8-bit operands or specified/overridden size. */
-#define ByteOp      (1<<0)     /* 8-bit operands. */
+#define ByteOp      (1<<16)    /* 8-bit operands. */
 /* Destination operand type. */
-#define ImplicitOps (1<<1    /* Implicit in opcode. No generic decode. */
-#define DstReg      (2<<1    /* Register operand. */
-#define DstMem      (3<<1    /* Memory operand. */
-#define DstAcc      (4<<1)      /* Destination Accumulator */
-#define DstDI       (5<<1    /* Destination is in ES:(E)DI */
-#define DstMem64    (6<<1    /* 64bit memory operand */
-#define DstMask     (7<<1)
+#define ImplicitOps (1<<17)    /* Implicit in opcode. No generic decode. */
+#define DstReg      (2<<17)    /* Register operand. */
+#define DstMem      (3<<17)    /* Memory operand. */
+#define DstAcc      (4<<17)    /* Destination Accumulator */
+#define DstDI       (5<<17)    /* Destination is in ES:(E)DI */
+#define DstMem64    (6<<17)    /* 64bit memory operand */
+#define DstMask     (7<<17)
 /* Source operand type. */
 #define SrcNone     (0<<4)     /* No source operand. */
 #define SrcImplicit (0<<4)     /* Source operand is implicit in the opcode. */
@@ -82,8 +82,9 @@
 #define Stack       (1<<13)     /* Stack instruction (push/pop) */
 #define Group       (1<<14)     /* Bits 3:5 of modrm byte extend opcode */
 #define GroupDual   (1<<15)     /* Alternate decoding of mod == 3 */
-#define GroupMask   0xff        /* Group number stored in bits 0:7 */
+#define GroupMask   0x0f        /* Group number stored in bits 0:3 */
 /* Misc flags */
+#define Undefined   (1<<25) /* No Such Instruction */
 #define Lock        (1<<26) /* lock prefix is allowed for the instruction */
 #define Priv        (1<<27) /* instruction generates #GP if current CPL != 0 */
 #define No64       (1<<28)
@@ -247,8 +248,7 @@ static u32 twobyte_table[256] = {
        /* 0x70 - 0x7F */
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        /* 0x80 - 0x8F */
-       SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm,
-       SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm,
+       X16(SrcImm),
        /* 0x90 - 0x9F */
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        /* 0xA0 - 0xA7 */
@@ -955,7 +955,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
        struct decode_cache *c = &ctxt->decode;
        int rc = X86EMUL_CONTINUE;
        int mode = ctxt->mode;
-       int def_op_bytes, def_ad_bytes, group;
+       int def_op_bytes, def_ad_bytes, group, dual;
 
 
        /* we cannot decode insn before we complete previous rep insn */
@@ -1055,18 +1055,20 @@ done_prefixes:
 
        if (c->d & Group) {
                group = c->d & GroupMask;
+               dual = c->d & GroupDual;
                c->modrm = insn_fetch(u8, 1, c->eip);
                --c->eip;
 
                group = (group << 3) + ((c->modrm >> 3) & 7);
-               if ((c->d & GroupDual) && (c->modrm >> 6) == 3)
-                       c->d = group2_table[group];
+               c->d &= ~(Group | GroupDual | GroupMask);
+               if (dual && (c->modrm >> 6) == 3)
+                       c->d |= group2_table[group];
                else
-                       c->d = group_table[group];
+                       c->d |= group_table[group];
        }
 
        /* Unrecognised? */
-       if (c->d == 0) {
+       if (c->d == 0 || (c->d & Undefined)) {
                DPRINTF("Cannot emulate %02x\n", c->b);
                return -1;
        }