]> 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 b38bd8b92aa6c84ed9a00295eeaac73bade26458..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)
 #define Src2One     (3<<29)
 #define Src2Mask    (7<<29)
 
+#define X2(x) (x), (x)
+#define X3(x) X2(x), (x)
+#define X4(x) X2(x), X2(x)
+#define X5(x) X4(x), (x)
+#define X6(x) X4(x), X2(x)
+#define X7(x) X4(x), X3(x)
+#define X8(x) X4(x), X4(x)
+#define X16(x) X8(x), X8(x)
+
 enum {
        Group1_80, Group1_81, Group1_82, Group1_83,
        Group1A, Group3_Byte, Group3, Group4, Group5, Group7,
@@ -138,16 +148,12 @@ static u32 opcode_table[256] = {
        ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
        ByteOp | DstAcc | SrcImm, DstAcc | SrcImm,
        0, 0,
-       /* 0x40 - 0x47 */
-       DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
-       /* 0x48 - 0x4F */
-       DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg,
+       /* 0x40 - 0x4F */
+       X16(DstReg),
        /* 0x50 - 0x57 */
-       SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack,
-       SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack,
+       X8(SrcReg | Stack),
        /* 0x58 - 0x5F */
-       DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack,
-       DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack,
+       X8(DstReg | Stack),
        /* 0x60 - 0x67 */
        ImplicitOps | Stack | No64, ImplicitOps | Stack | No64,
        0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,
@@ -156,12 +162,8 @@ static u32 opcode_table[256] = {
        SrcImm | Mov | Stack, 0, SrcImmByte | Mov | Stack, 0,
        DstDI | ByteOp | Mov | String, DstDI | Mov | String, /* insb, insw/insd */
        SrcSI | ByteOp | ImplicitOps | String, SrcSI | ImplicitOps | String, /* outsb, outsw/outsd */
-       /* 0x70 - 0x77 */
-       SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
-       SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
-       /* 0x78 - 0x7F */
-       SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
-       SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte,
+       /* 0x70 - 0x7F */
+       X16(SrcImmByte),
        /* 0x80 - 0x87 */
        Group | Group1_80, Group | Group1_81,
        Group | Group1_82, Group | Group1_83,
@@ -187,15 +189,9 @@ static u32 opcode_table[256] = {
        ByteOp | SrcSI | DstAcc | Mov | String, SrcSI | DstAcc | Mov | String,
        ByteOp | DstDI | String, DstDI | String,
        /* 0xB0 - 0xB7 */
-       ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov,
-       ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov,
-       ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov,
-       ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov,
+       X8(ByteOp | DstReg | SrcImm | Mov),
        /* 0xB8 - 0xBF */
-       DstReg | SrcImm | Mov, DstReg | SrcImm | Mov,
-       DstReg | SrcImm | Mov, DstReg | SrcImm | Mov,
-       DstReg | SrcImm | Mov, DstReg | SrcImm | Mov,
-       DstReg | SrcImm | Mov, DstReg | SrcImm | Mov,
+       X8(DstReg | SrcImm | Mov),
        /* 0xC0 - 0xC7 */
        ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM,
        0, ImplicitOps | Stack, 0, 0,
@@ -243,16 +239,8 @@ static u32 twobyte_table[256] = {
        ImplicitOps | Priv, 0, ImplicitOps | Priv, 0,
        ImplicitOps, ImplicitOps | Priv, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0,
-       /* 0x40 - 0x47 */
-       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
-       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
-       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
-       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
-       /* 0x48 - 0x4F */
-       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
-       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
-       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
-       DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov,
+       /* 0x40 - 0x4F */
+       X16(DstReg | SrcMem | ModRM | Mov),
        /* 0x50 - 0x5F */
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        /* 0x60 - 0x6F */
@@ -260,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 */
@@ -968,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 */
@@ -1068,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;
        }
@@ -1870,17 +1859,16 @@ static inline int emulate_grp9(struct x86_emulate_ctxt *ctxt,
                               struct x86_emulate_ops *ops)
 {
        struct decode_cache *c = &ctxt->decode;
-       u64 old = c->dst.orig_val;
+       u64 old = c->dst.orig_val64;
 
        if (((u32) (old >> 0) != (u32) c->regs[VCPU_REGS_RAX]) ||
            ((u32) (old >> 32) != (u32) c->regs[VCPU_REGS_RDX])) {
-
                c->regs[VCPU_REGS_RAX] = (u32) (old >> 0);
                c->regs[VCPU_REGS_RDX] = (u32) (old >> 32);
                ctxt->eflags &= ~EFLG_ZF;
        } else {
-               c->dst.val = ((u64)c->regs[VCPU_REGS_RCX] << 32) |
-                      (u32) c->regs[VCPU_REGS_RBX];
+               c->dst.val64 = ((u64)c->regs[VCPU_REGS_RCX] << 32) |
+                       (u32) c->regs[VCPU_REGS_RBX];
 
                ctxt->eflags |= EFLG_ZF;
        }
@@ -2616,7 +2604,7 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
                                        c->src.valptr, c->src.bytes);
                if (rc != X86EMUL_CONTINUE)
                        goto done;
-               c->src.orig_val = c->src.val;
+               c->src.orig_val64 = c->src.val64;
        }
 
        if (c->src2.type == OP_MEM) {
@@ -3029,6 +3017,8 @@ special_insn:
                if (c->modrm_reg == 5)
                        goto jump_far;
                goto grp45;
+       default:
+               goto cannot_emulate;
        }
 
 writeback:
@@ -3354,6 +3344,8 @@ twobyte_insn:
                if (rc != X86EMUL_CONTINUE)
                        goto done;
                break;
+       default:
+               goto cannot_emulate;
        }
        goto writeback;